Manchester Syntax is a bit backward
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.
———. n.d.a. https://arxiv.org/abs/1305.3758.
———. n.d.b. https://www.russet.org.uk/blog/2979.