Tuesday, March 01, 2005

Rules OWL
The majority of today was on encoding the RDFS rules into RDF, and modifying the OWL that describes it as I came across problems. Several times I found myself questioning some of the decisions I've made about this structure, but in the general case I stayed with what I was doing after thinking about it for a while.

The first thing I considered was how I am describing variables. Some example RDF for this is:

If I want to reference this variable elsewhere (such as in the subject clause) then I need to give it a name:
  <Variable rdf:about="#var_a">
While I don't need to reference every variable from elsewhere, it finally occurred to me that I was being inconsistent, and I should just name all of them. Once I made that decision, I started wondering if I should bother with the "name" predicate, since I could just use the URI. However, I decided to keep the name, as the URI isn't a suitable name for a variable ("http://..." etc). I thought about having code which stripped the fragment of the end of the URI, but that seems more like a hack, and it's subverting the RDF (which is supposed to provide all the information I could want about a node). So the name stays.

The second thing I wondered about was the URIReference class. This is a class which refers directly to a URI, such as <rdf:type>. I use these in constraints, and also in the select clause, to indicate a specific URI. An example is:
  <URIReference rdf:about="#ref_type">
<refersTo rdf:resource="&rdf;type"/>
The obvious question is whether I should use these nodes to point to the node with the required URI, or if I should just include that node. Later in the day I showed this to Simon, and it was the first question that he asked me. I found that amusing, as I'd spent ages wondering about it.

I think I've reached a conclusion here. I really want to be able to use an iTQL to find everything I need in one fell swoop, and using a URIReference node will let me do that. By using this node I can ask for the rdf:type of all of the relevant nodes, and I should either get a "Value" or a "URIReference". If I use the nodes directly (without going through a URIReference) then I might or might not get a type (depending on the node declaration). I would then know which nodes were Values, but finding the other nodes would be annoying, as I'd have to consider the typed nodes which are not "Value", plus I'd have to track down those nodes which were not returned because they didn't have a type.

From a semantic perspective, I'm more comfortable using this indirection as well. When I select this node in the rule I really want the URI, I don't want what that URI represents. I was initially tempted to provide the URI as a literal, but decided that referring to the real node made sense, as it provides some meaning that way.

So the indirection stays.

Finally, I came across rule 5a from RDFS. This is the one which handles transitive closure. In this case we really want to use the TransitiveConstraint object, so it is necessary to describe this object in the RDF as well. Unfortunately, these constraints wrap two other constraints which look like simple constraints, but have to follow specific rules. ie. The first constraint must have a fixed predicate and a variable on either side. The second constraint must have the same predicate, but be fixed at one end, with a variable at the other. This gets tricky to enforce in OWL, but I think I can do it (not that I need to, since I can enforce it in code, but if I can't do a simple thing like this, then I've got bigger problems). I've written the RDF for rule 5a, and I'm halfway through editing the ontology for transitive constraints. I should finish that first thing in the morning.

My plan is to get the RDFS rules and complete ontology written and validated by Thursday. I then have two pieces of code to write. The first piece will be the library that parses this RDF into a Query object, and does it efficiently. I don't anticipate that to be hard, but it will take some time.

The second piece of code is a resolver for handling prefix matching. I gave this some thought before I realised that the only thing I want to use prefix matching for is picking up all of the rdf:_n predicates. This is useful for anyone using a sequence (as I am), and is essential for rule XI in RDFS (which I am also doing). Other people may have a need for prefix matching, but given that this is necessary for correct RDF operation, I feel justified giving it a resolver of its own.

The resolver itself should be quite easy. It will essentially be a copy and paste of the Node Type resolver, only the selections from the string pool will not be all nodes of a particular type, but rather all nodes which start with "rdf:_". If it is so similar, then maybe I should investigate the use of generics to share the code between both resolvers? (Only kidding Andrew).

Rules Paper
I also took a coffee break and spent it on Guido's paper. I like what it can offer, and it may even have some usefulness for Kowari one day. However, it doesn't have anything to offer the OWL implementation, so I skimmed the last few pages. The list of references may be a different story though, so I'll be checking some of them out.

