Logan is an extension to NG4J (Named Graphs for Jena) that uses the Jess rule engine to support inference over Named Graphs.
The current release is version 0.81. Download Logan.
News
- 1st March 2011: RDFS rule set added (see below)
- 30th June 2010: Version 0.81 released
- 8th April 2010: This website relocated to http://logan.ontonym.org
- 30th March 2010: Logan documentation @ http://logan.ontonym.org/doc
- 30th March 2010: Logan Google Code site @ http://code.google.com/p/logan-rdf/
Features
- Extends NG4J with LoganGraphSet, an implementation of a NamedGraphSet that uses a Jess-based back end
- Integrated rulesets for RDF and OWL (coming in version 0.9).
- Support for persistence (coming in version 0.9)
- Extensible, through the loading of user specified rules at runtime.
Usage
Logan is used in exactly the same way as any other NG4J application. The only difference is how the graph set is constructed. To get up and running:
- Add the jar files in the distribution (logan-0.8.jar and everything under the lib directory) to your classpath.
- Obtain a copy of Jess (see the download section) and add it to your classpath.
- Create the graph set in your Java code as follows, passing the constructor any rule files to be loaded:
NamedGraphSet graphSet = new LoganGraphSet(String ... some_rules);
Data can then be loaded into the model, manipulated, and queried as per any other NG4J application.
Using the Reasoner
Using the reasoner requires some familiarity with Jess. Logan works by representing all quads in memory as Jess Facts, against which rules can be defined.
Each Quad Fact is represented by a data structure consisting of 7 slots: graph, subject, predicate, object, literal, lang, and datatype.
Not all of these slots are used in any given Quad representation. Specifically:
- When working with non-literal objects, quads are represented using only the graph, subject, predicate, and object slots.
- When working with literal objects, quads are represented using only the graph, subject, predicate, literal, lang, and datatype slots.
- Those slots not used for the representation of any given quad should always be assigned the value “NULL”.
Inference Example
This section illustrates the use of Logan via a simple example.
Using properties from the Ontonym person ontology, we define a generic rule to say that the brother of a person’s parent is that person’s uncle. More formally: parentOf(x, y) and brotherOf(z, y) => uncleOf(x, z).
we encode this using Jess as follows:
;;; Declare the graph name to hold the inferences (deffacts InferenceGraph (logan-graphname (graph "urn:inferred") ) ) ;;; A rule defining an uncle as the brother of a parent. (defrule uncleOf (declare (salience 50)) (logan-quad (subject ?y) (predicate "http://ontonym.org/0.8/person#parentOf") (object ?x)) (logan-quad (subject ?z) (predicate "http://ontonym.org/0.8/person#brotherOf") (object ?y)) (not (logan-quad (subject ?z) (predicate "http://ontonym.org/0.8/person#uncleOf") (object ?x)) ) => (assert (logan-quad (graph "urn:inferred") (subject ?z) (predicate "http://ontonym.org/0.8/person#uncleOf") (object ?x) (datatype "NULL") (lang "NULL") (literal "NULL") )) )
We save this as “uncle.clp” in the root of the project directory and pass it as a parameter when creating a graph set:
// Create the graph set and define a graph to contain relationship information.
NamedGraphSet graphSet = new LoganGraphSet("uncle.clp");
NamedGraph graph = graphSet.createGraph("http://example.org/family");
and create three people, Sam, Richard, and Christopher:
// Define Sam, Richard, and Christopher
Node sam = Node.createURI("http://example.org/sam");
Node richard = Node.createURI("http://example.org/richard");
Node christopher = Node.createURI("http://example.org/christopher");
We then assert that Christopher is Richard’s brother, and that Richard is Sam’s father:
// Assert Richard as Sam's parent.
Node fatherOf = Node.createURI("http://ontonym.org/0.8/person#parentOf");
graph.add(new Triple(richard, fatherOf, sam));
// Assert Christopher as Richard's brother.
Node brotherOf = Node.createURI("http://ontonym.org/0.8/person#brotherOf");
graph.add(new Triple(christopher, brotherOf, richard));
Now we can query to see if Sam has an uncle:
// Query for Sam's uncles.
Node uncleOf = Node.createURI("http://ontonym.org/0.8/person#uncleOf");
Iterator<Quad> matches = graphSet.findQuads(Node.ANY, Node.ANY, uncleOf, sam);
while (matches.hasNext()) {
System.out.println("Sam has uncle: " + matches.next().getSubject());
}
This prints “Sam has uncle: http://example.org/christopher” to the console.
We can also use SPARQL to inspect the quad store:
// Create a SPARQL query to select all uncles in the graph.
Query sparql = QueryFactory
.create("SELECT * WHERE { GRAPH ?g { ?s <http://ontonym.org/0.8/person#uncleOf> ?o } }");
QueryExecution qe = QueryExecutionFactory.create(sparql, new NamedGraphDataset(graphSet));
ResultSet results = qe.execSelect();
// For each result, print the relationship.
while (results.hasNext()) {
QuerySolution result = results.nextSolution();
RDFNode g = result.get("g");
RDFNode s = result.get("s");
RDFNode o = result.get("o");
System.out.println(g + " { " + s + " is the uncle of " + o + " . }");
}
This prints “urn:inferred { http://example.org/christopher is the uncle of http://example.org/sam . }” to the console.
We can see the full contents of the quad store by printing out the complete model. The following prints out the model using TriG syntax:
graphSet.write(System.out, "TRIG", null);
which gives us:
@prefix person: <http://ontonym.org/0.8/person#> .
<http://example.org/family> {
<http://example.org/christopher>
person:brotherOf <http://example.org/richard> .
<http://example.org/richard>
person:parentOf <http://example.org/sam> .
}
<urn:default> { }
<urn:inferred> {
<http://example.org/christopher>
person:uncleOf <http://example.org/sam> .
}
Rule Sets
What use an inference engine without some rules? Rule sets providing support for RDFS and OWL models will be distributed in the next release of Logan. For now, they are available to download here:
- RDFS Rule Set
- OWL 2 RL Rule Set (Coming Soon)
Download
Logan version 0.81 can be downloaded from its Google Code project page and is licensed under the terms of the Berkeley Software Distribution (BSD) License.
Logan requires both NG4J (included) and Jess (not included) to operate.
- Version 0.9.3 of NG4J is contained within the Logan distribution. Please visit the NG4J website for more details about the project.
- Logan uses version 7.1 of Jess. Jess is not available for Open Source licensing under any GPL license. To license and download Jess, please visit the Jess website.
In The Pipeline
The next steps are to release rule sets for RDFS and OWL and to extend Logan with persistence support.
Feedback
Found a bug? Please report it using the issue tracker.
Any other comments? Please email me using the details below.