It depends on what you mean by “has”

November 8, 2010

My specimen collection has several specimen cabinets. Each cabinet has drawers, and the drawers have trays.

ClassAssertion(s1:Collection s1:MyCollection)
ClassAssertion(s1:Cabinet s1:Cab-1)
ClassAssertion(s1:Drawer s1:Drawer-1-1)
ClassAssertion(s1:Tray s1:Tray-1-1-1)
ObjectPropertyAssertion(s1:has s1:MyCollection s1:Cab-1)
ObjectPropertyAssertion(s1:has s1:Cab-1 s1:Drawer-1-1)    
ObjectPropertyAssertion(s1:has s1:Drawer-1-1 s1:Tray-1-1-1)    

You would like to use my data. You decide to make a simple rule:
(a has c) ⊢ (a has b)∧(b has c).

The problem is, by “has” you mean “is physically contained in/part of”. MyCollection does not “have” those cabinets in that sense. Of course, you can’t help wishing that I had made that distinction in my data – used “has” in your sense only, or used “partOf” relationships where appropriate – but I didn’t, and you have to deal with that. So what you want to do is make a new property “pContains” (physically contains) and have a reasoner infer that for those “has” relations in my data that are between objects of the correct kind, pContains obtains and is transitive.

Well. It is possible to do. The trick is defining your own set of reasoning rules, and then reasoning over your rules + my data. So let’s do that. My data is in namespace s1, the new rules are in s2.

Firstly, we’ll define our property pContains, and we’ll define a class pContainer. We’ll declare that Cabinet, Drawer, and Tray are Containers. Our problem then becomes inferring “pContains” when there is a “has” between two containers.

SubClassOf(s1:Cabinet s2:pContainer)
SubClassOf(s1:Drawer s2:pContainer)
SubClassOf(s1:Tray s2:pContainer)

Ok. We can’t simply declare pContains to be a superclass of has, with a domain and range of pContainer. If we did that, then a reasoner would infer that MyCollection is a pContainer. And declaring it as a subclass does, well, very little.

There are a couple of features of OWL that “create” properties out of thin air – declaring a property as transitive, symmetric, and so on. In OWL2, there is a new device – property chains. In fact, the old property booleans can be defined in terms of property chains. But this doesn’t get us very far – our “has” property is a chain of one. Furthermore, the thing that we are interested in – whether the individuals are pContainers or not – is a class, not a property.

There is, however, a way to turn an individual’s membership of a class into a property. No, it isn’t using rdf:type. OWL won’t let you mix “levels” like that. Even though rdf:type is a property in the RDF world, it is not a “property” in the OWL sense of the word.

Instead, we use a reflexive property. Properties have to point somewhere, and you can’t create individuals with mere vocabulary rules. But with a reflexive property, you con’t need another individual to point at. The existence or nonexistence of a reflexive property can serve much the same role as a boolean value. Further, a reflexive property points back at where you started. If you follow one as part of a property chain, you dont “go” somewhere else.

Without further ado, the magic code is:

SubClassOf(s2:pContainer ObjectHasSelf(s2:selfIsPContainer))
  ObjectPropertyChain(s2:selfIsPContainer s1:has s2:selfIsPContainer) 

And yes: success! The HermiT OWL 2 DL reasoner correctly infers that our Cabinet pContains the draw and the tray, but not that MyCollection pContains them.

It’s difficult to overstate the power of this technique: converting an individual’s class membership into a reflexive property and then building property chains over that. It means that property chain inferences can be made conditional on an individual’s membership in almost any kind of class – and class definitions are very powerful. You can make a class definition based on an individual – for instance – having a data property that is a date in some date range, or that matches a regular expression. It becomes possible to create chains that are complex branched trees.

  ObjectPropertyChain(:a :b :c)
  ObjectHasValue(:abc :FOO) 
  ObjectPropertyChain(:d :selfIsABCEqualFoo :f)

It solves (or is a solution to) the problem of “decorating” properties with additional data by pulling them out into individuals, and still being able to reason over inferences. We see this in the TDWG vocabulary, where rather than taxon relationship properties, there exist taxon relationship objects with a from taxon, to taxon, and a relationship type.

Consider this:

  ObjectHasValue(:relationshipType :ISPARENTOF) 
    ObjectInverseOf(:fromTaxon) :selfIsParentofRelation :toTaxon

Not exciting? How about this:

    ObjectHasValue(:relationshipType :ISPARENTOF)
      DatatypeRestriction(xsd:string xsd:pattern ".*Paul Murray.*"^^xsd:string )
    ObjectInverseOf(:fromTaxon) :selfIsPaulsParentofRelation :toTaxon)

Now then: what are all the subtaxa of this taxon according to Paul Murray? Declare :paulsParentOf to be transitive, and you have your answer.

What you can’t do in OWL DL is create dependency loops in your property definitions. Doing this makes OWL undecidable, apparently. But still – the expressiveness that you can get with this technique is astonishing, and I’m pretty sure it works and is OWL DL.

It may be that this technique is already well known: that I have re-invented the wheel. If not, then I hereby dub it “Paul’s Mechanism”.



November 2, 2010

Class diagram as I have been discussing it:

Existing dwc ?