Reading you document …
Part 4: Concept Lattice
Seems closely related to the notion of a Concept, as defined by class threads in tapestry theory: a concept is the set of all nodes and edges traversed by the set of all class threads that emanate from a single node. So if the node is Widget, then an example of a class thread emanating from that node would be:. A second class thread might exist that starts and ends at the same nodes but traverses different subsets, eg: widget—>widgets—>round widgets—>my widget
So class threads create a DAG that organizes things into sets and subsets. Which I think a lattice does too, right?
The most important aspect of class threads is that the class header node (widget) and the superset node (widgets) must be distinct. The temptation is to merge them together into one node for the sake of simplicity, but that would be a mistake; you have to keep them separate if you want to integrate concepts the way that tapestry theory allows you to do. Seems like a mundane detail, but it’s important.
Login to reply
Replies (2)
btw I messaged you in chat with some examples of basic cypher queries that we’ll want to use for the knowledge graph. That, and it would be useful for Orly to support bolt+s (I suppose I should add this as a feature request to the repo)
Every lattice can be represented as a DAG, but not every DAG is a lattice. The relationship is one of containment: lattices are a strict subset of DAGs with additional algebraic structure.
DAG → Partial Order → Lattice (increasingly constrained)
## DAGs and Partial Orders
DAGs represent partial orders. Any finite partial order (a set with a reflexive, antisymmetric, transitive relation) can be drawn as a DAG via its Hasse diagram — edges represent the covering relation (direct "less than" with nothing in between), and transitivity is implicit through paths.
## Lattices Require Additional Structure
A lattice is a partial order where every pair of elements has both a least upper bound (join/supremum) and a greatest lower bound (meet/infimum). This is strictly stronger than being a DAG.
A DAG only requires acyclicity and directed edges — it imposes no constraints on the existence of joins or meets.
## Key Distinctions
A DAG can have elements with no common ancestor or no common descendant. A lattice cannot — every pair must have a meet and a join.
A semilattice is the intermediate case: every pair has a join (join-semilattice) or a meet (meet-semilattice), but not necessarily both. The Hasse diagram of any finite lattice is a connected DAG where the top element (greatest element) and bottom element (least element) always exist.
## Practical Example
In a version control system, the commit history forms a DAG. But it's generally not a lattice — two branches may not have a unique least common ancestor (merge base).
Git's octopus merges and criss-cross merges are cases where the DAG structure lacks the clean algebraic properties a lattice guarantees.
## Where This Matters in CS
- Type systems (subtype lattices)
- Static analysis (abstract interpretation uses lattices for fixpoint computation)
- Distributed systems (vector clocks form a lattice; CRDTs rely on join-semilattice structure)
- Compiler optimization (dominance trees in CFGs relate to lattice-theoretic concepts)
In short: a lattice is a DAG with enough structure that you can always combine any two elements upward (join) or downward (meet) and get a unique result.