Before commit eb2f0e04, I used to have this function in tawny.owl.

(defbdontfn
  add-subclass
  {:doc "Adds one or more subclass to name in ontology."
   :arglists '([name & subclass] [ontology name & subclass])}
  [o name subclass]
  (add-axiom o
             (.getOWLSubClassOfAxiom
              (owl-data-factory)
              (ensure-class o name)
              (ensure-class o subclass))))

The idea is, as the name suggests to add a subclass relationship to the ontology; on the face of it, everything looks fine. However, a closer look at the OWL API raises a question:

getOWLSubClassOfAxiom(OWLClassExpression subClass, OWLClassExpression superClass)

The subclass parameter in Clojure maps to the superClass parameter in Java. The subclass in Clojure is actually the superclass.

If we compare the property equivalent in Tawny, things seem more regular:

(defbdontfn add-superproperty
  "Adds all items in superpropertylist to property as
a superproperty."
  [o property superproperty]
  (add-axiom o
             (.getOWLSubObjectPropertyOfAxiom
              (owl-data-factory)
              (ensure-object-property o property)
              (ensure-object-property o superproperty))))

and the equivalent Java:

getOWLSubObjectPropertyOfAxiom(OWLObjectPropertyExpression subProperty,
                               OWLObjectPropertyExpression superProperty)

The names of the parameters are now the same way around in Clojure and Java. So, have I made a mistake in Tawny with subclass handling? Actually, no, because we get strangeness at a different point with properties; consider the object-property-handlers which map between frames and the functions which implement them:

(def ^{:private true} object-property-handlers
  {
   :domain add-domain
   :range add-range
   :inverse add-inverse
   :subproperty add-superproperty
   :characteristic add-characteristics
   :subpropertychain add-subpropertychain
   :disjoint add-disjoint-property
   :equivalent add-equivalent-property
   :annotation add-annotation
   :label add-label
   :comment add-comment})

So, the :subproperty: frame is implemented with the add-superproperty function. As might be expected, :subclass is implemented with add-subclass

Even without this oddness, the problem can be seen when considering just the add-* functions. Consider, add-label:

(defbmontfn add-label
  "Add labels to the named entities."
  [o named-entity label]
  (add-annotation
   o
   named-entity
   [(tawny.owl/label label)]))

The semantics of this are that the third argument, label, is added to the second, named-entity as a label. It is slightly more complex than this; the b in defbmontfn means broadcast — add-label is actually variadic and flattens meaning that any number of labels can be added.

With add-subclass the semantics are reversed; the second argument becomes a subclass of the third (or, again, because of broadcasting, the third or subsequent arguments). And add-subclass is inconsistent here — all of the other add-* have the same semantics as add-label.

So, clearly, both add-subclass and the :subproperty frame have problems, and are not consistent with the rest of the API. Two important parts of Tawny-OWL have been implemented backward. How did this happen?

Investigating Manchester Syntax

We can investigate this further, by considering another inconsistency with Tawny. Considering the object-property-handlers above, we can see that while :subproperty is implemented with add-superproperty, :subpropertychain is implemented with add-subpropertychain.

The slot names in Tawny come (nearly) directly from Manchester syntax; so, let us compare Manchester syntax with the functional syntax for sub-properties and sub-property chains, using the OWL Primer. In Manchester syntax:

ObjectProperty: hasFather
   SubPropertyOf: hasParent

In functional syntax:

SubObjectPropertyOf(
   :hasFather
   :hasParent
)

Compare this to the equivalent declaration for subproperty chain.

ObjectProperty: hasGrandparent
   SubPropertyChain: hasParent o hasParent

Or in functional syntax:

SubObjectPropertyOf(
   ObjectPropertyChain( :hasParent :hasParent )
   :hasGrandparent
 )

The filler for SubPropertyChain: comes first, while for SubProperty: is comes second.

This suggests that the SubPropertyOf: and SubPropertyChain: frames are back-to-front from each other (this is the values of the slots appear in different orders in the two syntaxes). So, with the former, SubPropertyOf: I am stating that the entity (hasFather) is related to the filler (hasParent) and that the filler (hasParent) is the super property. With the latter, SubPropertyChain: I am stating that the entity (hasGrandparent) is related to the filler (hasParent o hasParent) and that the filler (hasParent o hasParent) is the sub property.

So, the two appear to be inconsistent with each other. So, let’s consider a further analysis of the other slots. Consider, for example:

A
  Annotations: rdfs:label B

which means B is an annotation of A.

A
 EquivalentTo: B

means B is equivalent to A (or, in this case, that A is equivalent to B as equivalance is symmetrical).

A
  Domain: B

means B is a domain of A

A
  Type: B

means B is a type of A.

All of these are consistent with each other: the filler (B) has a relationship to the entity (A) which is defined by the slot (type), with the caveat that the EquivalentTo relationship is symmetric.

Now

A
  SubClassOf: B

A
  SubPropertyOf: B

are backward: the entity (A) has a relationship to the filler (B) defined by the slot (SubClassOf:, SubPropertyOf:) - it’s why the Of preposition has been added. It is not possible to add the same preposition to the other slots; although it is possible to add has to the beginning. So, for example, the natural language semantics of these statements preserves their OMN meaning:

A HasAnnotation: B
A HasType: B
A HasKey: B

Of these, only the latter is actually OMN. The only other slots with prepositions are EquivalentTo and SameAs — you could change these to has as well.

A HasEquivalent: B
A HasSame: B

This probably reduces the readability over all, but it does at least maintain the semantics. It is for this reason that I say SubClassOf: is backward; to be consistent, it should be Super:

So

A Super: B

means B is a superclass of A. Now, we could add the has preposition to the start, while preserving the natural language semantics.

A HasSuper: B

Everything that I have said here is also true of SubPropertyOf: which behaves in the same way as SubClassOf: (i.e. backwards wrt to most slots).

Going back to the very early question, SubPropertyChain: (note, not SubPropertyChainOf:) is the same way around as most slots and the opposite way around from SubPropertyOf:

A SubPropertyChain: B o B

could be replaced with

A HasSubPropertyChain: B o B

In summary, for Manchester syntax SubClassOf: and SubPropertyOf: frames are backward with respect to all the other frames.

The Implications for Tawny

Unfortunately, the situation in Tawny-OWL was slightly worse than for Manchester syntax. While writing an early version of the karyotype ontology (n.d.a) by hand, I found typing too hard so removed the prepositions (:subclass and not :subclassof). Combined with the lack of CamelCase, this seemed a cleaner syntax. But it has exacerbated the issues described here.

Although, I have become aware of this problem before the release of the first full version of Tawny, I decided that consistency with Manchester syntax was worth the hassle. My recent experiments with literate ontologies (n.d.b) however have made me realise that I could not leave the situation as it is. One key feature of Tawny is that it (normally) forces declaration of entities before use which avoids simple spelling mistakes common when writing Manchester syntax by hand. However, only having access to a :subclass slot means that ontologies must be declared from the top of the inheritance hierarchy downward. For a literate ontology, this restriction seems unnecessary, and places an unfortunate emphasis on the upper ontology. I would like also to be able to build from the bottom up.

Neither having the semantics of add-subclass backward, nor the :subproperty add-superclass solution work well as it stands, and extending this to a :superclass slot would make the situation worse. In short, the only sensible fix was to diverge from OWL Manchester syntax, and deprecate the use of :subclass and :subproperty. At the same time, I decided to remove some extra typing. Therefore, :subclass has become :super (shortening and reversing the natural language semantics, retaining the logical semantics), and the new slot :sub has been added. Likewise, :subproperty has become :super and a new slot :sub introduced for properties also. As well as avoiding extra typing, removing the suffix has meant that I can leave :subclass and :subproperty in place but deprecated; the alternative of just reversing their semantics seemed unfortunate. Only the semantics of add-subclass has been broken, being reversed.

The inconsistency with Manchester syntax is currently a little painful, especially as the :subclass slot has been around since the early days of Tawny (n.d.c) The advantage, however, is that I have a simple rule to remember: A :s B means “A has :s B” or equivalently, “B is :s of A”. For this reason, and because it paves the way for richer literate ontologies, I feel that this is a good change.