Pellet 2.1: Introducing Terp

Pellet 2.1 introduces Terp, a new syntax for querying OWL ontologies. Terp is a combination of Turtle and Manchester syntax; it was designed for maximum legibility and conciseness. With Terp, we have a query language for domain knowledge, rather than a query language for the syntax which that domain knowledge is encoded in.

SPARQL queries against OWL data are unnecessarily complex because SPARQL is aimed at RDF triples: to query OWL with SPARQL, you have to query the RDF serialization of OWL, which was never intended for human consumption. To make matters worse, having encoded knowledge in abstract OWL axioms, you’re then forced to care far too much about syntactic peculiarities to query that knowledge, which defeats some of the point of using OWL to begin with.

For example, if I try to query some information encoded with the Galen (medical terminology) ontology to find all solid structures in a leg, I have to write the following query in SPARQL:


SELECT ?structure 
WHERE {
  ?structure rdfs:subClassOf [ owl:intersectionOf (:SolidStructure
    [owl:onProperty :isStructuralComponentOf ; owl:someValuesFrom :Leg])].}

The syntax for specifying restrictions is very verbose; it requires creating an anonymous class and specifying two triples. Additionally, just to specify a logical conjunction (SolidStructure AND a part of a leg), you have to use the owl:intersectionOf construct, which is itself pretty verbose. Terp addresses these problems by letting us use Manchester syntax constructs that were designed specifically for OWL, rather than for RDF triples. We’ll publish a formal grammar for Terp at some point; but, basically, you can replace any subject or object in Turtle with some arbitrary Manchester syntax.

Terp also allows us to write logical operators in a more readable way. The Galen query for solid structures in a leg can be written in Terp thusly:


SELECT ?structure 
WHERE 
{?structure rdfs:subClassOf (:SolidStructure and :isStructuralComponentOf some :Leg ).}

The Terp query is obviously more legible and easier to write. The ability to specify property restrictions in one statement prevents the clutter of nested anonymous classes often visible in SPARQL. Consider the following SPARQL query that finds classes of body structures that have solid topology:


SELECT ?structure
WHERE 
{?structure owl:equivalentClass [owl:intersectionOf (:BodyStructure
                        [owl:onProperty :hasTopology ; 
                         owl:someValuesFrom [ owl:intersectionOf (:Topology
                                [owl:onProperty :hasState ; 
                                owl:someValuesFrom :topologicallySolid])])].}

There are only two levels of nesting there, and it is already quite difficult to understand the meaning of the query when looking at it for the first time. The meaning of the corresponding Terp is still clear, despite the nesting:


SELECT ?structure 
WHERE {?structure owl:equivalentClass (:BodyStructure and :hasTopology 
                              some ( :Topology and :hasState some :topologicallySolid)).}

Using owl:intersectionOf for conjunction and owl:union for alternative is unnecessarily verbose and can feel unnatural. This is especially apparent when dealing with nested conditions, which lead to readability issues, especially when conjunction and disjunction is mixed with property restrictions. An example can be seen in the following SPARQL query, which queries LUBM-encoded data for persons who are either full professors or lecturers and who teach a graduate course:


SELECT ?person 
WHERE 
{?person a [owl:intersectionOf ([ owl:unionOf( :FullProfessor :Lecturer)]
                        [owl:onProperty :teacherOf ; owl:someValuesFrom :GraduateCourse])].}

The corresponding Terp query is


SELECT ?person 
WHERE 
{?person a ((:FullProfessor or :Lecturer) and (:teacherOf some :GraduateCourse)).}

Terp supports the full set of OWL2 restrictions on properties, including cardinality restrictions. The following Terp query demonstrates the use of cardinality restrictions: it asks for wines made of at least two kinds of grape:


SELECT ?wine 
WHERE 
{?wine a ( wine:Wine and wine:madeFromGrape min 2).}

In many OWL-based applications, queries aren’t written by hand, they’re generated by a program. But even in that case we think Terp is a win since those queries inevitably have to be debugged by someone. In a future release of Pellet, we will likely add some additional syntactic sugar for some of the builtin OWL2 properties to be shorter and more legible.


Colophon

This is Thinking Clearly, a weblog by Clark & Parsia, LLC—read more about this site.

Follow us on Twitter RSS Feed