RDFS and OWL 2: From Vocabularies to Description Logic

RDF gives you triples; it does not give you meaning. Nothing in ex:P101 a ex:Pump tells a machine that pumps are equipment, that everything installed at a site is a physical object, or that nothing can be both a Pump and a Pipeline. Those commitments live one layer up, in RDFS and OWL 2. This lesson climbs that layer deliberately: first the modest, robust vocabulary machinery of RDFS, then the description-logic power tools of OWL 2, then the profiles that decide whether your reasoner finishes in milliseconds or dies overnight, and finally the modelling errors that account for most real-world OWL pain.

RDFS and OWL 2: From Vocabularies to Description Logic

RDFS: the modest layer that does most of the work

RDF Schema adds a small vocabulary for describing vocabularies, and its four workhorses carry a surprising fraction of production semantics. With rdfs:subClassOf you build class hierarchies: ex:Pump rdfs:subClassOf ex:Equipment means every pump is equipment, and a reasoner will type every pump instance as Equipment automatically. With rdfs:subPropertyOf you do the same for properties: ex:hasCentrifugalPump rdfs:subPropertyOf ex:hasPump. With rdfs:domain and rdfs:range you attach expectations to properties: ex:installedAt rdfs:domain ex:Equipment and rdfs:range ex:Site.

One RDFS behaviour surprises everyone with a database background, and it follows directly from the open-world logic of lesson 4: domain and range are inference rules, not filters. If you assert ex:Contract42 ex:installedAt ex:Aberdeen2, RDFS does not reject the triple as a violation; it concludes that Contract42 is Equipment. This is the single most common source of silent nonsense in beginner graphs: a mis-scoped domain axiom quietly reclassifies half your data. The professional posture is to use domain and range sparingly and generally, and to enforce expectations with SHACL (lesson 11), which really does reject. Alongside these, rdfs:label and rdfs:comment carry the human-readable names and definitions that make an ontology usable; treat them as mandatory, because an undocumented class is a future dispute.

OWL 2: saying enough that a machine can disagree with you

RDFS can say that classes nest. It cannot say that they exclude each other, that a property never has two values, or what membership of a class actually requires. OWL 2, the W3C’s description-logic language over RDF, adds exactly this expressive power, and the OWL 2 Primer is the reference companion for everything in this section. The heart of OWL is the class expression: instead of only naming classes, you construct them. From existing classes you build intersections, unions and complements; from properties you build restrictions, which are anonymous classes defined by how their members relate to other things.

Restrictions come in a few load-bearing shapes. An existential restriction, written in Manchester syntax as hasTopping some CheeseTopping, is the class of things with at least one cheese topping. A universal restriction, hasTopping only VegetableTopping, is the class of things whose every topping is vegetable, including, treacherously, things with no toppings at all: the empty case satisfies “only” vacuously, a classic exam trap and production bug. Cardinality restrictions (hasTopping exactly 3, hasCustomer max 1) count relationships. hasValue pins a property to a specific individual. Combined with equivalence axioms, these give you the two fundamentally different kinds of class definition: a subclass axiom (Margherita subClassOf hasTopping some TomatoTopping) states a necessary condition, while an equivalence (VegetarianPizza equivalentTo Pizza and hasTopping only VegetableTopping) states necessary and sufficient conditions. Only the latter lets a reasoner classify unseen individuals and discover subsumptions for you; ontologies made entirely of primitive subclasses give a reasoner nothing to do. The famous Stanford pizza tutorial has taught this distinction to two decades of students, and it survives modernisation intact: the “aha” moment is still watching the reasoner file MargheritaPizza under VegetarianPizza because the definitions entail it, not because anyone said so.

