You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by ca...@apache.org on 2017/08/16 23:10:11 UTC

incubator-rya git commit: RYA-297 Added owl:equivalentClass inference. Closes #184.

Repository: incubator-rya
Updated Branches:
  refs/heads/master 30475023d -> 85caccf41


RYA-297 Added owl:equivalentClass inference. Closes #184.

If A and B are equivalent classes, then A is a subclass of B and B is a subclass of A. Handled the same way as owl:equivalentProperty.


Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/85caccf4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/85caccf4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/85caccf4

Branch: refs/heads/master
Commit: 85caccf410ac53a8f6b21ef8bab9949cfa21728a
Parents: 3047502
Author: Jesse Hatfield <je...@parsons.com>
Authored: Tue Jul 25 17:08:31 2017 -0400
Committer: Caleb Meier <ca...@parsons.com>
Committed: Wed Aug 16 16:09:13 2017 -0700

----------------------------------------------------------------------
 .../inference/InferenceEngine.java              | 84 +++++++++-----------
 .../inference/SubClassOfVisitor.java            |  2 +-
 .../inference/InferenceEngineTest.java          | 79 ++++++++++++++++++
 .../rdftriplestore/inference/InferenceIT.java   | 37 +++++++++
 4 files changed, 156 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/85caccf4/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
index 2c2ba62..d0ff51b 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/InferenceEngine.java
@@ -127,22 +127,12 @@ public class InferenceEngine {
     public void refreshGraph() throws InferenceEngineException {
         ValueFactory vf = ValueFactoryImpl.getInstance();
         try {
+            CloseableIteration<Statement, QueryEvaluationException> iter;
             //get all subclassof
             Graph graph = TinkerGraph.open();
-            CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null,
-                    RDFS.SUBCLASSOF, null, conf);
-            try {
-                while (iter.hasNext()) {
-                    String edgeName = RDFS.SUBCLASSOF.stringValue();
-                    Statement st = iter.next();
-                    addStatementEdge(graph, edgeName, st);
-                }
-            } finally {
-                if (iter != null) {
-                    iter.close();
-                }
-            }
-
+            addPredicateEdges(RDFS.SUBCLASSOF, Direction.OUT, graph, RDFS.SUBCLASSOF.stringValue());
+            //equivalentClass is the same as subClassOf both ways
+            addPredicateEdges(OWL.EQUIVALENTCLASS, Direction.BOTH, graph, RDFS.SUBCLASSOF.stringValue());
             // Add unions to the subclass graph: if c owl:unionOf LIST(c1, c2, ... cn), then any
             // instances of c1, c2, ... or cn are also instances of c, meaning c is a superclass
             // of all the rest.
@@ -189,41 +179,12 @@ public class InferenceEngine {
                     iter.close();
                 }
             }
-
             subClassOfGraph = graph; //TODO: Should this be synchronized?
 
             graph = TinkerGraph.open();
-
-            iter = RyaDAOHelper.query(ryaDAO, null,
-                    RDFS.SUBPROPERTYOF, null, conf);
-            try {
-                while (iter.hasNext()) {
-                    String edgeName = RDFS.SUBPROPERTYOF.stringValue();
-                    Statement st = iter.next();
-                    addStatementEdge(graph, edgeName, st);
-                }
-            } finally {
-                if (iter != null) {
-                    iter.close();
-                }
-            }
-
+            addPredicateEdges(RDFS.SUBPROPERTYOF, Direction.OUT, graph, RDFS.SUBPROPERTYOF.stringValue());
             //equiv property really is the same as a subPropertyOf both ways
-            iter = RyaDAOHelper.query(ryaDAO, null, OWL.EQUIVALENTPROPERTY, null, conf);
-            try {
-                while (iter.hasNext()) {
-                    String edgeName = RDFS.SUBPROPERTYOF.stringValue();
-                    Statement st = iter.next();
-                    addStatementEdge(graph, edgeName, st);
-                    //reverse is also true
-                    addStatementEdge(graph, edgeName, new StatementImpl((Resource) st.getObject(), st.getPredicate(), st.getSubject()));
-                }
-            } finally {
-                if (iter != null) {
-                    iter.close();
-                }
-            }
-
+            addPredicateEdges(OWL.EQUIVALENTPROPERTY, Direction.BOTH, graph, RDFS.SUBPROPERTYOF.stringValue());
             subPropertyOfGraph = graph; //TODO: Should this be synchronized?
 
             iter = RyaDAOHelper.query(ryaDAO, null, RDF.TYPE, OWL.SYMMETRICPROPERTY, conf);
@@ -417,6 +378,39 @@ public class InferenceEngine {
         }
     }
 
