Sensemaking AI · Sensemaking Semantic Web
Submodule 2.1 · Modeling

RDFS and class hierarchies.

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.

Module 2 · Weeks 4–6 Requires Fuseki + Protégé ~2 hours hands-on RDFS · entailment · class hierarchy
Checking for Fuseki at localhost:3030…

The promise made in the 1.1 workbook.

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.

The core shift

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.

What to load before this workbook

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.

A small vocabulary with large consequences.

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.

rdfs:subClassOf

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.

rdfs:subPropertyOf

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.

rdfs:domain

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.

rdfs:range

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.

From the starter ontology

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
The open-world assumption, again

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.

The inference rules, made concrete.

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 nameIf 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.

Transitive and symmetric properties

OWL adds a few property characteristics that RDFS alone cannot express:

Why the starter ontology avoids transitivity

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.

Explore the class hierarchy in Protégé.

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.

Protégé walkthrough — open to expand all steps
1 Open the starter ontology expand

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.

Screenshot: Active Ontology tab showing the naruto ontology IRI, version info "starter", and the dcterms:created annotation visible in the Annotations panel.
2 Explore the class hierarchy expand

Click the Classes tab. Expand the owl:Thing node in the Class hierarchy panel on the left. You should see:

  1. naruto:Characternaruto:Ninja
  2. naruto:Arc (subclass of schema:CreativeWork — may show as an IRI)
  3. naruto:Jutsu, naruto:Team, naruto:Village

Click 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.

Screenshot: Classes tab with naruto:Ninja selected. Left panel shows the class tree with Character > Ninja indented. Right panel shows "SubClass Of: naruto:Character" in the Description section.
3 Explore object properties expand

Click the Object Properties tab. Select naruto:rivalOf. In the Description panel, confirm you see:

  • Characteristics: Symmetric
  • Domains: naruto:Ninja
  • Ranges: naruto:Ninja

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.

Screenshot: Object Properties tab with naruto:rivalOf selected. Right panel shows Characteristics: Symmetric, Domains: naruto:Ninja, Ranges: naruto:Ninja.
4 Run the RDFS reasoner expand

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.

Screenshot: Classes tab, naruto:Ninja selected, reasoner active. Description panel shows two sections: "Asserted" with SubClassOf: naruto:Character, and "Inferred" showing additional superclasses including schema:Person.
5 Observe symmetric property inference expand

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.

Screenshot: Individuals tab, naruto:SasukeUchiha selected. Property Assertions panel shows naruto:rivalOf naruto:NarutoUzumaki in the inferred section (displayed in a different color from asserted facts).
6 Observe inverse property inference expand

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.

Screenshot: Individuals tab, naruto:NarutoUzumaki selected. Inferred property assertions include naruto:studentOf naruto:KakashiHatake.

Five queries on the ontology schema and data.

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.

q01
What classes are defined in the ontology, and what is each a subclass of?
Pattern: querying the schema itself · rdfs:subClassOf as data
Open Fuseki ↗
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
q02
What are all the object properties, their domains, and their ranges?
Pattern: introspecting property declarations · rdfs:domain and rdfs:range as data
Open Fuseki ↗
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
q03
List all ninja with their rank and village.
Pattern: instance data query · OPTIONAL for rank · ORDER BY village
Open Fuseki ↗
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
q04
Which ninjas share an arc — and are they from different villages?
Pattern: multi-hop traversal · FILTER for cross-village · the value-add over co-appearance
Open Fuseki ↗
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
q05
CONSTRUCT: materialize all studentOf triples from senseiOf data.
Pattern: CONSTRUCT · materializing what a reasoner would derive · inverseOf in action
Open Fuseki ↗
PREFIX naruto: <https://sensemaking-ai.com/ns/naruto#>

CONSTRUCT {
  ?student naruto:studentOf ?sensei .
}
WHERE {
  ?sensei naruto:senseiOf ?student .
}

What to read and where to go next.

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.

Reference

W3C RDFS spec

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.

Tool

Protégé

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.

Starter data

naruto-ontology-starter.ttl

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.

Next submodule

Submodule 2.2 — OWL essentials

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.

Cheatsheet

Module 2 quick-reference (coming soon)

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.