2026-03-19 14:27:12 +01:00
# Design Decisions
2026-03-19 14:40:44 +01:00
This document explains *why* Geolog works the way it does.
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
---
## Geometric Logic: What It Means
Geolog uses "geometric logic" — a restricted form of logic that can express:
- "If X then Y" rules
- "There exists something such that..."
- "A or B" (but you can't say "not A")
**What you CAN write:**
```
// If x and y are both connected to z, they know each other
forall x, y, z. connected(x,z), connected(y,z) |- knows(x,y)
// Every person has a best friend
forall p : Person. |- exists f : Person. best_friend(p, f)
// Every task is either done or pending
forall t : Task. |- done(t) \/ pending(t)
```
**What you CANNOT write:**
```
// No negation allowed
forall x. |- not blocked(x) // INVALID
// No "if not" patterns
forall x. not done(x) |- pending(x) // INVALID
```
**Why this restriction?** Geometric logic has nice mathematical properties — it's preserved by "geometric morphisms" between topoi. This isn't just theory; it means the reasoning is compositional and predictable.
2026-03-19 14:27:12 +01:00
---
2026-03-19 14:40:44 +01:00
## Postfix Function Application
Most languages write `f(x)` to apply function `f` to `x` . Geolog writes `x f` .
```
// Traditional notation
src(ab) // "apply src to ab"
// Geolog notation
ab src // "ab, then src"
```
**Why?** It matches how you read pipelines left-to-right:
```
// Geolog: read left to right
ab src tgt // "take ab, get its src, get that's tgt"
// Traditional: read inside out
tgt(src(ab)) // "tgt of src of ab"
```
This is called "categorical" style because it matches how mathematicians compose morphisms in category theory.
---
## Identity System: Luids and Slids
Geolog needs to track elements across different operations. It uses two kinds of IDs:
| ID Type | Scope | Example |
|---------|-------|---------|
| **Luid** (Local Universe ID) | Global — unique across everything | "Element #4827 " |
| **Slid** (Structure-Local ID) | Local — index within one structure | "The 3rd vertex" |
**Why both?**
- Slids are small integers (0, 1, 2...) — fast for computation
- Luids persist across saves/loads — you can reference "that specific vertex" forever
```
Structure "Triangle":
Vertex A has Slid=0, Luid=1001
Vertex B has Slid=1, Luid=1002
Vertex C has Slid=2, Luid=1003
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
After merging A and B (because an axiom said A = B):
Vertex A has Slid=0, Luid=1001 (canonical)
Vertex B → now points to A
```
2026-03-19 14:27:12 +01:00
---
2026-03-19 14:40:44 +01:00
## Append-Only Storage
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
Geolog never deletes data. When you "remove" something, it's marked as removed but still stored.
**Why?**
- Perfect audit trail — you can see exactly what changed and when
- Safe undo — nothing is ever lost
- Git-like history — you can go back to any previous state
```
Commit 1: Added vertices A, B, C
Commit 2: Added edge ab
Commit 3: Marked edge ab as "removed" ← still stored, just flagged
```
2026-03-19 14:27:12 +01:00
---
## Type System
2026-03-19 14:40:44 +01:00
### Sorts (Types)
A **sort** is a type of thing. Vertices and Edges are different sorts:
```geolog
theory Graph {
V : Sort; // V is a type (the type of vertices)
E : Sort; // E is a type (the type of edges)
}
```
### Functions
Functions map elements to elements:
```geolog
src : E -> V; // Every edge has a source vertex
tgt : E -> V; // Every edge has a target vertex
mul : [x: M, y: M] -> M; // Binary function taking a pair
```
The `[x: M, y: M]` is a **product domain** — the function takes a record with two fields.
### Relations
Relations are yes/no questions about tuples:
```geolog
leq : [x: X, y: X] -> Prop; // "Is x ≤ y?"
connected : [a: V, b: V] -> Prop;
```
`Prop` means "proposition" — it's either true or false for each input.
2026-03-19 14:27:12 +01:00
---
2026-03-19 14:40:44 +01:00
## Chase Algorithm Design
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
The chase repeatedly applies rules until nothing new can be derived:
```
Initial facts: friends(alice, bob), friends(bob, charlie)
Rule: friends(x,y), friends(y,z) |- knows(x,z)
Iteration 1:
- Rule matches with x=alice, y=bob, z=charlie
- Conclusion knows(alice, charlie) is missing
- Add: knows(alice, charlie)
Iteration 2:
- No rule has missing conclusions
- Stop (fixpoint reached)
Final facts: friends(alice, bob), friends(bob, charlie), knows(alice, charlie)
```
**Key features:**
- Uses **tensor algebra** to efficiently find which rules need to fire
- Integrates **congruence closure** so `x = y` conclusions actually merge elements
- **Terminates** for theories with identity elements (earlier versions could loop forever)
2026-03-19 14:27:12 +01:00
---
## Solver Architecture
2026-03-19 14:40:44 +01:00
When you need to *find* a model (not just derive facts), the solver searches:
```
Goal: Find an instance of Graph with a cycle
Search tree:
Node 1: Empty graph
→ Obligation: need at least one edge (from some axiom)
→ Branch: try adding edge e1
Node 2: Graph with e1
→ Obligation: e1 needs src and tgt
→ Branch: try src(e1) = v1, tgt(e1) = v1 (self-loop!)
Node 3: Graph with e1, v1, self-loop
→ All axioms satisfied
→ SUCCESS: return this model
```
**Key features:**
- **Explicit search tree** — the solver builds a tree structure, not recursive function calls
- **Tactics** — different strategies (forward chaining, equation propagation) can be combined
- **Obligations** — "this axiom requires a witness" is tracked explicitly
2026-03-19 14:27:12 +01:00
---
## Query Compilation
2026-03-19 14:40:44 +01:00
Queries are compiled to relational algebra (like SQL internally):
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
```
Query: Find all x,y where connected(x,y) and connected(y,x)
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
Compiled plan:
1. Scan relation "connected" → get all (x,y) pairs
2. Scan relation "connected" → get all (a,b) pairs
3. Join where y=a and x=b
4. Project out x,y
```
2026-03-19 14:27:12 +01:00
2026-03-19 14:40:44 +01:00
This is optimized with standard database techniques (filter pushdown, etc.).