Recording derivations of previously asserted triples in Jena's rule reasoners?

179 views Asked by At

I created a Jena Rule Reasoner as in the documentation

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);

Everything works fine, and I can check the derivation of triples in the inferred model, but the triples which already exist in rawData are not re-inferred by the reasoner, even if they could be, which means that there will be no record of the derivation of such triples. Is there a way to force the reasoner to re-infer and record derivations of triples that already exist in the raw data?

1

There are 1 answers

3
Rob Hall On

Unfortunately, I cannot think of a way to force Jena to construct the derivations for the information in the raw data. I can, however, think of a brute-force way to cause information to be derived that could be derived, thus, resulting in a derivation.

Consider the result of the following (JUnit) test passing:

final Property p = ResourceFactory.createProperty("urn:eg:p");

final Model rawData = ModelFactory.createDefaultModel();
final Resource a = rawData.createResource("urn:a");
final Resource b = rawData.createResource("urn:b");
final Resource c = rawData.createResource("urn:c");
a.addProperty(p, b);
b.addProperty(p, c);
a.addProperty(p, c);

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);

assertTrue(inf.contains(a,p,c));
final Iterator<Derivation> d0 = inf.getDerivation(inf.asStatement(Triple.create(a.asNode(), p.asNode(), c.asNode())));
assertFalse(d0.hasNext());

inf.remove(a,p,c);

assertTrue(inf.contains(a,p,c));
final Iterator<Derivation> d1 = inf.getDerivation(inf.asStatement(Triple.create(a.asNode(), p.asNode(), c.asNode())));
assertTrue(d1.hasNext());

In effect, if you remove a triple from the graph that was presently in the raw data, then, if that triple can be derived, it will remain in the graph. You can then get the derivation. You can safely perform this (costly) operation for all triples in a graph using the following loop:

final Set<Statement> statements = new HashSet<>(rawData.listStatements().toSet());
for( final Statement s : statements ) {
    assert(inf.contains(s));
    inf.remove(s);
    if(!inf.contains(s)) {
        System.out.println("Cannot derive statement from raw data: "+s);
        inf.add(s);
    } else {
        System.out.println("Derivable statement removed from raw data: "+s);
    }
}

For the example data above (assuming we remove the everything after the creation of inf and replace it with our loop), the output is as follows:

Derivable statement removed from raw data: [urn:a, urn:eg:p, urn:c]
Cannot derive statement from raw data: [urn:b, urn:eg:p, urn:c]
Cannot derive statement from raw data: [urn:a, urn:eg:p, urn:b]

Your data is now in a state where you can obtain derivations for all derivable things, and only the minimal amount of rawData remains that would allow you to conclude the entirety of inf.

Note that the behavior of this operation may not be consistent or expected, especially in the presence of multiple derivation paths. Good luck.