Sketch of a rule-based OWL reasoner

  1. Getting the rules and the facts
  2. Synchronizing the Wilbur and LISA databases
  3. Passing the first OWL testcase
  4. Speed concerns

Our reasoner relies on LISA (Lisp Intelligent Software Agent), a forward-chaining inference engine to derive facts about our markup. LISA provides a clean API for specifying rules and facts, in a CLIPS-derived format. Its greatest advantage is its ability to reason with arbitrary CLOS (Common Lisp Object System) objects, or in our case, with Wilbur triple objects.

Wilbur's triple objects are standard CLOS objects and hence processing them in LISA is simple; all we have to do is include them in our knowledge base as facts. This is done using the assert macro:

(assert ((triple subject predicate object)))
Once asserted into LISA as facts, our triples will correctly respond to any LISA operator or rule.

Getting the rules and the facts

Before we can reason with actual RDF and OWL, there are a few bare-bone facts and rules that must be included in our knowledge base, such as: "everything is a resource" or "daml:Datatype is a subclass of daml:Literal". We derived these rules and facts by converting the DAMLJessKB (another CLIPS-derived inference system) to the LISA format. A simple Python script performs this conversion.

Synchronizing the Wilbur and LISA databases

When a file is read into Wilbur, it is stored in a triple store. Once the triples in Wilbur are asserted into the LISA fact base, there is no standard automatic mechanism to keep the two synchronized.

To simulate synchronization, three mechanisms are used:

  1. Triple store -> LISA database: To make sure that triples added to the Wilbur triple store are asserted as facts into LISA, the function db-add-triple was overloaded:
    ;; Have db-add-triple add the triple in question to ;; the LISA kb, if it is not already in it. (defmethod db-add-triple :after ((db db) (triple triple)) (let ((lisa-object (with-simple-query ...))) (if (not lisa-object) (let ((lisa-fact (assert ((triple ts tp to)))))))))
  2. LISA database -> Triple store: Achieving the opposite is completed using the rule sync-wilbur-db. Depending on their contexts, different LISA rules might have to explictly invoke this rule after asserting new facts into the knowledge base.
  3. Wilbur "mutation": Mutation is when an already existing object's slot has been changed. An example of this in the Wilbur toolkit is the triple-object function, that can be used as follows to change a triple's object slot value:
    (setf (triple-object my-triple) 'new-object-value)
    Capturing those changes is done by adding a before-method to triple-object. A hashtable whose keys are Wilbur triple objects and values their corresponding LISA facts is used to explictly signal the changes to LISA.

The figure below illustrates the above process:


Passing the first OWL testcase

We tested the reasoner by having it parse the first positive OWL testcase (from the testcases collection). The test is:

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:first="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#"
xmlns="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001">
<owl:FunctionalProperty rdf:ID="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#prop"/>
<rdf:Description rdf:ID="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#subject">
<first:prop rdf:resource="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#object1" />
<first:prop rdf:resource="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#object2" />
</rdf:Description>
</rdf:RDF>
Note that usage of xml:base was removed due to Wilbur's inability to parse it.

After pointing the parser at the relevant RDF, we can run the inference engine:

LISA-LISP(4): (run) [...output removed for brevity...] Triple added: s: http://www.daml.org/2001/03/daml+oil#rest p: http://www.w3.org/1999/02/22-rdf-syntax-ns#type o: http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource Triple added: s: http://www.daml.org/2001/03/daml+oil#rest p: http://www.w3.org/1999/02/22-rdf-syntax-ns#type o: http://www.w3.org/2000/01/rdf-schema#Resource Triple added: s: http://www.daml.org/2001/03/daml+oil#nil p: http://www.w3.org/1999/02/22-rdf-syntax-ns#type o: http://www.w3.org/1999/02/22-rdf-syntax-ns#Resource 280
For a total of 280 inferred triples. All that is left to do is test whether the test's conclusions file have been arrived at in our knowledge base. The custom function begin-tests performs this test:
LISA-LISP(6): (begin-tests) Loading first OWL test case 6.1.1 example 001.. Testing 6.1.1 example 001
The reasoner then outputs its results in N3 form to test-611-011.n3, which is converted into RDF/XML by CWM:

<!-- Processed by Id: cwm.py,v 1.97 2002/07/06 12:52:02 timbl Exp -->
<!-- using base file:/home/katz/semweb/lisa/test-611-011.n3 -->

<rdf:RDF
xmlns="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#"
xmlns:log="http://www.w3.org/2000/10/swap/log#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xmlns="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#">

<rdf:Description rdf:about="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#object1">
<owl:sameIndividualAs rdf:resource="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#object1"/>
<owl:sameIndividualAs rdf:resource="http://www.w3.org/2002/03owlt/FunctionalProperty/premises001#object2"/>
</rdf:Description>
</rdf:RDF>

Our reasoner passed the positive test: the expected triples were inferred.

Speed concerns

The current uncompiled version was able to infer 280 triples for the OWL test case in a total of 4,447 milliseconds. There are many ways to optimize although the system as is can hardly be considered "slow."


 Yarden Katz  <katz@underlevel.net> Last modified: Mon Jun 30 15:10:26 EST 2003