title: “Reasoners and rule engines: Jena inference support” slug: index

Overview of inference support

Available reasoners

The Inference API

Generic reasoner API

Finding a reasoner

Configuring a reasoner

Applying a reasoner to data

Accessing inferences

Reasoner description

Some small examples

String NS = "urn:x-hp-jena:eg/";

// Build a trivial example data set
Model rdfsExample = ModelFactory.createDefaultModel();
Property p = rdfsExample.createProperty(NS, "p");
Property q = rdfsExample.createProperty(NS, "q");
rdfsExample.add(p, RDFS.subPropertyOf, q);
rdfsExample.createResource(NS+"a").addProperty(p, "foo");
InfModel inf = ModelFactory.createRDFSModel(rdfsExample);  // [1]
Resource a = inf.getResource(NS+"a");
System.out.println("Statement: " + a.getProperty(q));
Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample);
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null);
InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample);
Resource config = ModelFactory.createDefaultModel()
                              .createResource()
                              .addProperty(ReasonerVocabulary.PROPsetRDFSLevel, "simple");
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(config);
InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample);
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance()Create(null);
reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel,
                      ReasonerVocabulary.RDFS_SIMPLE);
InfModel inf = ModelFactory.createInfModel(reasoner, rdfsExample);
Reasoner boundReasoner = reasoner.bindSchema(schema);
InfModel inf = ModelFactory.createInfModel(boundReasoner, data);

Operations on inference models

Validation

Model data = RDFDataMgr.loadModel(fname);
InfModel infmodel = ModelFactory.createRDFSModel(data);
ValidityReport validity = infmodel.validate();
if (validity.isValid()) {
    System.out.println("OK");
} else {
    System.out.println("Conflicts");
    for (Iterator i = validity.getReports(); i.hasNext(); ) {
        System.out.println(" - " + i.next());
    }
}

Extended list statements

Direct and indirect relationships

Derivations

eg:A eg:p eg:B .
eg:B eg:p eg:C .
eg:C eg:p eg:D .
String rules = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
Reasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));
reasoner.setDerivationLogging(true);
InfModel inf = ModelFactory.createInfModel(reasoner, rawData);
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);
    }
}
out.flush();

Accessing raw data and deductions

Processing control

Tracing

reasoner.setParameter(ReasonerVocabulary.PROPtraceOn, Boolean.TRUE);

The RDFS reasoner

RDFS reasoner - intro and coverage

eg:a eg:p nnn^^datatype .
eg:a eg:p _:anon1 .
_:anon1 rdf:type datatype .

RDFS configuration

reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel,
                      ReasonerVocabulary.RDFS_SIMPLE);
Resource config = ModelFactory.createDefaultModel()
                  .createResource()
                  .addProperty(ReasonerVocabulary.PROPsetRDFSLevel, "simple");
Reasoner reasoner = RDFSRuleReasonerFactory.theInstance()Create(config);

Summary of parameters

RDFS Example

<rdf:Description rdf:about="eg:mum">
  <rdfs:subPropertyOf rdf:resource="eg:parent"/>
</rdf:Description>

<rdf:Description rdf:about="eg:parent">
  <rdfs:range  rdf:resource="eg:Person"/>
  <rdfs:domain rdf:resource="eg:Person"/>
</rdf:Description>

<rdf:Description rdf:about="eg:age">
  <rdfs:range rdf:resource="xsd:integer" />
</rdf:Description>
<Teenager rdf:about="eg:colin">
    <mum rdf:resource="eg:rosy" />
    <age>13</age>
</Teenager>
Model schema = RDFDataMgr.loadModel("file:data/rdfsDemoSchema.rdf");
Model data = RDFDataMgr.loadModel("file:data/rdfsDemoData.rdf");
InfModel infmodel = ModelFactory.createRDFSModel(schema, data);

Resource colin = infmodel.getResource("urn:x-hp:eg/colin");
System.out.println("colin has types:");
printStatements(infmodel, colin, RDF.type, null);

Resource Person = infmodel.getResource("urn:x-hp:eg/Person");
System.out.println("\nPerson has types:");
printStatements(infmodel, Person, RDF.type, null);
ValidityReport validity = infmodel.validate();
if (validity.isValid()) {
    System.out.println("\nOK");
} else {
    System.out.println("\nConflicts");
    for (Iterator i = validity.getReports(); i.hasNext(); ) {
        ValidityReport.Report report = (ValidityReport.Report)i.next();
        System.out.println(" - " + report);
    }
}

RDFS implementation and performance notes

The OWL reasoner

OWL coverage

OWL Configuration

OWL Example

Model schema = RDFDataMgr.loadModel("file:data/owlDemoSchema.rdf");
Model data = RDFDataMgr.loadModel("file:data/owlDemoData.rdf");
Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
reasoner = reasoner.bindSchema(schema);
InfModel infmodel = ModelFactory.createInfModel(reasoner, data);
Resource nForce = infmodel.getResource("urn:x-hp:eg/nForce");
System.out.println("nForce *:");
printStatements(infmodel, nForce, null, null);
public void printStatements(Model m, Resource s, Property p, Resource o) {
    for (StmtIterator i = m.listStatements(s,p,o); i.hasNext(); ) {
        Statement stmt = i.nextStatement();
        System.out.println(" - " + PrintUtil.print(stmt));
    }
}
Resource gamingComputer = infmodel.getResource("urn:x-hp:eg/GamingComputer");
Resource whiteBox = infmodel.getResource("urn:x-hp:eg/whiteBoxZX");
if (infmodel.contains(whiteBox, RDF.type, gamingComputer)) {
    System.out.println("White box recognized as gaming computer");
} else {
    System.out.println("Failed to recognize white box correctly");
}
ValidityReport validity = infmodel.validate();
if (validity.isValid()) {
    System.out.println("OK");
} else {
    System.out.println("Conflicts");
    for (Iterator i = validity.getReports(); i.hasNext(); ) {
        ValidityReport.Report report = (ValidityReport.Report)i.next();
        System.out.println(" - " + report);
    }
}