Property characteristics extend the same discipline to relationships. You can declare a property transitive (partOf), symmetric (adjacentTo), asymmetric (properPartOf), functional (at most one value: hasBirthDate), inverse functional (a value identifies its subject: hasPassportNumber, the logical backbone of entity resolution), reflexive or irreflexive, and declare inverses (hasPart, isPartOf). Disjointness deserves special emphasis: OWL does not assume classes are disjoint, so without ex:Pump owl:disjointWith ex:Pipeline a reasoner will happily let an individual be both. Well-axiomatised sibling disjointness is what turns a reasoner from a passive indexer into an error detector that catches integration mistakes at load time.

Worked example · the Aberdeen-2 asset register

Where we left it: instance data exists, partitioned by source, but nothing says what ex:Pump means.

Schema v0.1 for the register, four axioms doing four different jobs:

ex:Pump  rdfs:subClassOf ex:Equipment .
ex:Pump  owl:disjointWith ex:Pipeline .
ex:installedAt rdfs:domain ex:Equipment ; rdfs:range ex:Site .
ex:hasPart a owl:TransitiveProperty .

Now watch the domain axiom earn its warning label. A clerk in the maintenance system links the contract to the site through the wrong field, and the feed emits ex:Contract42 ex:installedAt ex:Aberdeen2. RDFS does not reject it. It concludes, with impeccable logic, that Contract42 is Equipment, and the platform’s equipment count quietly gains a maintenance contract. Detection arrives only when we also assert what Contract42 is and what it cannot be: add ex:Contract42 a ex:Contract and ex:Contract owl:disjointWith ex:Equipment, and the reasoner now reports a genuine inconsistency pointing straight at the bad triple. That is the division of labour to internalise: domain and range axioms reclassify, silently; disjointness is what converts a silent reclassification into a caught error. The register keeps its domain axioms few and general, and its sibling classes disjoint by default.

State of the register: schema v0.1 with a working error detector. What it still cannot do is recognise that three source systems call the same thing by three different names, which is the next three lessons’ job.

The profiles: EL, QL, RL and what each buys

Full OWL 2 DL reasoning is decidable but expensive (worst-case doubly exponential). The standard therefore defines three profiles, each a syntactic subset with polynomial-time reasoning, each engineered for a different workload; the normative details are in the OWL 2 Profiles specification. Choosing a profile early is one of the highest-leverage architectural decisions in the stack, and lesson 15 pairs it with reasoner choice.

OWL 2 profiles: a selection matrix
Profile What you give up What you get Built for Flagship use
OWL 2 EL Universal restrictions, cardinality, inverses, unions Polynomial classification of enormous class hierarchies Huge terminologies rich in existential definitions Biomedical ontologies: SNOMED CT (300,000+ classes), Gene Ontology; reasoner: ELK
OWL 2 QL Most construction beyond basic hierarchies and domains/ranges Query answering rewritable into SQL over unchanged relational data Ontology-based data access over existing databases Virtual graphs over enterprise RDBMSs
OWL 2 RL Axioms that cannot compile to forward-chaining rules Rule-based materialization inside triple stores at data scale Large ABoxes needing scalable inference Production triple stores (GraphDB, RDFox and peers implement RL rulesets)
OWL 2 DL (full) Nothing expressively, tractability guarantees instead Complete SROIQ(D) reasoning Design-time modelling, moderate ABoxes Ontology authoring and QA with HermiT or Pellet

The pattern to internalise: profiles are workload declarations. EL says “my complexity is in the class hierarchy”. QL says “my data stays relational”. RL says “I want inference materialised over big instance data”. Full DL says “I am designing and want maximum error detection, and my ABox is small enough to afford it”. Mixed architectures are normal: author in DL for maximum checking, deploy the deliverable subset under RL in the production store.

What breaks · “a pump has one impeller, so make it functional”

Every mechanical engineer will confirm that P-101 has exactly one impeller, so the modeller reaches for the obvious axiom:

ex:hasImpeller a owl:FunctionalProperty .
ex:P101 ex:hasImpeller ex:IMP12 .   # from the 2021 archive export
ex:P101 ex:hasImpeller ex:IMP77 .   # from the current live export

