Repository: incubator-rya Updated Branches: refs/heads/master 41c1e9115 -> 637e3ff35
RYA-293 Added owl:unionOf inference. Closes #180. If A is the union of B and C, then B and C are subclasses of A. Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/637e3ff3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/637e3ff3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/637e3ff3 Branch: refs/heads/master Commit: 637e3ff3501608f5879633f1a38e3c8bd1cb3751 Parents: 41c1e91 Author: Jesse Hatfield <[email protected]> Authored: Thu Jul 20 18:48:24 2017 -0400 Committer: Caleb Meier <[email protected]> Committed: Wed Aug 16 06:40:13 2017 -0700 ---------------------------------------------------------------------- .../inference/InferenceEngine.java | 49 +++++++++++++++++++- .../inference/InferenceEngineTest.java | 31 +++++++++++++ .../rdftriplestore/inference/InferenceIT.java | 37 +++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/637e3ff3/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 a87dd8d..2c2ba62 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 @@ -125,6 +125,7 @@ public class InferenceEngine { } public void refreshGraph() throws InferenceEngineException { + ValueFactory vf = ValueFactoryImpl.getInstance(); try { //get all subclassof Graph graph = TinkerGraph.open(); @@ -142,6 +143,53 @@ public class InferenceEngine { } } + // 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. + // (In principle, an instance of c is likewise implied to be at least one of the other + // types, but this fact is ignored for now to avoid nondeterministic reasoning.) + iter = RyaDAOHelper.query(ryaDAO, null, OWL.UNIONOF, null, conf); + try { + while (iter.hasNext()) { + Statement st = iter.next(); + Value unionType = st.getSubject(); + // Traverse the list of types constituting the union + Value current = st.getObject(); + while (current instanceof Resource && !RDF.NIL.equals(current)) { + Resource listNode = (Resource) current; + CloseableIteration<Statement, QueryEvaluationException> listIter = RyaDAOHelper.query(ryaDAO, + listNode, RDF.FIRST, null, conf); + try { + if (listIter.hasNext()) { + Statement firstStatement = listIter.next(); + if (firstStatement.getObject() instanceof Resource) { + Resource subclass = (Resource) firstStatement.getObject(); + Statement subclassStatement = vf.createStatement(subclass, RDFS.SUBCLASSOF, unionType); + addStatementEdge(graph, RDFS.SUBCLASSOF.stringValue(), subclassStatement); + } + } + } finally { + listIter.close(); + } + listIter = RyaDAOHelper.query(ryaDAO, listNode, RDF.REST, null, conf); + try { + if (listIter.hasNext()) { + current = listIter.next().getObject(); + } + else { + current = RDF.NIL; + } + } finally { + listIter.close(); + } + } + } + } finally { + if (iter != null) { + iter.close(); + } + } + subClassOfGraph = graph; //TODO: Should this be synchronized? graph = TinkerGraph.open(); @@ -221,7 +269,6 @@ public class InferenceEngine { } inverseOfMap = invProp; - ValueFactory vf = ValueFactoryImpl.getInstance(); iter = RyaDAOHelper.query(ryaDAO, null, vf.createURI("http://www.w3.org/2002/07/owl#propertyChainAxiom"), null, conf); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/637e3ff3/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 f60a1e2..05adbc8 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 @@ -29,6 +29,7 @@ import org.apache.accumulo.core.client.security.tokens.PasswordToken; import org.apache.rya.accumulo.AccumuloRdfConfiguration; import org.apache.rya.accumulo.AccumuloRyaDAO; import org.apache.rya.rdftriplestore.RdfCloudTripleStore; +import org.apache.tinkerpop.gremlin.structure.Graph; import org.junit.After; import org.junit.Assert; @@ -115,6 +116,7 @@ public class InferenceEngineTest extends TestCase { Assert.assertEquals(typeToValueImplications, inferenceEngine.getHasValueByProperty(vf.createURI("urn:taxon"))); } + @Test public void testHasValueGivenType() throws Exception { String insert = "INSERT DATA { GRAPH <http://updated/test> {\n" + " <urn:Biped> owl:onProperty <urn:walksUsingLegs> . \n" @@ -164,4 +166,33 @@ public class InferenceEngineTest extends TestCase { valuesImplyingAnimal.get(taxon).addAll(valuesImplyingTunicate.get(taxon)); Assert.assertEquals(valuesImplyingAnimal, inferenceEngine.getHasValueByType(vf.createURI("urn:Animal"))); } + + @Test + public void testUnionOf() throws Exception { + final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n" + + " <urn:A> owl:unionOf <urn:list1> . \n" + + " <urn:B> owl:unionOf <urn:list2> . \n" + + " <urn:list1> rdf:first <urn:X> . \n" + + " <urn:list1> rdf:rest <urn:list2> . \n" + + " <urn:list2> rdf:first <urn:Y> . \n" + + " <urn:list2> rdf:rest <urn:list3> . \n" + + " <urn:list3> rdf:first <urn:Z> . \n" + + " <urn:Y> rdfs:subClassOf <urn:SuperY> . \n" + + " <urn:SubY> rdfs:subClassOf <urn:Y> . \n" + + "}}"; + conn.prepareUpdate(QueryLanguage.SPARQL, ontology).execute(); + inferenceEngine.refreshGraph(); + Graph subClassGraph = inferenceEngine.getSubClassOfGraph(); + Set<URI> subClassesA = inferenceEngine.findParents(subClassGraph, vf.createURI("urn:A")); + Set<URI> subClassesB = inferenceEngine.findParents(subClassGraph, vf.createURI("urn:B")); + Set<URI> expectedA = new HashSet<>(); + Set<URI> expectedB = new HashSet<>(); + expectedB.add(vf.createURI("urn:Y")); + expectedB.add(vf.createURI("urn:SubY")); + expectedB.add(vf.createURI("urn:Z")); + expectedA.addAll(expectedB); + expectedA.add(vf.createURI("urn:X")); + Assert.assertEquals(expectedA, subClassesA); + Assert.assertEquals(expectedB, subClassesB); + } } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/637e3ff3/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 c950a3e..d3f2faf 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 @@ -178,4 +178,41 @@ public class InferenceIT extends TestCase { expected.add(new ListBindingSet(varNames, vf.createURI("urn:Hank"), vf.createURI("urn:Mammalia"))); Assert.assertEquals(expected, new HashSet<>(solutions)); } + + @Test + public void testUnionQuery() throws Exception { + final String ontology = "INSERT DATA { GRAPH <http://updated/test> {\n" + + " <urn:A> owl:unionOf <urn:list1> . \n" + + " <urn:B> owl:unionOf <urn:list2> . \n" + + " <urn:list1> rdf:first <urn:X> . \n" + + " <urn:list1> rdf:rest <urn:list2> . \n" + + " <urn:list2> rdf:first <urn:Y> . \n" + + " <urn:list2> rdf:rest <urn:list3> . \n" + + " <urn:list3> rdf:first <urn:Z> . \n" + + " <urn:SubY> rdfs:subClassOf <urn:Y> . \n" + + " <urn:Y> rdfs:subClassOf <urn:SuperY> . \n" + + "}}"; + final String instances = "INSERT DATA { GRAPH <http://updated/test> {\n" + + " <urn:Alice> a <urn:X> . \n" + + " <urn:Bob> a <urn:Y> . \n" + + " <urn:Carol> a <urn:Z> . \n" + + " <urn:Dan> a <urn:SuperY> . \n" + + " <urn:Eve> a <urn:SubY> . \n" + + "}}"; + final String query = "SELECT ?x { GRAPH <http://updated/test> { ?x a <urn:B> } } \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:Bob")); + expected.add(vf.createURI("urn:Carol")); + 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()); + } }
