001package org.dllearner.utilities.graph; 002 003import java.io.File; 004import java.util.*; 005import java.util.function.Function; 006import java.util.stream.Collectors; 007import java.util.stream.Stream; 008 009import org.jgrapht.Graph; 010import org.jgrapht.GraphPath; 011import org.jgrapht.graph.DefaultEdge; 012import org.jgrapht.graph.GraphWalk; 013import org.jgrapht.graph.builder.GraphTypeBuilder; 014import org.jgrapht.traverse.RandomWalkIterator; 015import org.semanticweb.owlapi.apibinding.OWLManager; 016import org.semanticweb.owlapi.dlsyntax.renderer.DLSyntaxObjectRenderer; 017import org.semanticweb.owlapi.io.ToStringRenderer; 018import org.semanticweb.owlapi.model.*; 019import static org.apache.jena.sys.JenaSystem.forEach; 020 021/** 022 * Utility methods working on graph level by means of JGraphT API. 023 * 024 * @author Lorenz Buehmann 025 */ 026public class GraphUtils { 027 028 /** 029 * Maps the ABox of an OWL ontology to a directed graph. 030 * <p> 031 * It just uses object property assertions to build the graph of the individuals. Edges are not labeled. 032 * 033 * @param ont the ontology 034 * @return a directed graph with labeled vertices 035 */ 036 public static Graph<OWLIndividual, DefaultEdge> aboxToGraph(OWLOntology ont) { 037 038 Set<OWLObjectPropertyAssertionAxiom> axioms = ont.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION); 039 040 Graph<OWLIndividual, DefaultEdge> g = GraphTypeBuilder 041 .directed() 042 .allowingMultipleEdges(true) 043 .edgeClass(DefaultEdge.class) 044 .vertexClass(OWLIndividual.class) 045 .buildGraph(); 046 047 axioms.forEach(ax -> g.addEdge(ax.getSubject(), ax.getObject())); 048 049 return g; 050 } 051 052 /** 053 * Maps the ABox of an OWL ontology to a labeled directed graph. 054 * <p> 055 * It just uses object property assertions to build the graph of the individuals. Edges are labeled with the 056 * object property. 057 * 058 * @param ont the ontology 059 * @return a directed graph with labeled vertices and edges 060 */ 061 public static Graph<OWLIndividual, OWLPropertyEdge> aboxToLabeledGraph(OWLOntology ont) { 062 063 Set<OWLObjectPropertyAssertionAxiom> axioms = ont.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION); 064 065 Graph<OWLIndividual, OWLPropertyEdge> g = GraphTypeBuilder 066 .directed() 067 .allowingMultipleEdges(true) 068 .vertexClass(OWLIndividual.class) 069 .edgeClass(OWLPropertyEdge.class) 070 .buildGraph(); 071 072 axioms.forEach(ax -> { 073 g.addVertex(ax.getSubject()); 074 g.addVertex(ax.getObject()); 075 g.addEdge(ax.getSubject(), ax.getObject(), new OWLPropertyEdge(ax.getProperty())); 076 }); 077 078 return g; 079 } 080 081 private static TypedOWLIndividual toTypedIndividual(OWLIndividual ind, OWLOntology ont) { 082 Set<OWLClass> types = ont.getClassAssertionAxioms(ind).stream() 083 .map(OWLClassAssertionAxiom::getClassExpression) 084 .filter(ce -> !ce.isAnonymous()) 085 .map(OWLClassExpression::asOWLClass) 086 .collect(Collectors.toSet()); 087 088 return new TypedOWLIndividual(ind, types); 089 } 090 091 /** 092 * Maps the ABox of an OWL ontology to a labeled directed graph. 093 * <p> 094 * It just uses object property assertions to build the graph of the individuals. 095 * Edges are labeled with the object property. 096 * Vertices are annotated with the types of the individuals. 097 * 098 * @param ont the ontology 099 * @return a directed graph with labeled and type annotated vertices as well as labeled edges 100 */ 101 public static Graph<TypedOWLIndividual, OWLPropertyEdge> aboxToLabeledGraphWithTypes(OWLOntology ont) { 102 103 Set<OWLObjectPropertyAssertionAxiom> axioms = ont.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION); 104 105 Graph<TypedOWLIndividual, OWLPropertyEdge> g = GraphTypeBuilder 106 .directed() 107 .allowingMultipleEdges(true) 108 .vertexClass(TypedOWLIndividual.class) 109 .edgeClass(OWLPropertyEdge.class) 110 .buildGraph(); 111 112 // we cache the created vertices because computation of types can be expensive, 113 // at least when inference would be used 114 Map<OWLIndividual, TypedOWLIndividual> cache = new HashMap<>(); 115 116 axioms.forEach(ax -> { 117 // process the subject 118 OWLIndividual ind = ax.getSubject(); 119 TypedOWLIndividual source = cache.computeIfAbsent(ind, i -> toTypedIndividual(i, ont)); 120 121 // and the object 122 ind = ax.getObject(); 123 TypedOWLIndividual target = cache.computeIfAbsent(ind, i -> toTypedIndividual(i, ont)); 124 125 g.addVertex(source); 126 g.addVertex(target); 127 g.addEdge(source, target, new OWLPropertyEdge(ax.getProperty())); 128 }); 129 130 cache.clear(); 131 132 return g; 133 } 134 135 136 public static void main(String[] args) throws OWLOntologyCreationException { 137 ToStringRenderer.getInstance().setRenderer(new DLSyntaxObjectRenderer()); 138 139 OWLOntology ont = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(new File("/home/user/work/datasets/poker/poker_straight_flush_p5-n347.owl")); 140 OWLClass hand = OWLManager.getOWLDataFactory().getOWLClass(IRI.create("http://dl-learner.org/examples/uci/poker#Hand")); 141 final String targetClass = "straight_flush"; 142 143 Graph<TypedOWLIndividual, OWLPropertyEdge> g = aboxToLabeledGraphWithTypes(ont); 144 145 Set<TypedOWLIndividual> startNodes = ont.getIndividualsInSignature().stream() 146 .filter(ind -> ont.getAnnotationAssertionAxioms(ind.asOWLNamedIndividual().getIRI()).stream() 147 .map(OWLAnnotationAssertionAxiom::annotationValue) 148 .map(OWLAnnotationValue::asLiteral) 149 .anyMatch(lit -> lit.isPresent() && lit.get().getLiteral().equals(targetClass))) 150 .map(TypedOWLIndividual::new) 151 .limit(1) 152 .collect(Collectors.toSet()); 153 154 int maxPathLength = 10; 155 156 startNodes.forEach(node -> { 157 158 // compute all path up to length 159 List<GraphPath<TypedOWLIndividual, OWLPropertyEdge>> paths = new AllPaths<>(g).getAllPaths(node, true, maxPathLength); 160 161 // show all paths 162 paths.forEach(System.out::println); 163 164 // show all paths but just the edges 165 List<List<OWLObjectPropertyExpression>> pathEdges = paths.stream() 166 .map(path -> path.getEdgeList().stream().map(LabeledEdge::getLabel).collect(Collectors.toList())) 167 .collect(Collectors.toList()); 168// pathEdges.forEach(System.out::println); 169 170 // show just the distinct list of the edge sequences 171 List<List<OWLObjectPropertyExpression>> pathEdgesDistinct = new ArrayList<>(new HashSet<>(pathEdges)); 172 173 Comparator<List<OWLObjectPropertyExpression>> c = Comparator.<List<OWLObjectPropertyExpression>>comparingInt(List::size).thenComparing(Object::toString); 174 175 Collections.sort(pathEdgesDistinct, c); 176 pathEdgesDistinct.forEach(System.out::println); 177 178 }); 179 } 180 181 182}