Reputation: 3535
I have a serious problem to get any reasoner up and running. Also the examples from the documentation: https://jena.apache.org/documentation/inference/ does not work here. I transferred the example into a unit test, so that the problem might be easier reproduced.
Is reasoning limited to certain environment like a spatial JDK or so on, or am i getting something wrong?
Thanks
Here the example code (as java unit test):
import static org.junit.Assert.assertNotNull;
import java.io.PrintWriter;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Derivation;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.vocabulary.RDFS;
public class ReasonerTest {
String NS = "urn:x-hp-jena:eg/";
// Build a trivial example data set
Model model = ModelFactory.createDefaultModel();
InfModel inf;
Resource A = model.createResource(NS + "A");
Resource B = model.createResource(NS + "B");
Resource C = model.createResource(NS + "C");
Resource D = model.createResource(NS + "D");
Property p = model.createProperty(NS, "p");
Property q = model.createProperty(NS, "q");
@Before
public void init() {
// Some small examples (subProperty)
model.add(p, RDFS.subPropertyOf, q);
model.createResource(NS + "A").addProperty(p, "foo");
String rules = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
GenericRuleReasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));
reasoner.setDerivationLogging(true);
inf = ModelFactory.createInfModel(reasoner, model);
// Derivations
A.addProperty(p, B);
B.addProperty(p, C);
C.addProperty(p, D);
}
@Test
public void subProperty() {
Statement statement = A.getProperty(q);
System.out.println("Statement: " + statement);
assertNotNull(statement);
}
@Test
public void derivations() {
String trace = null;
PrintWriter out = new PrintWriter(System.out);
for (StmtIterator i = inf.listStatements(A, p, D); i.hasNext(); ) {
Statement s = i.nextStatement();
System.out.println("Statement is " + s);
for (Iterator id = inf.getDerivation(s); id.hasNext(); ) {
Derivation deriv = (Derivation) id.next();
deriv.printTrace(out, true);
trace += deriv.toString();
}
}
out.flush();
assertNotNull(trace);
}
@Test
public void listStatements() {
StmtIterator stmtIterator = inf.listStatements();
while(stmtIterator.hasNext()) {
System.out.println(stmtIterator.nextStatement());
}
}
}
Upvotes: 2
Views: 3050
Reputation: 85813
The eg:
prefix in the rules doesn't expand to what you think it does. I modified your rules string to
String rules = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)] [rule2: -> (<urn:ex:a> eg:foo <urn:ex:b>)]";
so that rule2 will always insert the triple urn:ex:a eg:foo urn:ex:b into the graph. Then, the output from your tests includes:
[urn:ex:a, urn:x-hp:eg/foo, urn:ex:b]
[urn:x-hp-jena:eg/C, urn:x-hp-jena:eg/p, urn:x-hp-jena:eg/D]
The first line shows the triple that my rule2 inserted, whereas the second uses the prefix you entered by hand. We see that the eg:
prefix is short for urn:x-hp:eg/
. If you change your NS string accordingly, with String NS = "urn:x-hp:eg/";
, then your derivations test will pass.
The subProperty test fails for two reasons. First, it's checking in the wrong model.
You're checking with A.getProperty(q)
:
Statement statement = A.getProperty(q);
System.out.println("Statement: " + statement);
assertNotNull(statement);
A
is a resource that you created for the the model model
, not the model inf
, so when you ask for A.getProperty(q)
, it's actually asking model
for the statement, so you won't see the inferences in inf
. You can use inModel
to get A
"in inf
" so that getProperty
looks in the right model:
Statement statement = A.inModel(inf).getProperty(q);
Alternatively, you could also ask inf
directly whether it contains a triple of the form A q <something>
:
inf.contains( A, q, (RDFNode) null );
Or you could enumerate all such statements:
StmtIterator stmts = inf.listStatements( A, q, (RDFNode) null );
assertTrue( stmts.hasNext() );
while ( stmts.hasNext() ) {
System.out.println( "Statement: "+stmts.next() );
}
Even if you're querying the right model, your inference model still needs to do RDFS reasoning as well as your custom rule that makes the property p transitive. To do that, we can pull the rules out from an RDFS reasoner, add your rule to that a copy of that list, and then create a custom reasoner with the new list of rules:
// Get an RDFS reasoner
GenericRuleReasoner rdfsReasoner = (GenericRuleReasoner) ReasonerRegistry.getRDFSReasoner();
// Steal its rules, and add one of our own, and create a
// reasoner with these rules
List<Rule> customRules = new ArrayList<>( rdfsReasoner.getRules() );
String customRule = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
customRules.add( Rule.parseRule( customRule ));
Reasoner reasoner = new GenericRuleReasoner( customRules );
Here's the modified code, all together for easy copying and pasting. All the tests pass.
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Derivation;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.vocabulary.RDFS;
public class ReasonerTest {
String NS = "urn:x-hp:eg/";
// Build a trivial example data set
Model model = ModelFactory.createDefaultModel();
InfModel inf;
Resource A = model.createResource(NS + "A");
Resource B = model.createResource(NS + "B");
Resource C = model.createResource(NS + "C");
Resource D = model.createResource(NS + "D");
Property p = model.createProperty(NS, "p");
Property q = model.createProperty(NS, "q");
@Before
public void init() {
// Some small examples (subProperty)
model.add(p, RDFS.subPropertyOf, q);
A.addProperty(p, "foo" );
// Get an RDFS reasoner
GenericRuleReasoner rdfsReasoner = (GenericRuleReasoner) ReasonerRegistry.getRDFSReasoner();
// Steal its rules, and add one of our own, and create a
// reasoner with these rules
List<Rule> customRules = new ArrayList<>( rdfsReasoner.getRules() );
String customRule = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
customRules.add( Rule.parseRule( customRule ));
Reasoner reasoner = new GenericRuleReasoner( customRules );
reasoner.setDerivationLogging(true);
inf = ModelFactory.createInfModel(reasoner, model);
// Derivations
A.addProperty(p, B);
B.addProperty(p, C);
C.addProperty(p, D);
}
@Test
public void subProperty() {
StmtIterator stmts = inf.listStatements( A, q, (RDFNode) null );
assertTrue( stmts.hasNext() );
while ( stmts.hasNext() ) {
System.out.println( "Statement: "+stmts.next() );
}
}
@Test
public void derivations() {
String trace = null;
PrintWriter out = new PrintWriter(System.out);
for (StmtIterator i = inf.listStatements(A, p, D); i.hasNext(); ) {
Statement s = i.nextStatement();
System.out.println("Statement is " + s);
for (Iterator<Derivation> id = inf.getDerivation(s); id.hasNext(); ) {
Derivation deriv = (Derivation) id.next();
deriv.printTrace(out, true);
trace += deriv.toString();
}
}
out.flush();
assertNotNull(trace);
}
@Test
public void listStatements() {
StmtIterator stmtIterator = inf.listStatements();
while(stmtIterator.hasNext()) {
System.out.println(stmtIterator.nextStatement());
}
}
}
Upvotes: 7