Primary reading
Allemang et al. — Ch 6–8
The conceptual heart of Module 2. Chapter 6 covers RDFS; Chapter 7 introduces OWL basics; Chapter 8 covers modeling patterns. Read in order alongside the submodule workbooks.
The schema layer on top of RDF data. How subClassOf, domain, and range give a reasoner something to act on — and why that changes what SPARQL can see.
In the Submodule 1.1 workbook, Challenge C4 asked you to query for rival relationships using sensemaking:rivalOf. The file declared it as owl:SymmetricProperty. But your plain SPARQL query returned only the asserted direction — not the symmetric inverse. The "Think about this" prompt asked: does plain SPARQL pick up inferred triples?
The answer was no. Plain SPARQL queries what is explicitly in the store. The symmetric inverse — if Naruto rivalOf Sasuke, then Sasuke rivalOf Naruto — would require a reasoner to materialize it. RDFS and OWL are the vocabulary for telling a reasoner what to derive. This submodule is where that thread resolves.
Module 1 established: RDF stores facts as triples; SPARQL retrieves them. Module 2 adds: RDFS and OWL declare schema rules that let a reasoner derive new triples from existing ones. A triple asserted in the data plus a rule in the schema equals new knowledge — without anyone explicitly writing the new triple.
Load modules/02-modeling/artifacts/naruto-ontology/naruto-ontology-starter.ttl into Fuseki's mythology dataset (or a new naruto dataset). The prefix for all queries is naruto: <https://sensemaking-ai.com/ns/naruto#>. The file contains the full class hierarchy, properties, example characters, and arc individuals from the three S-tier arcs.
RDFS (RDF Schema) adds just a handful of terms to RDF's base vocabulary. Four of them do most of the work. Each one is a triple in the ontology that tells a reasoner a rule about the data.
Every instance of the subclass is also an instance of the superclass. If naruto:Ninja rdfs:subClassOf naruto:Character, a reasoner infers that every Ninja is also a Character — without asserting it for each individual.
Every triple using the subproperty implies the same triple with the superproperty. If naruto:senseiOf rdfs:subPropertyOf foaf:knows, then every sensei-student pair is also a knows-pair in the inferred graph.
If any resource has a value for this property, the reasoner infers that resource is a member of the domain class. naruto:hasJutsu rdfs:domain naruto:Ninja: anyone with a jutsu is inferred to be a Ninja.
If any resource is the object of this property, the reasoner infers it is a member of the range class. naruto:hasJutsu rdfs:range naruto:Jutsu: anything that is the object of hasJutsu is inferred to be a Jutsu.
Here is how these terms appear in naruto-ontology-starter.ttl. Each declaration is a rule that a reasoner can fire:
# rdfs:subClassOf creates a class hierarchy naruto:Ninja rdfs:subClassOf naruto:Character . naruto:Character rdfs:subClassOf schema:Person . # Inference: every Ninja is also a Character and also a schema:Person # rdfs:domain fires on any subject that uses this property naruto:hasJutsu rdfs:domain naruto:Ninja ; rdfs:range naruto:Jutsu . # Inference: anything with a hasJutsu triple is a Ninja; # anything that IS a hasJutsu value is a Jutsu # owl:inverseOf works with RDFS reasoners too naruto:senseiOf owl:inverseOf naruto:studentOf . # Inference: wherever senseiOf is asserted, studentOf holds in reverse
RDFS entailment only adds inferred triples — it never removes them, and it never concludes that something is false because it is not stated. If a character has no naruto:hasJutsu triple, RDFS does not conclude they have no jutsu. It simply has no rule to fire. This was the open-world assumption from Submodule 1.1; it becomes more consequential as the schema gets richer. SHACL (Submodule 2.3) is the answer for applications that need closed-world constraints.
Three RDFS entailment rules cover most of what matters in practice. Each rule says: given these two triples in the store, derive this third triple.
| Rule name | If the store contains… | …derive |
|---|---|---|
| subclass inheritance | ?x a naruto:Ninja .naruto:Ninja rdfs:subClassOf naruto:Character . |
?x a naruto:Character . |
| domain inference | naruto:Gaara naruto:hasJutsu naruto:SandManipulation .naruto:hasJutsu rdfs:domain naruto:Ninja . |
naruto:Gaara a naruto:Ninja . |
| range inference | naruto:Gaara naruto:hasJutsu naruto:SandManipulation .naruto:hasJutsu rdfs:range naruto:Jutsu . |
naruto:SandManipulation a naruto:Jutsu . |
In the starter ontology, naruto:Gaara is explicitly typed as naruto:Ninja — so the domain inference produces a redundant triple. Domain and range inferences are most valuable when data arrives without type assertions: an external source might only assert the predicate-object pair, and the domain rule fills in the class membership automatically.
OWL adds a few property characteristics that RDFS alone cannot express:
owl:SymmetricProperty — if A P B, derive B P A. Used on naruto:rivalOf in the starter ontology.owl:TransitiveProperty — if A P B and B P C, derive A P C. Powerful; use with care. Transitivity on a large graph triggers a recursive closure computation that can be expensive. The starter ontology deliberately does NOT declare any transitive properties.owl:inverseOf — if A P B, derive B Q A where Q is P's inverse. Used on naruto:senseiOf / naruto:studentOf.The Module 2 README calls this the "transitivity trap." Declaring naruto:familyOf transitive would mean that Naruto and every member of the Uzumaki clan (scattered across the world, many unreachable in the graph) would be inferred to be related to every other Uzumaki. The reasoner would need to compute the full transitive closure — and it would keep firing as new data arrives. Transitivity is correct for some properties (geographic containment, taxonomic hierarchy) and catastrophic for others. The decision requires intent, not reflex.
Protégé is the standard tool for working with OWL ontologies. This walkthrough opens the starter Naruto ontology, explores the class hierarchy, and runs RDFS reasoning to observe what gets inferred. Expand each step when you are ready to work through it — the steps are independent, so you can skip ones you have already completed.
Protégé install notes are in resources/tools.md. Download from protege.stanford.edu if not already installed.
In Protégé: File → Open, navigate to modules/02-modeling/artifacts/naruto-ontology/naruto-ontology-starter.ttl, and open it. Protégé may ask about the format — select Turtle if prompted.
In the Active Ontology tab, confirm the ontology IRI reads https://sensemaking-ai.com/ns/naruto. If Protégé shows a blank IRI or an error, the file path may need adjustment.
Click the Classes tab. Expand the owl:Thing node in the Class hierarchy panel on the left. You should see:
naruto:Character → naruto:Ninjanaruto:Arc (subclass of schema:CreativeWork — may show as an IRI)naruto:Jutsu, naruto:Team, naruto:VillageClick on naruto:Ninja. In the Description panel on the right, confirm that SubClass Of: naruto:Character is listed. This is the rdfs:subClassOf assertion from the TTL rendered as Protégé's class description syntax.
Click the Object Properties tab. Select naruto:rivalOf. In the Description panel, confirm you see:
Now select naruto:senseiOf. Confirm: Inverse Of: naruto:studentOf. This is the owl:inverseOf assertion — the property that a reasoner uses to derive studentOf from senseiOf data.
From the menu: Reasoner → HermiT (or select Pellet if HermiT is not available). Then: Reasoner → Start Reasoner. Wait for the status bar to show "Reasoner: Synchronized."
Return to the Classes tab and click naruto:Ninja. The Description panel now shows two sections: the asserted description (what you wrote) and the inferred description (what the reasoner derived). You should see that Ninja is now inferred to be a subclass of schema:Person — because Ninja → Character → schema:Person forms a transitive subClassOf chain.
With the reasoner running, click the Individuals by class tab (or the Individuals tab). Select naruto:NarutoUzumaki. In the Property Assertions panel, you should see naruto:rivalOf naruto:SasukeUchiha listed as an asserted fact.
Now select naruto:SasukeUchiha. Look in the inferred property assertions (shown in a lighter color or a separate section). You should see naruto:rivalOf naruto:NarutoUzumaki — the symmetric inverse that was never explicitly written in the TTL.
This is the answer to Submodule 1.1 Challenge C4. The reasoner derived the reverse direction from the owl:SymmetricProperty declaration. Plain SPARQL against the raw TTL would not have seen it.
Still in the Individuals tab with the reasoner running, select naruto:NarutoUzumaki. In the inferred property assertions, look for naruto:studentOf naruto:KakashiHatake. The TTL asserts naruto:KakashiHatake naruto:senseiOf naruto:NarutoUzumaki. The reasoner derives the inverse because naruto:senseiOf owl:inverseOf naruto:studentOf is declared.
Note: not all RDFS reasoners implement owl:inverseOf — it is technically an OWL term. HermiT and Pellet both handle it; a pure RDFS reasoner would not. In production, confirm which entailment regime your triplestore supports before relying on property inversions.
These queries run against the raw naruto-ontology-starter.ttl in Fuseki — without an OWL reasoner. They return only explicitly asserted triples. The "Think about this" prompts ask what would change if you ran the same query against a reasoner-enriched store.
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#> SELECT ?class ?label ?parent WHERE { ?class a owl:Class ; rdfs:label ?label . OPTIONAL { ?class rdfs:subClassOf ?parent . } FILTER (LANG(?label) = "en" || LANG(?label) = "") } ORDER BY ?label
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#> SELECT ?property ?label ?domain ?range WHERE { ?property a owl:ObjectProperty ; rdfs:label ?label . OPTIONAL { ?property rdfs:domain ?domain . } OPTIONAL { ?property rdfs:range ?range . } FILTER (LANG(?label) = "en" || LANG(?label) = "") } ORDER BY ?label
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX skos: <http://www.w3.org/2004/02/skos/core#> PREFIX schema: <https://schema.org/> PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#> SELECT ?name ?rankLabel ?villageName WHERE { ?ninja a naruto:Ninja ; naruto:canonicalName ?name ; naruto:memberOfVillage ?village . ?village rdfs:label ?villageName . OPTIONAL { ?ninja naruto:hasRank ?rank . ?rank skos:prefLabel ?rankLabel . FILTER (LANG(?rankLabel) = "en") } } ORDER BY ?villageName ?name
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX schema: <https://schema.org/> PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#> SELECT DISTINCT ?nameA ?nameB ?arcName ?villageA ?villageB WHERE { ?a naruto:canonicalName ?nameA ; naruto:memberOfVillage ?vA ; naruto:appearsInArc ?arc . ?b naruto:canonicalName ?nameB ; naruto:memberOfVillage ?vB ; naruto:appearsInArc ?arc . ?arc schema:name ?arcName . ?vA rdfs:label ?villageA . ?vB rdfs:label ?villageB . FILTER (?a != ?b && STR(?a) < STR(?b)) FILTER (?vA != ?vB) } ORDER BY ?arcName ?nameA
PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#> CONSTRUCT { ?student naruto:studentOf ?sensei . } WHERE { ?sensei naruto:senseiOf ?student . }
The conceptual heart of Module 2. Chapter 6 covers RDFS; Chapter 7 introduces OWL basics; Chapter 8 covers modeling patterns. Read in order alongside the submodule workbooks.
Short and readable. Section 2 defines the class and property terms; Section 3 covers the entailment semantics. Bookmark the property table — it is the authoritative reference for what each RDFS term means.
The standard ontology editor. This submodule uses it for RDFS walkthrough steps 1–6. Submodule 2.2 uses it heavily for OWL restrictions and the HermiT reasoner. Install before starting.
The ontology file for this workbook. Read the comments alongside the Protégé steps — each design decision is annotated. Exercise 2.3 asks you to extend this into the full 1.0.0 release.
Picks up where RDFS ends: classes, individuals, restrictions, and the five OWL profiles. The Protégé walkthrough adds cardinality restrictions and runs HermiT to observe class membership inferences.
RDFS and OWL term quick reference — what each term asserts, what a reasoner derives from it, and common mistakes. Available when Module 2 materials are complete.