... + 3 other similar reports

OWL notes and limitations

Comprehension axioms

class A = intersectionOf (minCardinality(P, 1), maxCardinality(P,1))
class B = cardinality(P,1)

Prototypes

Direct/indirect

Performance

Incompleteness

The transitive reasoner

The general purpose rule engine

Overview of the rule engine(s)

Rule syntax and structure

bare-rule := term, ... term -> hterm, ... hterm // forward rule or bhterm <- term, ... term // backward rule

hterm := term or [ bare-rule ]

term := (node, node, node) // triple pattern or (node, node, functor) // extended triple pattern or builtin(node, ... node) // invoke procedural primitive

bhterm := (node, node, node) // triple pattern

functor := functorName(node, ... node) // structured literal

node := uri-ref // e.g. http://foo.com/eg or prefix:localname // e.g. rdf:type or <uri-ref> // e.g. <myscheme:myuri> or ?varname // variable or ‘a literal’ // a plain string literal or ‘lex’^^typeURI // a typed literal, xsd:* type names supported or number // e.g. 42 or 25.5

[all2: (?C rdfs:subClassOf all(?P, ?D)) -> print('Rule for ', ?C) [all1b: (?Y rdf:type ?D) <- (?X ?P ?Y), (?X rdf:type ?C) ] ]

[max1: (?A rdf:type max(?P, 1)), (?A ?P ?B), (?A ?P ?C) -> (?B owl:sameAs ?C) ]

List rules = Rule.rulesFromURL("file:myfile.rules");

or

BufferedReader br = /* open reader */ ;
List rules = Rule.parseRules( Rule.rulesParserFromReader(br) );

or

String ruleSrc = /* list of rules in line */
List rules = Rule.parseRules( rulesSrc );

In the first two cases (reading from a URL or a BufferedReader) the rule file is preprocessed by a simple processor which strips comments and supports some additional macro commands:

# Example rule file
@prefix pre: <http://jena.hpl.hp.com/prefix#>.
@include <RDFS>.

[rule1: (?f pre:father ?a) (?u pre:brother ?f) -> (?u pre:uncle ?a)]

Forward chaining engine

Backward chaining engine

Tabling

-> table(rdfs:subClassOf).
[r1: (?A rdfs:subClassOf ?C) <- (?A rdfs:subClassOf ?B) (?B rdfs:subClassOf ?C)]

Hybrid rule engine

GenericRuleReasoner configuration

String ruleSrc = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -&gt; (?a eg:p ?c)]";
List rules = Rule.parseRules(ruleSrc);
...
Reasoner reasoner = new GenericRuleReasoner(rules);</pre>

Summary of parameters

Builtin primitives

Example

eg:r eg:concatFirst  eg:p .
eg:r eg:concatSecond eg:q .
eg:A eg:p eg:B .
eg:B eg:q eg:C .
String rules =
    "[r1: (?c eg:concatFirst ?p), (?c eg:concatSecond ?q) -&gt; " +
    "     [r1b: (?x ?c ?y) &lt;- (?x ?p ?z) (?z ?q ?y)] ]";
Reasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));
InfModel inf = ModelFactory.createInfModel(reasoner, rawData);
System.out.println("A * * =&gt;");
Iterator list = inf.listStatements(A, null, (RDFNode)null);
while (list.hasNext()) {
    System.out.println(" - " + list.next());
}

Example 2

// Register a namespace for use in the demo
String demoURI = "http://jena.hpl.hp.com/demo#";
PrintUtil.registerPrefix("demo", demoURI);

// Create an (RDF) specification of a hybrid reasoner which
// loads its data from an external file.
Model m = ModelFactory.createDefaultModel();
Resource configuration =  m.createResource();
configuration.addProperty(ReasonerVocabulary.PROPruleMode, "hybrid");
configuration.addProperty(ReasonerVocabulary.PROPruleSet,  "data/demo.rules");

// Create an instance of such a reasoner
Reasoner reasoner = GenericRuleReasonerFactory.theInstance().create(configuration);

// Load test data
Model data = RDFDataMgr.loadModel("file:data/demoData.rdf");
InfModel infmodel = ModelFactory.createInfModel(reasoner, data);

// Query for all things related to "a" by "p"
Property p = data.getProperty(demoURI, "p");
Resource a = data.getResource(demoURI + "a");
StmtIterator i = infmodel.listStatements(a, p, (RDFNode)null);
while (i.hasNext()) {
    System.out.println(" - " + PrintUtil.print(i.nextStatement()));
}

[rule1: (?P rdf:type demo:TransProp) -> [ (?X ?P ?Y) <- (?Y ?P ?X) ] [ (?A ?P ?C) <- (?A ?P ?B), (?B ?P ?C) ] ]

Combining RDFS/OWL with custom rules

Model data = RDFDataMgr.loadModel("file:data.n3");
List rules = Rule.rulesFromURL("myrules.rules");

GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
reasoner.setOWLTranslation(true);               // not needed in RDFS case
reasoner.setTransitiveClosureCaching(true);

InfModel inf = ModelFactory.createInfModel(reasoner, data);

Notes

_:anon rb:validation on() .
?x rb:violation f(summary, description, args) .

Extensions

Rule syntax

Builtins

Preprocessing hooks

Extending the inference support

Futures