Triples and Graphs: Facts as a Network
📍 Where we are: Part I · Knowledge Representation — Chapter 1. Volume 1 closed with The Honest Verdict, which weighed an exact-but-brittle symbolic half against a robust-but-opaque neural half on one shared academic world; Volume 2 now zooms in on that world and asks the most basic question of all — how do you write a fact down so a machine can hold it?
Before a machine can prove anything, learn anything, or answer anything, it has to hold the facts in a shape it can walk through. This chapter is about that shape, and it is almost embarrassingly simple. Every fact is a triple, and a heap of triples is a graph. The whole of symbolic knowledge representation is built on that one move, so it is worth watching it happen slowly, on a world small enough to draw on a napkin.
Imagine a corkboard covered in index cards. Each card holds one tiny sentence — "alice advises bob," "bob authored p1," "p2 cites p1." Now pin a string from the name on the left of each card to the name on the right, and write the verb on the string. Step back, and without meaning to you have drawn a network: dots for the people and papers, labelled strings between them. You did not design the network; it simply is what a pile of one-sentence facts looks like when you connect the names. That network is a knowledge graph, and everything in this volume is what a machine can do once the facts are pinned up this way.
What this chapter covers
- The triple, the atom of a fact — every fact is an ordered
(subject, predicate, object); the binary relation instanceadvises(alice, bob)is the triple(alice, advises, bob), nothing more. - Triples are a labelled directed graph — individuals become nodes, predicates become edge labels, and the academic world becomes a graph you can draw and whose edges you can count.
- Grounded in the companion code — the 18 role edges are built straight from the Volume 1 facts by
ontology._build_abox, and the module reports its own size: 13 individuals, 18 role assertions. - Two kinds of edge — role assertions wire one individual to another (data edges); concept assertions wire an individual to its type (type edges), the first glimpse of the ABox.
- Why a graph beats a table — paths, reachability, and multi-hop questions fall out of simply following edges, giving a first taste of
grandAdvisorreached along a two-edge path. - The role schema at a glance — a table of the six roles, their arity, and how to read each one.
- The unsolved part — a bare graph fixes structure but not meaning: two graphs can disagree on what "advises" means, which is exactly the gap RDF and OWL are built to close.
The triple: the atom of a fact
Start with the smallest thing a knowledge base can say. A triple is an ordered trio : a subject , a predicate , and an object [1]. The decoder, before any symbols, is a plain English sentence — read the predicate as the verb and the triple as "subject predicate object." The triple (alice, advises, bob) reads "alice advises bob." That is the entire idea: a fact is a subject, a relationship, and what it relates to.
This is the same thing Volume 1 wrote as a binary relation instance — a relationship holding between exactly two things. When logic writes advises(alice, bob), the predicate advises in front and the two arguments in parentheses, it is saying precisely what the triple says; the two notations are the same fact wearing different clothes:
In the companion knowledge base these facts are stored as literal tuples, written predicate-first as (predicate, subject, object) — the same triple, just serialized with the verb in front — so kb.py (lines 47–50) already is a list of triples:
("advises", "alice", "bob"),
("advises", "bob", "carol"),
("advises", "bob", "dave"),
("advises", "carol", "erin"),
Each row is one triple, one indivisible statement of who advises whom. You cannot break a triple into anything smaller and still have a fact: drop the object and "alice advises" names no relationship; drop the predicate and "alice … bob" says nothing. The triple is the atom of symbolic knowledge, the unit that everything larger is assembled from.
A pile of triples is a labelled directed graph
Now collect many triples and something appears for free. Let be the set of individuals (the things we talk about) and the set of predicates (the relationships). A set of facts is then a subset of all possible triples,
where is the Cartesian product ("every possible combination"), so an element of is exactly a triple with individuals and a predicate. But this set has a second, visual reading. Treat each individual as a node and each triple as a directed edge drawn from node to node and labelled with the predicate . Then is a labelled directed graph — "directed" because the arrow points from subject to object (alice advises bob, not the reverse), "labelled" because each edge carries its predicate as a tag [2]:
Nothing was added and nothing was lost: the triple set and the graph are the same object, one written as rows, the other as dots and arrows. This is the quiet engine of the whole field — a knowledge base is a graph, and a graph is a knowledge base [2].
Draw the academic world and count. The five people (alice, bob, carol, dave, erin), three papers (p1, p2, p3), two institutions (mit, cmu), and three topics (logic, ml, nesy) are the 13 nodes. The role facts are the arrows between them: four advises arrows tracing the advising chain alice → bob → carol → erin plus the branch bob → dave, four authored arrows from people to papers, two cites arrows forming the citation chain p3 → p2 → p1, five affiliated arrows binding people to institutions, and three about arrows tagging each paper with a topic. Add them up — — and the academic world is a graph of 13 individuals joined by 18 role edges.
The academic world as a labelled directed graph: 13 individuals wired by 18 role edges, with faint type edges to their classes and one dashed derived grandAdvisor edge riding along two advises hops.
Original diagram by the authors, created with AI assistance.
Grounded in the companion: 18 edges, built not typed
None of these edges is drawn by hand. The companion ontology promises it is the same world as Volume 1 by building its edges directly from kb.FACTS, mapping each lowercase predicate to its Volume 2 name. The mapping tables (ontology.py, lines 179–180) list which predicates become concept (type) facts and which become role (data) facts:
_CONCEPT_OF = {"professor": "Professor", "student": "Student"}
_ROLE_OF = {"advises", "authored", "cites", "affiliated", "about"}
Then _build_abox (ontology.py, lines 194–198) walks every fact and sorts it by shape — a length-2 fact is a type assertion, a length-3 fact is a role assertion:
for fact in FACTS:
if len(fact) == 2 and fact[0] in _CONCEPT_OF:
concept_assertions.append((_CONCEPT_OF[fact[0]], fact[1]))
elif len(fact) == 3 and fact[0] in _ROLE_OF:
role_assertions.append((fact[0], fact[1], fact[2]))
The ROLE_ASSERTIONS list this produces is the edge set of the graph — each entry (predicate, subject, object) is one labelled arrow. The nodes are not declared separately either; they are computed as exactly the individuals that appear as a subject or an object anywhere in the assertions (ontology.py, lines 211–213):
INDIVIDUALS = sorted({a for _, a in CONCEPT_ASSERTIONS}
| {a for _, a, _ in ROLE_ASSERTIONS}
| {b for _, _, b in ROLE_ASSERTIONS})
Read that as "a node exists precisely when some edge touches it," the graph-theoretic definition of a node set. Running the module (python3 ontology.py) prints its own dimensions from summary (ontology.py, lines 216–220):
10 named concepts, 6 roles, 14 TBox axioms; ABox: 13 concept assertions, 18 role assertions over 13 individuals.
and previews the edge list itself, the first five arrows exactly as stored:
ABox role assertions: [('advises', 'alice', 'bob'), ('advises', 'bob', 'carol'), ('advises', 'bob', 'dave'), ('advises', 'carol', 'erin'), ('authored', 'alice', 'p1')] ...
Those numbers are the graph on the page: 18 role assertions over 13 individuals, every arrow derived from a Volume 1 fact so the two volumes cannot drift apart.
Two kinds of edge: data and type
Look again at the split in _build_abox. A binary fact like advises(alice, bob) became a role assertion, an edge from one individual to another. But a unary fact — a fact about a single thing, like professor(alice) — became a concept assertion Professor(alice) instead. In a plain relational world these look nothing alike, yet in the graph they are both just edges, and the difference is only where the arrow lands.
A role assertion is a data edge: it runs from an individual to an individual, alice → bob. A concept assertion is a type edge: it runs from an individual up to a class, alice → Professor, recording what kind of thing the node is. Volume 1 stored ("professor", "alice") as a length-2 fact; here it becomes the type edge that says node alice belongs to the class Professor. There are 13 such type edges — the five people typed as Professor or Student, the three papers as Paper, two institutions as Institution, three topics as Topic — laid over the 18 data edges like a second, thinner layer of wiring.
This two-layer picture is the first sighting of the ABox — the assertional box, the collection of ground facts about named individuals — which the next chapters make precise. Its two halves are exactly the two kinds of edge: concept assertions (what each node is) and role assertions (how the nodes relate). Keeping them apart matters because reasoning treats them differently: a type edge can climb a class hierarchy (the schema will later say Professor ⊑ Researcher ⊑ Person, where ⊑ reads "is a subclass of," so a professor counts as a researcher and a researcher as a person, and alice's Professor edge implies a Person type too), while a data edge can be chained — which is the whole reason we wanted a graph in the first place.
Why a graph, and not a table
You could store all this in a spreadsheet: one table per predicate, two columns for subject and object. So why insist on a graph? Because the questions we care about are questions about paths, and paths are what a graph makes cheap and a table makes painful.
Give each predicate its edge relation, the set of subject–object pairs it connects,
Following one edge and then another is relational composition, written with the ring ∘ ("composed with"). We read ∘ left-to-right — follow first, then — which matches how OWL writes its role chains (some texts write it as ;) and reverses the classical function-composition order, where would apply first:
where reads "there exists some middle node " and ∧ reads "and." In words: is in the composition when you can get from to by hopping through some shared middle node . This is a two-hop path, and in a graph you find it by literally walking two edges; in a table you must pay for a self-join and invent a name for the join column.
The academic world's marquee example is grandAdvisor. Walk two advises edges in a row and you have the grand-advising relation:
Three two-edge paths, three grand-advisor pairs, read straight off the picture: alice → bob → carol makes alice carol's grand-advisor, alice → bob → dave and bob → carol → erin the other two. The schema will later name this pattern with the role chain advises ∘ advises ⊑ grandAdvisor — the very same containment symbol ⊑ as in the class hierarchy above, here reading "is a sub-relation of" (grand-advising is a special case of the two-hop relation) rather than "is a subclass of," so one containment symbol serves both concepts and roles — turning a path you can trace into an edge a reasoner can derive, the dashed shortcut in the figure. For now the point is only that reachability, multi-hop questions, and "who connects to whom, and how far" are native graph operations. Store facts as a graph and traversal is free; store them as tables and every hop is a join.
Here is the graph's schema at a glance — all six roles, each a binary relation (arity 2, meaning it links exactly two nodes), with how many edges each contributes to the 18 and how to read one:
| Role | Arity | Asserted edges | Reading of (subject, object) |
|---|---|---|---|
advises | 2 | 4 | subject advises object — a professor advises a student |
authored | 2 | 4 | subject authored the paper object |
cites | 2 | 2 | paper subject cites paper object |
affiliated | 2 | 5 | subject is affiliated with the institution object |
about | 2 | 3 | paper subject is about the topic object |
grandAdvisor | 2 | 0 | subject is the grand-advisor of object — not asserted, derived from advises ∘ advises |
The first five rows sum to the 18 asserted edges; grandAdvisor has none of its own, because it is meant to be computed from the two-hop advises paths rather than stated. That empty count is a preview of the entire discipline: the graph you assert is smaller than the graph that is true, and closing the gap is what reasoning does.
The unsolved part
A graph fixes the shape of knowledge perfectly and its meaning not at all. Nothing in the picture says what the string "advises" denotes. Our academic world means it as "PhD supervision," but a second lab could publish an identically shaped graph in which advises means "sits on a thesis committee," or points the other way (student → professor), or quietly reuses the node name mit for a different institution. Merge the two graphs and the arrows line up flawlessly while the facts silently contradict each other — a machine following edges cannot tell, because a bare label carries no agreed definition, no direction convention, and no promise that two graphs mean the same thing by the same word [3].
Worse, the graph alone cannot even state the rules we have been leaning on. "Every advises edge goes from a professor to a student," "grandAdvisor is two advises hops," "nobody is both a professor and a student" — none of these lives in the graph; they were prose in the margins. A pile of triples is a superb way to store and traverse facts, but it is mute about which facts must follow from the ones drawn and which combinations are forbidden. That missing layer — a shared, machine-readable vocabulary with agreed meaning — is not an afterthought; it is the next thing to build.
Why it matters
Everything downstream in neuro-symbolic AI consumes this graph. The description-logic reasoners of this volume complete it — adding the derived grandAdvisor edges and the implied Person types until no rule fires anything new. The knowledge-graph embeddings of Volume 3 learn coordinates for these same nodes so that a true edge scores better than a false one. The differentiable query layers of later volumes traverse a soft version of exactly these paths. All of them start from the same substrate: individuals as nodes, relationships as labelled directed edges, facts as triples. Get the representation right — know that a fact is a triple and a knowledge base is a graph — and every method that follows has a common object to stand on. It is the format on which the exact half and the robust half of the field finally meet.
Key terms
- Triple — an ordered
(subject, predicate, object); the atomic unit of symbolic knowledge, e.g.(alice, advises, bob). - Predicate / binary relation — the relationship in a triple; a binary relation
advises(alice, bob)and the triple(alice, advises, bob)are the same fact. - Labelled directed graph — nodes joined by directed edges that each carry a label; a set of triples is one, with individuals as nodes and predicates as edge labels.
- Node / individual — a thing the graph talks about; here the 13 people, papers, institutions, and topics, computed as exactly the subjects and objects that appear in some assertion.
- Data edge (role assertion) — an edge between two individuals, e.g. alice → bob under
advises; 18 of them in the academic world. - Type edge (concept assertion) — an edge from an individual up to its class, e.g. alice →
Professor; 13 of them, previewing the ABox. - ABox (assertional box) — the ground facts about named individuals, split into concept assertions and role assertions.
- Relational composition ∘ — following one edge then another, read left-to-right; collects the two-hop pairs, the operation behind
grandAdvisorand reachability. - Role chain — a schema rule like
advises ∘ advises ⊑ grandAdvisorthat turns a two-hop path into a derivable edge.
Where this leads
The graph gives us structure without meaning: arrows a machine can traverse but not interpret, and rules that stayed stranded in the margins. The next chapter, RDF and OWL, fixes both. RDF (the Resource Description Framework) standardizes the triple itself — giving every node and predicate a globally unique name so two graphs can safely agree on what advises means — and OWL (the Web Ontology Language) adds the vocabulary to say the rules the bare graph could only imply: that advising links a professor to a student, that grand-advising is two advising hops, that some concepts are forbidden. It is the same 13 individuals and 18 edges, finally given a language for their meaning.