While reading in the coffee room I introduced myself to Peter Robinson. He seemed quite nice, and later on I thought I'd check out his staff page to see what kind of work he does. It turns out that he's interested in logic programming, and theorem proving. I like coincidences like that. I'll have to have another chat with him.

In the late afternoon I went upstairs for a short meeting with Bob. This was mostly to give him an update on where I am and what I'm doing.

Bob seemed pretty happy about it all, but he pointed out that I'm now well beyond where I need to be in order to do my confirmation. I was already aware of that, but it was still good to be prodded a little. I've been so busy lately that it's easy to procrastinate on that item. My main problem is that I really need to do this writing at night (as I'm doing the implementation work during the day), and blogging plus reading means that I'm not really getting to it. I have to prioritize though, so I've asked Bob to check in on me by the end of the week to see that I've made a start on the write up.

I explained where I'm going with the set-at-a-time resolution, and he agreed that it sounded good. I mentioned the paper which proved that set-at-a-time is provably as efficient as tuple-at-a-time and he was surprised, as he thought it should be much more efficient. I agree with him there, so I'll probably be looking for more papers like that. I still believe that Kowari will be the only set-at-a-time OWL inferencer, so that will certainly make my project novel (an essential requirement).

Logic vs. Rules
I also asked about the difference between a Logic engine and a Rules engine. Perhaps I misunderstood Guido (Andrew can probably enlighten me here) but I thought that Guido considered the two systems to be distinct. Bob does not, and was wondering what Guido might have been getting at. As he rightly pointed out, a logic engine is usually implemented with a rules engine.

Bob asked what I believed the difference to be, and I'm afraid that I wasn't particularly articulate at the time. However, from what I can infer, a logic engine seems to perform algebraic manipulation to reduce the equations to their simplest form for efficiency, ideally eliminating elements of the equation which can be cancelled, and hopefully demonstrate the entire equation to be consistent or inconsistent. Once reduced in this way, the final result can be applied to the data to find all interpretations which makes the equation consistent.

Conversely, a rules engine simply tests each statement against each rule. For those statements which match, the head of the rule is executed (this is typically an assertion of new data). This is highly flexible, and can be used to perform all First Order Logic (FOL) operations, as well as many operations which do not conform to FOL. Often the last stage in the "logic engine" process described above is implemented in this way.

I should check out some Prolog implementations, as well as systems like FaCT++ and Vampire to see if they conform to this view of logic engines.

Bob also pointed out that he has a chapter in one of his books on bottom-up evaluation for Datalog systems. This basically means that these systems are implemented as sets of internal rules. He's lent me the book tonight, so I'll be reading that chapter when I finish here.

I also asked Bob about some future ideas. I was careful to explain that I didn't plan on getting ahead of myself, but I'm really interested in where I'll be going after I've done my present course.

Rules engines are all very good, but they can only let you do things that you know about when you set up the rules. This limits their general applicability.

Ontology languages (such as OWL) offer a lot more scope. While they are implemented with rules, they let you describe a more flexible structure, and the underlying rules will then work within that. However, it is still difficult to get ontologies from different areas to work together, particularly for cross-inferencing between domains. At least OWL offers some form of portability of information, but even when nodes from different ontologies can be declared to be the owl:sameAs each other, there is still very little beyond type information that can be inferred from this.

In order to do more complex inferencing between domains (without prior knowledge to see a rules engine), a method of describing ontologies and how they interact must be developed. This doesn't really exist yet.

I expressed this to Bob, and he agreed that this is definitely the next stage of work in the field. He thinks that systems like OWL will provide the building blocks for the next layer up, where this higher layer will allow for descriptions like what I'm discussing. In his opinion, in 5 to 10 year no one will be doing OWL: they will be working on a layer above it.

I'll be continuing to think on this over the next few months. I know that Peter Bruza at the DSTC is working in this area, so I've made an appointment to speak with him on Thursday of this week. I don't know what to say, except to pose the question described above (how do I infer across knowledge domains?) but I'd love to hear what he may have to tell me.

Anyway, that's enough speculating for tonight. I have some reading on Datalog to get to.

No comments: