geolog-zeta-fork/examples/geolog/transitive_closure.geolog

78 lines
1.9 KiB
Plaintext
Raw Normal View History

2026-02-26 11:50:51 +01:00
// Transitive Closure Example
//
// This example demonstrates the chase algorithm computing transitive
// closure of a relation. We define a Graph theory with Edge and Path
// relations, where Path is the transitive closure of Edge.
//
// Run with:
// cargo run -- examples/geolog/transitive_closure.geolog
// Then:
// :source examples/geolog/transitive_closure.geolog
// :inspect Chain
// :chase Chain
//
// The chase will derive Path tuples for all reachable pairs:
// - Edge(a,b), Edge(b,c), Edge(c,d) as base facts
// - Path(a,b), Path(b,c), Path(c,d) from base axiom
// - Path(a,c), Path(b,d) from one step of transitivity
// - Path(a,d) from two steps of transitivity
theory Graph {
V : Sort;
// Direct edges in the graph
Edge : [src: V, tgt: V] -> Prop;
// Reachability (transitive closure of Edge)
Path : [src: V, tgt: V] -> Prop;
// Base case: every edge is a path
ax/base : forall x, y : V.
[src: x, tgt: y] Edge |- [src: x, tgt: y] Path;
// Inductive case: paths compose
ax/trans : forall x, y, z : V.
[src: x, tgt: y] Path, [src: y, tgt: z] Path |- [src: x, tgt: z] Path;
}
// A linear chain: a -> b -> c -> d
// Chase derives Path tuples from Edge via ax/base and ax/trans.
instance Chain : Graph = chase {
a : V;
b : V;
c : V;
d : V;
// Edges form a chain
[src: a, tgt: b] Edge;
[src: b, tgt: c] Edge;
[src: c, tgt: d] Edge;
}
// A diamond: a -> b, a -> c, b -> d, c -> d
// Chase derives all reachable paths.
instance Diamond : Graph = chase {
top : V;
left : V;
right : V;
bottom : V;
// Two paths from top to bottom
[src: top, tgt: left] Edge;
[src: top, tgt: right] Edge;
[src: left, tgt: bottom] Edge;
[src: right, tgt: bottom] Edge;
}
// A cycle: a -> b -> c -> a
// Chase derives all reachable paths (full connectivity).
instance Cycle : Graph = chase {
x : V;
y : V;
z : V;
[src: x, tgt: y] Edge;
[src: y, tgt: z] Edge;
[src: z, tgt: x] Edge;
}