+    /**
+     * Query for all triples involving a given predicate and add corresponding edges to a
+     * {@link Graph} in one or both directions.
+     * @param predicate Find all connections via this predicate URI
+     * @param dir Direction of interest: for a matching triple, if {@link Direction#OUT} add an edge
+     *      from subject to object; if {@link Direction#IN} add an edge from object to subject;
+     *      if {@link Direction#BOTH} add both.
+     * @param graph A TinkerPop graph
+     * @param edgeName Label that will be given to all added edges
+     * @throws QueryEvaluationException
+     */
+    private void addPredicateEdges(URI predicate, Direction dir, Graph graph, String edgeName)
+            throws QueryEvaluationException {
+        CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO,
+                null, predicate, null, conf);
+        try {
+            while (iter.hasNext()) {
+                Statement st = iter.next();
+                if (Direction.OUT.equals(dir) || Direction.BOTH.equals(dir)) {
+                    addStatementEdge(graph, edgeName, st);
+                }
+                if (Direction.IN.equals(dir) || Direction.BOTH.equals(dir)) {
+                    addStatementEdge(graph, edgeName, new StatementImpl((Resource) st.getObject(),
+                            st.getPredicate(), st.getSubject()));
+                }
+            }
+        } finally {
+            if (iter != null) {
+                iter.close();
+            }
+        }
+    }
+
     private void refreshPropertyRestrictions() throws QueryEvaluationException {
         // Get a set of all property restrictions of any type
         CloseableIteration<Statement, QueryEvaluationException> iter = RyaDAOHelper.query(ryaDAO, null, OWL.ONPROPERTY, null, conf);

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/85caccf4/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
----------------------------------------------------------------------
diff --git a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
index 89d3b7b..7fb1b4a 100644
--- a/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
+++ b/sail/src/main/java/org/apache/rya/rdftriplestore/inference/SubClassOfVisitor.java
@@ -68,7 +68,7 @@ public class SubClassOfVisitor extends AbstractInferVisitor {
                 String s = UUID.randomUUID().toString();
                 Var typeVar = new Var(s);
                 FixedStatementPattern fsp = new FixedStatementPattern(typeVar, new Var("c-" + s, RDFS.SUBCLASSOF), objVar, conVar);
-                fsp.statements.add(new NullableStatementImpl(subclassof_uri, RDFS.SUBCLASSOF, subclassof_uri));
+                parents.add(subclassof_uri);
                 for (URI u : parents) {
                     fsp.statements.add(new NullableStatementImpl(u, RDFS.SUBCLASSOF, subclassof_uri));
                 }

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/85caccf4/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
----------------------------------------------------------------------
diff --git a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
index 05adbc8..58aeb88 100644
--- a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
+++ b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceEngineTest.java
@@ -18,6 +18,7 @@ package org.apache.rya.rdftriplestore.inference;
  * under the License.
  */
 
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -86,6 +87,84 @@ public class InferenceEngineTest extends TestCase {
     }
 
     @Test
+    public void testSubClassGraph() throws Exception {
+        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:A> rdfs:subClassOf <urn:C> . \n"
+                + "  <urn:B> rdfs:subClassOf <urn:C> . \n"
+                + "  <urn:C> rdfs:subClassOf <urn:D> . \n"
+                + "  <urn:E> owl:equivalentClass <urn:D> . \n"
+                + "  <urn:E> rdfs:subClassOf <urn:G> . \n"
+                + "  <urn:Z> a owl:Class . \n"
+                + "  <urn:F> owl:equivalentClass <urn:G> . \n"
+                + "}}";
+        conn.prepareUpdate(QueryLanguage.SPARQL, insert).execute();
+        inferenceEngine.refreshGraph();
+        Graph graph = inferenceEngine.getSubClassOfGraph();
+        URI a = vf.createURI("urn:A");
+        URI b = vf.createURI("urn:B");
+        URI c = vf.createURI("urn:C");
+        URI d = vf.createURI("urn:D");
+        URI e = vf.createURI("urn:E");
+        URI f = vf.createURI("urn:F");
+        URI g = vf.createURI("urn:G");
+        URI z = vf.createURI("urn:Z");
+        URI missing = vf.createURI("urn:Missing");
+        Set<URI> empty = new HashSet<>();
+        Set<URI> belowLevel2 = new HashSet<>(Arrays.asList(new URI[] { a, b }));
+        Set<URI> belowLevel3 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e }));
+        Set<URI> belowLevel4 = new HashSet<>(Arrays.asList(new URI[] { a, b, c, d, e, f, g }));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, a));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, b));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, z));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, missing));
+        Assert.assertEquals(belowLevel2, inferenceEngine.findParents(graph, c));
+        Assert.assertEquals(belowLevel3, inferenceEngine.findParents(graph, d));
+        Assert.assertEquals(belowLevel3, inferenceEngine.findParents(graph, e));
+        Assert.assertEquals(belowLevel4, inferenceEngine.findParents(graph, f));
+        Assert.assertEquals(belowLevel4, inferenceEngine.findParents(graph, g));
+    }
+
+    @Test
+    public void testSubPropertyGraph() throws Exception {
+        String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:p> rdfs:subPropertyOf <urn:q> . \n"
+                + "  <urn:p> rdfs:subPropertyOf <urn:r> . \n"
+                + "  <urn:r> owl:equivalentProperty <urn:s> . \n"
+                + "  <urn:q> rdfs:subPropertyOf <urn:t> . \n"
+                + "  <urn:t> rdfs:subPropertyOf <urn:u> . \n"
+                + "  <urn:s> rdfs:subPropertyOf <urn:u> . \n"
+                + "  <urn:v> owl:equivalentProperty <urn:u> . \n"
+                + "  <urn:w> a owl:FunctionalProperty . \n"
+                + "}}";
+        conn.prepareUpdate(QueryLanguage.SPARQL, insert).execute();
+        inferenceEngine.refreshGraph();
+        Graph graph = inferenceEngine.getSubPropertyOfGraph();
+        URI p = vf.createURI("urn:p");
+        URI q = vf.createURI("urn:q");
+        URI r = vf.createURI("urn:r");
+        URI s = vf.createURI("urn:s");
+        URI t = vf.createURI("urn:t");
+        URI u = vf.createURI("urn:u");
+        URI v = vf.createURI("urn:v");
+        URI w = vf.createURI("urn:w");
+        URI missing = vf.createURI("urn:Missing");
+        Set<URI> empty = new HashSet<>();
+        Set<URI> belowQ = new HashSet<>(Arrays.asList(new URI[] { p }));
+        Set<URI> belowR = new HashSet<>(Arrays.asList(new URI[] { p, r, s }));
+        Set<URI> belowT = new HashSet<>(Arrays.asList(new URI[] { p, q }));
+        Set<URI> belowU = new HashSet<>(Arrays.asList(new URI[] { p, q, r, s, t, u, v }));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, p));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, w));
+        Assert.assertEquals(empty, inferenceEngine.findParents(graph, missing));
+        Assert.assertEquals(belowQ, inferenceEngine.findParents(graph, q));
+        Assert.assertEquals(belowR, inferenceEngine.findParents(graph, r));
+        Assert.assertEquals(belowR, inferenceEngine.findParents(graph, s));
+        Assert.assertEquals(belowT, inferenceEngine.findParents(graph, t));
+        Assert.assertEquals(belowU, inferenceEngine.findParents(graph, u));
+        Assert.assertEquals(belowU, inferenceEngine.findParents(graph, v));
+    }
+
+    @Test
     public void testHasValueGivenProperty() throws Exception {
         String insert = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:Biped> owl:onProperty <urn:walksUsingLegs>  . \n"

http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/85caccf4/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
----------------------------------------------------------------------
diff --git a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
index d3f2faf..6824751 100644
--- a/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
+++ b/sail/src/test/java/org/apache/rya/rdftriplestore/inference/InferenceIT.java
@@ -35,6 +35,7 @@ import org.junit.Test;
 import org.openrdf.model.Value;
 import org.openrdf.model.ValueFactory;
 import org.openrdf.model.impl.ValueFactoryImpl;
+import org.openrdf.model.vocabulary.FOAF;
 import org.openrdf.query.BindingSet;
 import org.openrdf.query.QueryLanguage;
 import org.openrdf.query.QueryResultHandlerException;
@@ -105,6 +106,42 @@ public class InferenceIT extends TestCase {
     }
 
     @Test
+    public void testSubClassInferenceQuery() throws Exception {
+        final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:Agent> owl:equivalentClass <http://dbpedia.org/ontology/Agent> . \n"
+                + "  <urn:Person> rdfs:subClassOf <urn:Agent> . \n"
+                + "  [ owl:equivalentClass <http://schema.org/Person> ] rdfs:subClassOf <http://dbpedia.org/ontology/Agent> . \n"
+                + "  <" + FOAF.PERSON.stringValue() + "> owl:equivalentClass <http://dbpedia.org/ontology/Person> . \n"
+                + "  <" + FOAF.PERSON.stringValue() + "> owl:equivalentClass <urn:Person> . \n"
+                + "  <http://dbpedia.org/ontology/Engineer> rdfs:subClassOf <http://dbpedia.org/ontology/Person> . \n"
+                + "  <http://dbpedia.org/ontology/Engineer> rdfs:subClassOf <http://example.org/Person> . \n"
+                + "  <http://dbpedia.org/ontology/Engineer> owl:equivalentClass <http://www.wikidata.org/entity/Q81096> . \n"
+                + "}}";
+        final String instances = "INSERT DATA { GRAPH <http://updated/test> {\n"
+                + "  <urn:Alice> a <http://schema.org/Person> . \n"
+                + "  <urn:Bob> a <http://www.wikidata.org/entity/Q81096> . \n"
+                + "  <urn:Carol> a <http://example.org/Person> . \n"
+                + "  <urn:Dan> a <http://example.org/Engineer> . \n"
+                + "  <urn:Eve> a <urn:Agent> . \n"
+                + "}}";
+        final String query = "SELECT ?x { GRAPH <http://updated/test> { ?x a <urn:Agent> } } \n";
+        conn.prepareUpdate(QueryLanguage.SPARQL, ontology).execute();
+        inferenceEngine.refreshGraph();
+        conn.prepareUpdate(QueryLanguage.SPARQL, instances).execute();
+        conn.prepareTupleQuery(QueryLanguage.SPARQL, query).evaluate(resultHandler);
+        Set<Value> expected = new HashSet<>();
+        expected.add(vf.createURI("urn:Alice"));
+        expected.add(vf.createURI("urn:Bob"));
+        expected.add(vf.createURI("urn:Eve"));
+        Set<Value> returned = new HashSet<>();
+        for (BindingSet bs : solutions) {
+            returned.add(bs.getBinding("x").getValue());
+        }
+        Assert.assertEquals(expected, returned);
+        Assert.assertEquals(expected.size(), solutions.size());
+    }
+
+    @Test
     public void testHasValueTypeQuery() throws Exception {
         final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n"
                 + "  <urn:Biped> owl:onProperty <urn:walksOnLegs>  ; owl:hasValue \"2\"^^<xsd:integer> . \n"