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}