Transitive closure
DefinitionStaged transitive-closure computation#✓fully proved
Let \(A\) be a Boolean adjacency matrix on the vertices \(0, \dots, n-1\) and let \(k \le n\). The computation first builds the \(n \times n\) Boolean matrix \(T^{(0)}\) whose entry \((i, j)\) is true exactly when \(i = j\) or \(A_{ij}\) is true. Then, for \(p = 0, \dots, k - 1\), it builds a new matrix \(T^{(p+1)}\) from the saved matrix \(T^{(p)}\) by \(T^{(p+1)}_{ij} = T^{(p)}_{ij} \lor (T^{(p)}_{ip} \land T^{(p)}_{pj})\), and it returns \(T^{(k)}\). One time unit is charged for each cell assignment.
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
private def buildInitial {n : Nat} (adjacency : Fin n → Fin n → Bool) :
(rows : Nat) → rows ≤ n → TimeM Nat (Vector (Vector Bool n) rows)
| 0, _ => pure #v[]
| rows + 1, hrows => do
let table ← buildInitial adjacency rows (by omega)
let row ← initializeRow adjacency ⟨rows, by omega⟩ n (by omega)
pure (table.push row)
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:40
Used by 9
DefinitionSaved-matrix transitive-closure algorithm#✓fully proved
Given a Boolean adjacency matrix \(A\) on the vertices \(0, 1, \dots, n-1\), the algorithm first builds the matrix \(t^{(0)}\) with \(t^{(0)}_{ij}\) true exactly when \(i = j\) or \(A_{ij}\) is true. Then, for \(k = 0, 1, \dots, n-1\) in turn, it builds a new matrix \(t^{(k+1)}\) with \(t^{(k+1)}_{ij} = t^{(k)}_{ij} \lor (t^{(k)}_{ik} \land t^{(k)}_{kj})\) for all \(i, j\), reading every operand from the saved matrix \(t^{(k)}\), and it returns \(t^{(n)}\). One time unit is charged for each cell assignment; reads, Boolean operations and matrix allocation are free.
This is the saved-matrix recurrence of CLRS for the reflexive transitive closure.
@[no_expose]
def transitiveClosure {n : Nat} (adjacency : Fin n → Fin n → Bool) :
TimeM Nat (Fin n → Fin n → Bool) := do
let final ← transitiveClosureStages adjacency n (by omega)
pure fun i j => (final.get i).get j
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
TheoremInitial matrix of the transitive-closure computation#✓fully proved
Let \(A\) be a Boolean adjacency matrix on the vertices \(0, \dots, n-1\). For all vertices \(i\) and \(j\), the entry \((i, j)\) of the matrix produced by the staged transitive-closure computation with no pivot stages is true if and only if \(i = j\) or \(A_{ij}\) is true.
theorem transitiveClosureStages_zero_cell {n : Nat} (adjacency : Fin n → Fin n → Bool)
(i j : Fin n) :
((transitiveClosureStages adjacency 0 (by omega)).ret.get i).get j =
(decide (i = j) || adjacency i j)
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
Uses 1 · Used by 1
TheoremTransition recurrence of the transitive-closure stages#✓fully proved
Let \(A\) be a Boolean adjacency matrix on the vertices \(0, \dots, n-1\), and for \(m \le n\) let \(T^{(m)}\) be the matrix produced by the staged transitive-closure computation on \(A\) after its first \(m\) pivot stages. For every \(k < n\) and all vertices \(i\) and \(j\),
Every operand of stage \(k + 1\) is read from the complete matrix saved after stage \(k\).
theorem transitiveClosureStages_succ_cell {n : Nat} (adjacency : Fin n → Fin n → Bool)
(k : Nat) (hk : k < n) (i j : Fin n) :
let previous := (transitiveClosureStages adjacency k (by omega)).ret
((transitiveClosureStages adjacency (k + 1) (by omega)).ret.get i).get j =
((previous.get i).get j ||
((previous.get i).get ⟨k, hk⟩ && (previous.get ⟨k, hk⟩).get j))
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
Uses 1 · Used by 1
TheoremCost of initializing the transitive-closure matrix#✓fully proved
For every Boolean adjacency matrix on \(n\) vertices, the staged transitive-closure computation with no pivot stages (only the initialization of the \(n \times n\) matrix) charges exactly \(n^2\) time units, one for each cell assignment.
theorem transitiveClosure_initializations {n : Nat} (adjacency : Fin n → Fin n → Bool) :
(transitiveClosureStages adjacency 0 (by omega)).time = n ^ 2
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
Uses 1
TheoremCost of one transition stage#✓fully proved
For every Boolean adjacency matrix on \(n\) vertices and every \(k < n\), the time charged by the staged transitive-closure computation with \(k + 1\) pivot stages minus the time charged with \(k\) pivot stages equals \(n^2\): one time unit for each cell assignment of the new stage.
theorem transitiveClosure_stage_assignments {n : Nat} (adjacency : Fin n → Fin n → Bool)
(k : Nat) (hk : k < n) :
(transitiveClosureStages adjacency (k + 1) (by omega)).time -
(transitiveClosureStages adjacency k (by omega)).time = n ^ 2
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
Uses 1
TheoremCost of the transition stages of transitive closure#✓fully proved
Charge one time unit for each cell assignment. For every Boolean adjacency matrix on \(n\) vertices, let \(a\) be the cost of running the initialization of the saved-matrix transitive-closure algorithm followed by all \(n\) of its stages, and let \(b\) be the cost of running the initialization alone. Then \(a - b = n^3\), where the subtraction is subtraction of natural numbers, truncated at \(0\). That is, the \(n\) transition stages together perform exactly \(n^3\) cell assignments.
theorem transitiveClosure_transition_assignments {n : Nat}
(adjacency : Fin n → Fin n → Bool) :
(transitiveClosureStages adjacency n (by omega)).time -
(transitiveClosureStages adjacency 0 (by omega)).time = n ^ 3
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
Uses 1
TheoremInvariant of the transitive-closure stages#✓fully proved
Let \(A\) be a Boolean adjacency matrix of a directed graph on the vertices \(0, \dots, n-1\) and let \(k \le n\). For all vertices \(i\) and \(j\), the entry \((i, j)\) of the matrix produced by the staged transitive-closure computation after its first \(k\) pivot stages is true if and only if there are vertices \(i = v_0, v_1, \dots, v_m = j\) with \(m \ge 0\) such that each \(A_{v_t v_{t+1}}\) is true and every intermediate vertex \(v_1, \dots, v_{m-1}\) is less than \(k\).
theorem transitiveClosureStages_cell_eq_true_iff {n : Nat}
(adjacency : Fin n → Fin n → Bool) (pivots : Nat) (hpivots : pivots ≤ n)
(i j : Fin n) :
((transitiveClosureStages adjacency pivots hpivots).ret.get i).get j = true ↔
∃ path, path.IsChainFromTo (fun a b => adjacency a b = true) i j ∧
FloydWarshall.InternalVerticesBelow pivots path
@[no_expose]
def transitiveClosureStages {n : Nat} (adjacency : Fin n → Fin n → Bool)
(pivots : Nat) (hpivots : pivots ≤ n) : TimeM Nat (Vector (Vector Bool n) n) := do
let initial ← buildInitial adjacency n (by omega)
runStages initial pivots hpivots
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:77
def InternalVerticesBelow {n : Nat} (k : Nat) (path : List (Fin n)) : Prop :=
∀ vertex ∈ path.tail.dropLast, vertex.val < k
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:45
Uses 4 · Used by 1
TheoremCorrectness of the transitive-closure algorithm#✓fully proved
Let \(A\) be a Boolean adjacency matrix of a directed graph on the vertices \(0, \dots, n-1\). For all vertices \(i\) and \(j\), the entry \((i, j)\) of the matrix returned by the transitive-closure algorithm on \(A\) is true if and only if \(j\) is reachable from \(i\) by a sequence of zero or more edges of the graph.
theorem transitiveClosure_cell_eq_true_iff {n : Nat}
(adjacency : Fin n → Fin n → Bool) (i j : Fin n) :
(transitiveClosure adjacency).ret i j = true ↔
Relation.ReflTransGen (fun a b => adjacency a b = true) i j
@[no_expose]
def transitiveClosure {n : Nat} (adjacency : Fin n → Fin n → Bool) :
TimeM Nat (Fin n → Fin n → Bool) := do
let final ← transitiveClosureStages adjacency n (by omega)
pure fun i j => (final.get i).get j
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:84
TheoremRunning time of the transitive-closure algorithm#✓fully proved
For every Boolean adjacency matrix on \(n\) vertices, the transitive-closure algorithm charges exactly \(n^2 + n^3\) time units: \(n^2\) cell assignments to initialize the matrix and \(n^2\) in each of the \(n\) transition stages.
theorem transitiveClosure_time {n : Nat} (adjacency : Fin n → Fin n → Bool) :
(transitiveClosure adjacency).time = n ^ 2 + n ^ 3
@[no_expose]
def transitiveClosure {n : Nat} (adjacency : Fin n → Fin n → Bool) :
TimeM Nat (Fin n → Fin n → Bool) := do
let final ← transitiveClosureStages adjacency n (by omega)
pure fun i j => (final.get i).get j
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:84
Uses 2 · Used by 2
TheoremCost of transitive closure on the empty graph#✓fully proved
For the graph with no vertices, the transitive-closure algorithm charges \(0\) time units: it performs no cell assignments.
theorem transitiveClosure_time_zero (adjacency : Fin 0 → Fin 0 → Bool) :
(transitiveClosure adjacency).time = 0
@[no_expose]
def transitiveClosure {n : Nat} (adjacency : Fin n → Fin n → Bool) :
TimeM Nat (Fin n → Fin n → Bool) := do
let final ← transitiveClosureStages adjacency n (by omega)
pure fun i j => (final.get i).get j
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:84
Uses 2
TheoremCost of transitive closure on one vertex#✓fully proved
For every Boolean adjacency matrix on a single vertex, the transitive-closure algorithm charges exactly \(2\) time units: one cell assignment for the initialization and one for the single transition stage.
theorem transitiveClosure_time_one (adjacency : Fin 1 → Fin 1 → Bool) :
(transitiveClosure adjacency).time = 2
@[no_expose]
def transitiveClosure {n : Nat} (adjacency : Fin n → Fin n → Bool) :
TimeM Nat (Fin n → Fin n → Bool) := do
let final ← transitiveClosureStages adjacency n (by omega)
pure fun i j => (final.get i).get j
CSLibExt/Algorithms/Lean/Graph/TransitiveClosure.lean:84
Uses 2
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.