Using FOAF and OWL

The FOAF ontology has been updated to be much more OWL friendly, so much of this note is no longer relavent, and the code will probably produce erroneous results

Motivation

When creating new ontologies on the web, it's often useful to extend other ontologies in order to promote more understanding between tools.

In the case extending of FOAF, using OWL as the extension language makes sense, since FOAF is already using some of the expressive power of OWL.

Unfortunately, since FOAF makes only partial use of OWL (along with some quirks), it is difficult for many OWL tools to understand the FOAF ontology. Thus, it is often necessary to process the FOAF ontology into a usable form.

FOAF and OWL Issues

There are roughly two levels of issues that deter OWL tools from using the FOAF ontology. The first of those are just syntactic issues, which are relatively easy to fix. The rest are modeling issues, which require some judgment.

Syntactic Differences

The syntactic issues with OWL compatibility are solely a matter of missing triples. These involve properly typing properties and classes so they're relatively easy to fix.

Labeling Classes

Classes in OWL need to be labeled as OWL:Class. Most tools understand it enough when you use RDFS:Class, but it's good form (and less warnings) to go ahead and label it.

Labeling Properties

Labeling properties is important to OWL tools - it tells them how to handle the various uses of them. Some tools, like OWLApi, try to guess the type of the property in the presence of instances, but can often get it wrong otherwise.

The three main categories of properties are Annotation, Datatype, and Object properties.

Annotation properties are usually meant to have extra-reasoning meaning, and thus aren't dealt with by the standard tableaux algorithms. 'wot:assurance' is one such property, and 'foaf:membershipClass' is another. Annotation properties are also properties that have to deal with non-individuals (classes, properties, ontologies) that aren't in the rdf, rdfs, or owl namespaces. dc:description and dc:date are examples of these uses (at least as used in foaf).

Datatype properties deal with relating instances to literal values, such as foaf:name is one such property.

Object properties relate instances to other instances, such as foaf:knows and foaf:fundedBy.

One advantage of labeling the properties is that you can now drop the range and domain restrictions that point to rdf:Resource or rdf:Literal.

Picking your OWL Level

OWL Full is a subset of first order logic, and is theoretically implementable in reasoners like Vampire. However, as of yet, no one has implemented all of OWL Full. Thus, depending on your tool set, you may need to adjust the ontology.

Fitting into OWL-Full

Although FOAF is technically sitting in OWL-Full, the less you can be in it, the better the tools can handle it. Thus, in the spirit of this, these are changes that minimally effect the meaning of the foaf ontology.

The first change is to rip out the imports of the OWL and RDFS ontologies. The owl ontology itself states:

"""
    We do not expect people to import this file
    explicitly into their ontology. People that do import this file
    should expect their ontology to be an OWL Full ontology. 
"""

There are valid reasons to import the OWL ontology, but they mostly deal with extending OWL itself. Since FOAF isn't particularly extending the language (foaf:membershipClass excluded), dropping the imports of owl and rdfs is a painless change.

Down to OWL-DL

Going down to OWL-DL is a little bit more painful.

The least painful of these changes is removing the domains and ranges that point to rdf:Resource. Since in the rdfs schema rdfs:Class is a subclass of rdf:Resource, this means that any of these properties could point to a class as well as an instance. Since this isn't the usual intention (judgment call here), it's safe to either drop the restriction since it can be inferred by the label of owl:ObjectProperty, or replace the restriction with a pointer to owl:Thing.

Also, since annotation properties can't have ranges or domains, the domain and range of foaf:membershipClass needs to be removed. It may be that foaf:membershipClass should just be removed altogether, since it can be more generally modeled with standard owl constructs.

A little bit bit more annoying is the subPropertyOf relationship between foaf:name and rdfs:label. Since in OWL, rdfs:label is defined as an annotation property, it can't have any sub properties. There is work in reasoners such as Pellet to support this, but it isn't supported by the standard. Thus, to be in OWL-DL, you need to drop this relationship. Once it's dropped, it's safe to have foaf:name as an owl:ObjectProperty.

Finally, annoying as it is, owl:InverseFunctionalProperty is not supported on datatype properties. Again, there is work going on to support this, but it's more annoying to implement in a complete fashion than annotation property relationships. So the IFP type needs to be dropped on mbox_sha1sum and some of the foaf:nick sub properties.

Note that jabber (as xmpp) has a uri scheme (xmpp:), and thus probably shouldn't be a sub property of foaf:nick as it's more similar to a mailbox.

As a side-side rant, IFPs are useful for data merging, but make a lousy system for identification (in the place of URIs). See the last two months of comments on public-rdf-dawg and public-rdf-dawg-comments for example problems that arise.

Little bit more to OWL-Lite

Finally, if your system can't handle disjoints, then once you complete the above changes, removing owl:disjointWith will put you into OWL-Lite.

Conclusions

Automating the Changes

If you want to be compatible with various OWL tools, yet want to keep up with the recent changes to the foaf ontology, you need to automate the processsing of the spec.

In short, if you've identified which level of OWL that your application needs, you can download foaf_clean.py at http://www.mindswap.org/2005/foaf_cleaner/foaf_cleaner.py and run it with '-level <LEVEL>' where <LEVEL> is 'full', 'dl', or 'lite'. foaf_cleaner provides simple command line help with '--help'.

foaf_cleaner requires python 2.4 and rdflib 2.1, and is distributed under the MIT license.

RDFLib output is a little rough, so you might want to run it through your own rdf prettifier. Unfortunately, rdf unparsing is in a sad state at the moment, and I wish there were more apis that facilitated custom output :(.

I've run the foaf spec through foaf_cleaner with '--level=dl --clean', cleaned up the output with a devel copy of swoop, plus a couple of minor hand edits to produce http://www.mindswap.org/2003/owl/foaf which is used by a number of mindswap ontologies.

Suggestions for the spec

Applying the syntactic changes, plus removing owl:imports of rdfs and owl, plus changing the restrictions that point to rdf:Resource and removing the domain and range of membershipClass would put FOAF on a much better footing with most OWL tools. The rest of the changes are either much less likely to confuse systems, or would drop important restrictions that the community relies on. This level corresponds to the options '--full --restrictions' to foaf_cleaner.py.

As a supplement, official variants of the spec corresponding to the various owl levels could be published, and ontology (extension) writers could choose which spec would best fit with their application.

MINDSWAP is a W3C member