I've now checked the existing Drools inferencing code into Kowari. It is still an external application with no integration into the Kowari application, but it included and built as a part of the Kowari package now.
I should create a set of test files so inferencing can be tested from Ant, but I won't be working on that until I get a little more time. However, I do have Ant correctly building the code, and this is a significant portion of the work, since the most difficult part of making Drools work as a Kowari client was getting the classpath correct.
In the meantime I've moved onto getting inferencing working for OWL, and not just RDFS. I'm basing the work on one of the OWL Lite papers by Raphael Volz. He has done several, but this one seemed to be the most convenient.
As I've already commented, it seems to be possible to take all of the required Horn Clauses required for OWL Lite and convert them into iTQL. I already have the required statements for RDFS, so now I just need to convert the OWL statements as well, and add them to the Drools configuration file. I started this afternoon on this, and I'll be continuing for the next couple of days.
To start with I thought I'd confirm the RDFS iTQL against the Horn clauses for RDFS. This way I could make sure I was doing things as I expected, and it could run a check on the work already done. Since this is the first time I've considered the specifics of conversion, I hadn't realised that the Sesame entailment code was written to perform much of its inferencing iteratively rather than directly.
An example of this iterative approach can be shown with rdfs:subClassOf. Given a statement of:
C rdfs:subClassOf DThen the resulting Horn Clause is:
D(x) :- C(x)To consider this statement in natural language for a moment, we can see that it says that if there is an instance of an object which is of class C, then it is also an instance of class D.
Both sides of this clause make statements:
1. C is of type rdfs:Class
2. D is of type rdfs:Class
3. if x is of type C then x is of type D
However, the RDFS entailment code from Sesame does not bother with the first two statements. If D is of type
rdfs:Classthen this code will successfully create a statement that C is also of type
rdfs:Classvia rule 9:
Also, if a predicate mentions that its domain or range includes objects of type rdfs:Class then this will create type statements as well, via rules 2 and 3:
select $aaa <rdf:type> $yyy from @@SOURCE@@
where $aaa <rdf:type> $xxx and $xxx <rdfs:subClassOf> $yyy;
select $xxx <rdf:type> $zzz from @@SOURCE@@
where $xxx $aaa $yyy and $aaa <rdfs:domain> $zzz;
select $uuu <rdf:type> $zzz from @@SOURCE@@
where $xxx $aaa $uuu and $aaa <rdfs:range> $zzz;
Unfortunately none of the above will create the statement that D is of type
rdfs:Class, which is explicit in the horn clause. The statement that C is an
rdfs:Classmay or may not be created depending on whether D is mentioned.
For completeness sake it may be worth adding in a new statement to create a type statement for any resources appearing in an
rdfs:subClassOfstatement. However, I may be going overboard, as it is normal to declare classes explicitly, particularly at the head of a hierarchy. Assuming usual practice in the creation of an ontology, creating a rule like this may not pick up anything new.
I'll leave it for the moment, but I might refer back here if I have some time.
While I was at it I noticed that I'm not using
transin these rules. That makes the system completely forward chained, which isn't right. I may have fixed this before, but since I have not had anywhere to check the code in before today then it has possibly been mislaid. Fortunately, it's easy enough to fix this part of the code.