Both exports are true, in their own eras: IMP-12 was swapped out for IMP-77 by work order WO-2022-114. The reasoner, seeing a functional property with two values and no unique-name assumption, draws the only conclusion open to it: ex:IMP12 owl:sameAs ex:IMP77. Two physical impellers, one in the pump and one in a scrap skip, are now one individual, their serial numbers become interchangeable, and the warranty claim on IMP-77 happily cites IMP-12’s service history. Assert them differentFrom and the entire ontology becomes inconsistent instead, which at least is loud. The real defect is in the sentence, not the machinery: “one impeller” meant one impeller at a time, and “at a time” is exactly what an atemporal functional axiom cannot say. State-based modelling from lesson 3 says it cleanly: each temporal part of P-101 has one impeller. Functional properties belong on relations that hold once forever, like hasSerialNumber.

The errors everyone makes

A handful of mistakes account for most OWL grief in the wild, and all are cheap to avoid once named. Class versus instance confusion: modelling Boeing747 as an instance of Aircraft when your data needs individual airframes typed as Boeing747; the test is whether the thing has its own instances. Misused universal restrictions: writing hasTopping only CheeseTopping while forgetting it says nothing about existence, so the intended “must have cheese” needs some as well. Domain and range as constraints: covered above, and worth repeating because it reclassifies data silently. Property hierarchies ignored: fifteen unrelated site-link properties where one general property with subproperties would let queries generalise. Missing disjointness: the reasoner cannot catch category errors you never made expressible. The sameAs cannon: casually linking records with owl:sameAs during integration, which under no-unique-names logic merges every property of both individuals, propagating errors graph-wide; prefer weaker links (skos:closeMatch, lesson 29) until identity is proven. And gratuitous expressivity: every exotic axiom narrows your profile options and slows reasoning; an axiom that answers no competency question is cost without benefit, a theme lesson 27 turns into a testing discipline of its own.

Check yourself

The register declares ex:maintainedUnder rdfs:domain ex:Equipment and nothing else relevant. A feed error loads ex:Aberdeen2 ex:maintainedUnder ex:Contract42, linking the site itself to the contract. What does the reasoner do?

  1. Rejects the triple, because Aberdeen-2 is a site, not equipment.
  2. Accepts the triple and infers that ex:Aberdeen2 is Equipment.
  3. Reports an inconsistency between the Site and Equipment types.
  4. Nothing; domain declarations are documentation for humans.
Show the answer, and why each wrong option is wrong

B is correct. Domain axioms are inference rules: from “x maintainedUnder y” and the domain declaration, the reasoner derives “x is Equipment”. The platform is now equipment, silently, and every equipment rollup is wrong by one site.

A is the constraint misconception: nothing in RDFS or OWL ever rejects a triple; rejection is SHACL’s job, two lessons from now. C would require the ontology to know that Site and Equipment are disjoint, and the scenario declares no such axiom; without it the reasoner sees no conflict in Aberdeen-2 being both. Adding that disjointness is precisely how you turn this silent error into a caught one. D is the opposite misconception: domain declarations are among the most consequential axioms you can write, which is why this lesson tells you to use them sparingly and generally.

Where this leaves you

You can now read the entire semantic stack’s schema layer: RDFS for hierarchies, labels and lightweight expectations; OWL 2 restrictions and equivalences for machine-checkable definitions; property characteristics for relational logic; disjointness for error detection; profiles for tractability. The skill that compounds from here is judgement about how much logic to buy: enough that the reasoner can catch your mistakes and discover your implicit hierarchy, not so much that you are modelling metaphysics nobody queries. That judgement develops through practice, and the guided modelling exercises in the ontology foundations and semantic standards course are built to accelerate exactly this. Before we return to modelling method in module 3, you need to interrogate graphs fluently: after a three-lesson detour through SKOS and controlled vocabularies, lesson 10 teaches SPARQL by mapping it onto the SQL you already know.

RDFS and OWL 2: From Vocabularies to Description Logic in practice