Problems with inference examples from Apache Jena framework

java, jena, jena-rules, rdf, reasoning

Solution

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

Problem

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()); } } } ```

Original source