Documenting
I've spent pretty much the whole day documenting, so there's not a lot to say here. Somehow the following ended up lengthy anyway, and given that it's late I won't be proofreading it until later. Read at your own risk. :-)
The early part of the day was spent modifying the camera ontology from XFront to better demonstrate the OWL-Lite features we needed. The original camera ontology has moved on their site since it was first published, but thanks to Google I discovered that it's still there.
I then had to create an RDF file which declared cameras with various properties. Short on inspiration I went and found real specs for cameras from Olympus and Pentax. I even discovered what a "Large-Format" camera is, and several models from Sinar were included as well. It's enough to make you interested in photography.
We now have valid cameras, and several invalid cameras. The invalid ones violate restrictions on cardinality, someValuesFrom and allValuesFrom. We also have the documentation to explain how to validate the RDF using iTQL. This iTQL is the basis for the consistency and entailment rules in Kowari, and will eventually be incorporated into the rules engine (which works, but is not integrated and not all of the rules are written).
One problem I had was with namespaces. Now I'm the first to confess that I really don't know much about XML. I just stumble around in it, mostly copying bits from other sources as I need them. Learning it all seemed too time consuming when I have so many other things to be reading.
To start with, for convenience I declared an entity:
<!ENTITY camera "http://www.xfront.com/owl/ontologies/camera/#">
Note the # on the end? I watched AN use this namespace to declare an instance in the following way:<rdf:Description rdf:about="&camera;Olympus-OM-10">
...
<rdf:Description/>
Not too pretty, but when queried the database for this node I got: http://www.xfront.com/owl/ontologies/camera/#Olympus-OM-10
Which was what I expected.
However, taking a lead from XFront (and some half-remembered method of declaring a namespace for a node) I tried to use it this way:
<rdf:Description rdf:about="Olympus-OM-10" xmlns="&camera;">
...
<rdf:Description/>
This had the unexpected effect of losing the #: http://www.xfront.com/owl/ontologies/camera/Olympus-OM-10
Now I know this will be my fault, but I really don't understand how the # got lost here. Maybe I really do need to learn XML.
A New Type Predicate
After sleeping on the OWL description problem, I realised that it is not such a difficult problem. What we need a another "magical" predicate that lets us define "type". At the moment we can say:
$instance <rdf:type> <ns:Class>
This will pick up all simple class types, and after a round of using trans($x owl:subClassOf $y)
it will also pick up every superclass that was explicitly declared. However, this will not track down if a complex class expression is applicable to an object instance.
Adapting some terminology I picked up in a recent paper, I believe that we can solve the problem if we introduce a predicate which describes if an expression subsumes a node. For instance, we may have a node of type X, and we need to see if it is subsumed by an expression E. A use case for this is to see if the node meets an
owl:allValuesFrom
restriction on a predicate that a subject uses to refer to it. If X is a subclass of Y, which is a subclass of Z, and E is a union between T and Z, then the instance will meet the criteria, and E can be said to subsume the instance. This is a much more complex expression than would normally be described in iTQL, and a single operation which could return true or false on the matter would be very useful.
The operation to test if x was subsumed by description D could go as follows:
1. Get the types of x. If this is an empty list then return "unknown" since we don't know anything about x and can't say anything about it. (Throw an exception to do this?)
2. If any item in the types list is equal to D then return true (this could be skipped, as the list gets checked again in step 4, but it does allow for a quick exit).
3. Get all the supertypes for x and add them to the list of types.
4. If any item in the current types list is equal to D then return true.
5. If D is an
owl:Restriction
then test the instance with the restriction and return the result.
6. If D is an
owl:unionOf
then recurse for each description in the union, returning the ORed results.
7. If D is an
owl:intersectionOf
then recurse for each description in the intersection, returning the ANDed results.
8. If D is an
owl:complementOf
then recurse on the description contained in the expression, and return the complement (using a logical NOT).
9. If D is an
owl:oneOf
then test if x is equal to (or declared the owl:sameIndividualAs
) any of the elements in the list, returning true if it is, or false otherwise.
10. At this point throw an exception, because the description D was not well formed.
This can be done in a straightforward manner, with the execution attached to a predicate like
<tucana:subsumedBy>
. I could even use a <tucana:type>
predicate, as it is conceptually similar to an <rdf:type>
. Using a predicate like this I could modify the iTQL for the incomplete owl:someValuesFrom
test:select $s $p $x count(
select $o
from <rmi://mysite.com/server1#model>
where $s $p $o
and $o <rdf:type> $x
)
from <rmi://mysite.com/server1#model>
where $r <rdf:type> <owl:Restriction>
and $r <owl:onProperty> $p
and $r <owl:someValuesFrom> $x
and $c <rdfs:subClassOf> $r
and $s <rdf:type> $c
and $s $p $obj
having $k0 <tucana:occursLessThan> '1'^^<xsd:nonNegativeInteger>;
This would be changed to the slightly shorter:select $s $p $x count(
select $o
from <rmi://mysite.com/server1#model>
where $s $p $o
and $o <rdf:type> $x
)
from <rmi://mysite.com/server1#model>
where $r <rdf:type> <owl:Restriction>
and $r <owl:onProperty> $p
and $r <owl:someValuesFrom> $x
and $s <tucana:subsumedBy> $r
and $s $p $obj
having $k0 <tucana:occursLessThan> '1'^^<xsd:nonNegativeInteger>;
Thinking about this just now made me realise that this iTQL may not even be strictly necessary. Having a subsumption operation as I just described takes away a lot of the work of the restriction consistency tests, as the operation does the consistency tests internally. In this case, it may just be necessary to see if a class is subsumed by the description that a rdf:type
declaration refers to. In other words, if a statement says: <ns:instance> <rdf:type> <ns:Type>
Then consistency could be tested simply be checking if ns:instance
is subsumed by ns:Type
. Of course, this would necessitate skipping ns:Type
in the list when executing steps 2 and 4, or else ns:instance
of type ns:Type
would be considered consistent simply because it was of type ns:Type
. I should think about this a little more, but I'm pretty sure this last idea will work.
Of course, this means that I need some way to test an
owl:Restriction
in the general case, but this is not all that hard. There are essentially 3 types of restrictions, and each is placed on a predicate. All that is needed is to take the instance in question, and find all statements which use that instance as a subject with the given predicate:
1. For
owl:allValuesFrom
and owl:someValuesFrom
test subsumption of the objects from the found statements. For owl:someValuesFrom
return true the moment an appropriate object is found, or false if none are found. For owl:allValuesFrom
return false the moment an inappropriate object is found or true if all objects are correct.
2. For the cardinality restrictions, check the number of the objects found, and return true if it is larger than
owl:minCardinality
, smaller than owl:maxCardinality
, or equal to owl:cardinality
.
3. For
owl:hasValue
, test each object, returning true as soon as one is found to be equal to the given value, or false if nothing in the list matches.
Looking at it, this takes a lot of work out of writing iTQL for consistency checking, and the code to do it all will be quite straightforward. Once we have the current release out of the way I'll present it all to AN and TJ and confirm that it's as effective as I believe.