According to the documentation (and testing with Jena 2.11.1) you can get access to a Derivation
object which will allow you to create a textual description of what happened. In the following example, we retrieve RuleDerivation
objects that expose a little bit more regarding the internal state.
The following is a tested implementation of the documentation example which begins with the following model:
<urn:eg:C> <urn:eg:p> <urn:eg:D> .
<urn:eg:B> <urn:eg:p> <urn:eg:C> .
<urn:eg:A> <urn:eg:p> <urn:eg:B> .
... and the following rule:
[rule1: (?a urn:eg:p ?b) (?b urn:eg:p ?c) -> (?a urn:eg:p ?c)]
... to produce this resulting model:
<urn:eg:B> <urn:eg:p> <urn:eg:D> , <urn:eg:C> .
<urn:eg:A> <urn:eg:p> <urn:eg:D> , <urn:eg:C> , <urn:eg:B> .
<urn:eg:C> <urn:eg:p> <urn:eg:D> .
This basic transitive inference becomes the core aspect of the example to follow. Note that we obtain an instance of RuleDerivation
which is a start towards your end goal.
final Resource A = ResourceFactory.createResource("urn:eg:A");
final Resource B = ResourceFactory.createResource("urn:eg:B");
final Resource C = ResourceFactory.createResource("urn:eg:C");
final Resource D = ResourceFactory.createResource("urn:eg:D");
final Property p = ResourceFactory.createProperty("urn:eg:p");
final Model rawData = ModelFactory.createDefaultModel();
rawData.add(A, p, B);
rawData.add(B, p, C);
rawData.add(C, p, D);
final String rules = "[rule1: (?a urn:eg:p ?b) (?b urn:eg:p ?c) -> (?a urn:eg:p ?c)]";
final Reasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));
reasoner.setDerivationLogging(true);
final InfModel inf = ModelFactory.createInfModel(reasoner, rawData);
final 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 (final Iterator<Derivation> id = inf.getDerivation(s); id.hasNext(); ) {
final RuleDerivation deriv = (RuleDerivation) id.next();
deriv.printTrace(out, true);
}
}
out.flush();
The output of this example is:
Statement is [urn:eg:A, urn:eg:p, urn:eg:D]
Rule rule1 concluded (urn:eg:A urn:eg:p urn:eg:D) <-
Rule rule1 concluded (urn:eg:A urn:eg:p urn:eg:C) <-
Fact (urn:eg:A urn:eg:p urn:eg:B)
Fact (urn:eg:B urn:eg:p urn:eg:C)
Fact (urn:eg:C urn:eg:p urn:eg:D)
EDIT - Tips
Check out the internals of RuleDerivation#printTrace(...)
if you are looking for an example about how to explore derivations. If you want to convert a triple (from RuleDerivation#getMatches()
) back to a statement, use StatementImpl#toStaetment(Triple,ModelCom)
.
EDIT2 - Done Assuming that you are using one of Jena's built in rule-based reasoners, the following code will allow you to explore the matches for one particular derivation reported by a reasoner.
final StmtIterator input = inf.listStatements(A, p, D);
assert( input.hasNext() );
final Iterator<Derivation> derivations = inf.getDerivation(input.next());
assert( null != derivations );
assert( derivations.hasNext() );
final RuleDerivation oneDerivation = (RuleDerivation) derivations.next();
final ExtendedIterator< Statement > matches =
new NiceIterator< Triple >()
.andThen( oneDerivation.getMatches().iterator())
.mapWith( new Map1< Triple, Statement >(){
@Override
public Statement map1( final Triple t )
{
/* Note that it seems that this model doesn't really mean anything. While
* the statement will be associated with the infModel, the triple that led
* to the match could have been from either the deductions graph or the
* raw graph. This does not actually add any triples to the underlying
* store.
*/
return StatementImpl.toStatement(t, (ModelCom)inf);
}});