问题
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());
}
}
}
回答1:
The prefix eg: isn't what you think it is:
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.
You need to ask the right model
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() );
}
You need RDFS reasoning too
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 );
The complete result
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());
}
}
}
来源:https://stackoverflow.com/questions/24786035/problems-with-inference-examples-from-apache-jena-framework