Floyd–Warshall algorithm
DefinitionWeight of a vertex path in an extended-integer weight matrix#✓fully proved
Let \(w\) assign to each ordered pair of vertices in \(\{0, \dots, n-1\}\) a weight in \(\mathbb{Z} \cup \{\infty\}\). The weight of a list of vertices \(v_0, v_1, \dots, v_m\) with \(m \ge 1\) is \(w(v_0, v_1) + w(v_1, v_2) + \cdots + w(v_{m-1}, v_m)\), computed in \(\mathbb{Z} \cup \{\infty\}\) where adding \(\infty\) gives \(\infty\). The empty list and every single-vertex list have weight \(0\).
def pathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
List (Fin n) → WithTop Int
| [] => 0
| [_] => 0
| source :: target :: rest =>
weight source target + pathWeight weight (target :: rest)
Used by 13
DefinitionFinite-weight vertex path in a weight matrix#✓fully proved
Let \(w\) assign to each ordered pair of vertices in \(\{0, \dots, n-1\}\) a weight in \(\mathbb{Z} \cup \{\infty\}\), and let \(s\) and \(t\) be vertices. A list of vertices \(p\) is a weighted path from \(s\) to \(t\) when \(p\) is nonempty, its first entry is \(s\), its last entry is \(t\), and \(w(u, v) \ne \infty\) for every pair of consecutive entries \(u, v\) of \(p\).
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
Used by 13
DefinitionIntermediate vertices below a bound#✓fully proved
For a natural number \(k\), a list of vertices in \(\{0, \dots, n - 1\}\) has all its intermediate vertices below \(k\) when every entry of the list other than its first and its last is less than \(k\).
def InternalVerticesBelow {n : Nat} (k : Nat) (path : List (Fin n)) : Prop :=
∀ vertex ∈ path.tail.dropLast, vertex.val < k
Used by 9
DefinitionStage-\(k\) shortest-path weight#✓fully proved
Let \(w\) assign to each ordered pair of vertices in \(\{0, \dots, n-1\}\) a weight in \(\mathbb{Z} \cup \{\infty\}\), let \(k\) be a natural number, let \(s\) and \(t\) be vertices and let \(d \in \mathbb{Z} \cup \{\infty\}\). A weighted path from \(s\) to \(t\) is a nonempty list of vertices that starts at \(s\), ends at \(t\) and has \(w(u, v) \ne \infty\) for every pair of consecutive vertices \(u, v\); its weight is the sum of these values \(w(u, v)\), and its intermediate vertices are all its entries except the first and the last. Then \(d\) is the stage-\(k\) shortest-path weight from \(s\) to \(t\) when \(d\) is at most the weight of every weighted path from \(s\) to \(t\) whose intermediate vertices are all less than \(k\), and either \(d = \infty\) or some such path has weight exactly \(d\).
def IsStageShortestPathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(k : Nat) (source target : Fin n) (distance : WithTop Int) : Prop :=
(∀ path, IsWeightedPath weight source target path → InternalVerticesBelow k path →
distance ≤ pathWeight weight path) ∧
(distance = ⊤ ∨ ∃ path, IsWeightedPath weight source target path ∧
InternalVerticesBelow k path ∧ pathWeight weight path = distance)
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:40
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
def pathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
List (Fin n) → WithTop Int
| [] => 0
| [_] => 0
| source :: target :: rest =>
weight source target + pathWeight weight (target :: rest)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:32
Uses 3 · Used by 3
DefinitionNegative cycles#✓fully proved
For an \(n \times n\) matrix \(w\) of weights in \(\mathbb{Z} \cup \{+\infty\}\), a list of vertices \(v_0, \dots, v_m\) is a negative cycle when \(m \ge 1\), \(v_m = v_0\), every weight \(w_{v_i v_{i+1}}\) with \(i < m\) is finite, the vertices \(v_0, \dots, v_{m-1}\) are pairwise distinct, and the path weight \(\sum_{i < m} w_{v_i v_{i+1}}\) is negative.
def IsNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(cycle : List (Fin n)) : Prop :=
∃ base, IsWeightedPath weight base base cycle ∧ 2 ≤ cycle.length ∧
cycle.dropLast.Nodup ∧ pathWeight weight cycle < 0
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:40
def pathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
List (Fin n) → WithTop Int
| [] => 0
| [_] => 0
| source :: target :: rest =>
weight source target + pathWeight weight (target :: rest)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:32
Uses 2 · Used by 5
DefinitionMatrices with a negative cycle#✓fully proved
An \(n \times n\) matrix \(w\) of weights in \(\mathbb{Z} \cup \{+\infty\}\) has a negative cycle when some list of vertices is a negative cycle for \(w\).
def HasNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
∃ cycle, IsNegativeCycle weight cycle
def IsNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(cycle : List (Fin n)) : Prop :=
∃ base, IsWeightedPath weight base base cycle ∧ 2 ≤ cycle.length ∧
cycle.dropLast.Nodup ∧ pathWeight weight cycle < 0
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:57
Uses 1 · Used by 5
DefinitionWeight matrices without negative cycles#✓fully proved
Let \(w\) assign to each ordered pair of vertices in \(\{0, \dots, n-1\}\) a weight in \(\mathbb{Z} \cup \{\infty\}\). Then \(w\) has no negative cycle when there is no list of vertices \(v_0, v_1, \dots, v_m\) with \(m \ge 1\) such that \(v_m = v_0\), the vertices \(v_0, \dots, v_{m-1}\) are pairwise distinct, \(w(v_{i-1}, v_i) \ne \infty\) for \(1 \le i \le m\), and \(w(v_0, v_1) + \cdots + w(v_{m-1}, v_m) < 0\).
def NoNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
¬HasNegativeCycle weight
def HasNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
∃ cycle, IsNegativeCycle weight cycle
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:63
Uses 1 · Used by 5
StructureFloyd–Warshall cost record#✓fully proved
A cost record for the Floyd–Warshall algorithm is a pair of natural numbers: the number of initialization events (input matrix cells copied into the initial distance table) and the number of min-plus transition events (table entries updated).
structure Cost where
/-- Input matrix cells copied and diagonal-normalized. -/
initializations : Nat
/-- Executed min-plus table transitions. -/
transitions : Nat
deriving DecidableEq, Repr
Used by 11
DefinitionTotal Floyd–Warshall cost#✓fully proved
The total of a Floyd–Warshall cost record is its number of initialization events plus its number of min-plus transition events.
def Cost.total (cost : Cost) : Nat := cost.initializations + cost.transitions
structure Cost where
/-- Input matrix cells copied and diagonal-normalized. -/
initializations : Nat
/-- Executed min-plus table transitions. -/
transitions : Nat
deriving DecidableEq, Repr
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:71
Uses 1 · Used by 1
DefinitionFloyd–Warshall algorithm#✓fully proved
Given an \(n \times n\) matrix \(w\) of weights in \(\mathbb{Z} \cup \{+\infty\}\) indexed by the vertices \(0, \dots, n - 1\), the Floyd–Warshall algorithm starts from the table with \(d^{(0)}_{ii} = \min(w_{ii}, 0)\) and \(d^{(0)}_{ij} = w_{ij}\) for \(i \ne j\), and for \(k = 0, \dots, n - 1\) computes the table \(d^{(k+1)}_{ij} = \min\bigl(d^{(k)}_{ij}, d^{(k)}_{ik} + d^{(k)}_{kj}\bigr)\). It returns the matrix \(d^{(n)}\) together with its cost: one initialization event for each entry of \(d^{(0)}\) and one transition event for each entry of each table \(d^{(k+1)}\).
Cslib.Algorithms.Lean.FloydWarshall.floydWarshall · 47 lines
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
let value := min (weight rowIndex column) (if rowIndex = column then 0 else ⊤)
pure (row.push value)
let rec buildInitial :
(i : Nat) → i ≤ n → TimeM Cost (Vector (Vector (WithTop Int) n) i)
| 0, _ => pure #v[]
| i + 1, hi => do
let table ← buildInitial i (by omega)
let row ← initializeRow ⟨i, by omega⟩ n (by omega)
pure (table.push row)
let rec buildStageRow (previous : Table) (pivot rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← buildStageRow previous pivot rowIndex j (by omega)
TimeM.tick ⟨0, 1⟩
let column : Fin n := ⟨j, by omega⟩
let value := min (tableGet previous rowIndex column)
(tableGet previous rowIndex pivot + tableGet previous pivot column)
pure (row.push value)
let rec buildStage (previous : Table) (pivot : Fin n) :
(i : Nat) → i ≤ n → TimeM Cost (Vector (Vector (WithTop Int) n) i)
| 0, _ => pure #v[]
| i + 1, hi => do
let table ← buildStage previous pivot i (by omega)
let row ← buildStageRow previous pivot ⟨i, by omega⟩ n (by omega)
pure (table.push row)
let rec runStages (initial : Table) : (k : Nat) → k ≤ n → TimeM Cost Table
| 0, _ => pure initial
| k + 1, hk => do
let previous ← runStages initial k (by omega)
buildStage previous ⟨k, by omega⟩ n (by omega)
do
let initial ← buildInitial n (by omega)
let final ← runStages initial n (by omega)
pure fun i j => tableGet final i j
structure Cost where
/-- Input matrix cells copied and diagonal-normalized. -/
initializations : Nat
/-- Executed min-plus table transitions. -/
transitions : Nat
deriving DecidableEq, Repr
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:71
Uses 1 · Used by 9
DefinitionNegative-diagonal test#✓fully proved
For an \(n \times n\) matrix \(d\) with entries in \(\mathbb{Z} \cup \{+\infty\}\), the negative-diagonal test on \(d\) is the Boolean value that is true exactly when \(d_{vv} < 0\) for some vertex \(v\).
TheoremInitialization count of Floyd–Warshall#✓fully proved
For every \(n\) and every \(n \times n\) matrix of weights in \(\mathbb{Z} \cup \{+\infty\}\), the Floyd–Warshall algorithm performs exactly \(n^2\) initialization events, one for each ordered pair of vertices.
theorem floydWarshall_initializations {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
(floydWarshall weight).time.initializations = n ^ 2
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
Uses 2 · Used by 1
TheoremTransition count of Floyd–Warshall#✓fully proved
For every \(n\) and every \(n \times n\) matrix of weights in \(\mathbb{Z} \cup \{+\infty\}\), the Floyd–Warshall algorithm performs exactly \(n^3\) min-plus transition events, one for each triple \((k, i, j)\) of vertices.
theorem floydWarshall_transitions {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
(floydWarshall weight).time.transitions = n ^ 3
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
Uses 2 · Used by 1
TheoremFloyd–Warshall performs \(n^2 + n^3\) steps#✓fully proved
For every \(n\) and every \(n \times n\) matrix of weights in \(\mathbb{Z} \cup \{+\infty\}\), the total number of events counted by the Floyd–Warshall algorithm, initialization events plus min-plus transition events, is exactly \(n^2 + n^3\).
theorem floydWarshall_time {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
(floydWarshall weight).time.total = n ^ 2 + n ^ 3
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
Uses 5
TheoremCharacterization of the negative-diagonal test#✓fully proved
For every \(n \times n\) matrix \(d\) with entries in \(\mathbb{Z} \cup \{+\infty\}\), the negative-diagonal test on \(d\) returns true if and only if \(d_{vv} < 0\) for some vertex \(v\).
theorem hasNegativeDiagonal_eq_true_iff {n : Nat}
(distance : Fin n → Fin n → WithTop Int) :
hasNegativeDiagonal distance = true ↔ ∃ vertex, distance vertex vertex < 0
def hasNegativeDiagonal {n : Nat} (distance : Fin n → Fin n → WithTop Int) : Bool :=
(List.finRange n).any fun vertex => decide (distance vertex vertex < 0)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:136
Uses 1 · Used by 1
TheoremFloyd–Warshall computes shortest-path distances#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), suppose that \(w\) has no negative cycle, and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). Then for all vertices \(s\) and \(t\), \(D(s, t)\) is at most the weight of every weighted path from \(s\) to \(t\), and either \(D(s, t) = \infty\) or \(D(s, t)\) is the weight of some weighted path from \(s\) to \(t\). Here a weighted path is a nonempty vertex sequence in which every consecutive pair has finite weight, and its weight is the sum of these weights.
Formally this is the stage-\(n\) characterization, which considers only paths whose intermediate vertices are all below \(n\); every path qualifies.
theorem floydWarshall_distance_spec {n : Nat}
(weight : Fin n → Fin n → WithTop Int) (source target : Fin n)
(hNoCycle : NoNegativeCycle weight) :
IsStageShortestPathWeight weight n source target
((floydWarshall weight).ret source target)
def NoNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
¬HasNegativeCycle weight
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:67
def IsStageShortestPathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(k : Nat) (source target : Fin n) (distance : WithTop Int) : Prop :=
(∀ path, IsWeightedPath weight source target path → InternalVerticesBelow k path →
distance ≤ pathWeight weight path) ∧
(distance = ⊤ ∨ ∃ path, IsWeightedPath weight source target path ∧
InternalVerticesBelow k path ∧ pathWeight weight path = distance)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:49
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
TheoremFinite Floyd–Warshall distances are attained#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). If \(D(s, t) = d\) for vertices \(s\), \(t\) and an integer \(d\), then there is a weighted path from \(s\) to \(t\) (a nonempty vertex sequence from \(s\) to \(t\) in which every consecutive pair has finite weight) whose weight, the sum of the weights of its consecutive pairs, is \(d\).
theorem floydWarshall_distance_realized {n : Nat}
(weight : Fin n → Fin n → WithTop Int) (source target : Fin n) (distance : Int)
(hDistance : (floydWarshall weight).ret source target = (distance : WithTop Int)) :
∃ path, IsWeightedPath weight source target path ∧
pathWeight weight path = (distance : WithTop Int)
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:40
def pathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
List (Fin n) → WithTop Int
| [] => 0
| [_] => 0
| source :: target :: rest =>
weight source target + pathWeight weight (target :: rest)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:32
Uses 5 · Used by 2
TheoremNo path is shorter than the Floyd–Warshall distance#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), suppose that \(w\) has no negative cycle, and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). Then for all vertices \(s\) and \(t\) and every weighted path \(p\) from \(s\) to \(t\) (a nonempty vertex sequence from \(s\) to \(t\) in which every consecutive pair has finite weight), \(D(s, t)\) is at most the weight of \(p\), the sum of the weights of its consecutive pairs.
theorem floydWarshall_distance_minimal {n : Nat}
(weight : Fin n → Fin n → WithTop Int) (source target : Fin n)
(path : List (Fin n)) (hNoCycle : NoNegativeCycle weight)
(hPath : IsWeightedPath weight source target path) :
(floydWarshall weight).ret source target ≤ pathWeight weight path
def NoNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
¬HasNegativeCycle weight
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:67
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:40
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
def pathWeight {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
List (Fin n) → WithTop Int
| [] => 0
| [_] => 0
| source :: target :: rest =>
weight source target + pathWeight weight (target :: rest)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:32
TheoremFloyd–Warshall reports \(\infty\) exactly for unreachable pairs#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). For all vertices \(s\) and \(t\), \(D(s, t) = \infty\) if and only if there is no weighted path from \(s\) to \(t\), that is, no nonempty vertex sequence from \(s\) to \(t\) in which every consecutive pair has finite weight.
theorem floydWarshall_distance_eq_top_iff {n : Nat}
(weight : Fin n → Fin n → WithTop Int) (source target : Fin n) :
(floydWarshall weight).ret source target = ⊤ ↔
¬∃ path, IsWeightedPath weight source target path
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
def IsWeightedPath {n : Nat} (weight : Fin n → Fin n → WithTop Int)
(source target : Fin n) (path : List (Fin n)) : Prop :=
path.IsChainFromTo (fun left right => weight left right ≠ ⊤) source target
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:40
TheoremA negative diagonal entry in Floyd–Warshall reveals a negative cycle#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). If \(D(v, v) < 0\) for some vertex \(v\), then \(w\) has a negative cycle: a vertex sequence \(v_0, v_1, \dots, v_m\) with \(m \ge 1\) and \(v_m = v_0\), whose vertices \(v_0, \dots, v_{m-1}\) are pairwise distinct, in which every consecutive pair has finite weight, and whose total weight is negative.
theorem floydWarshall_hasNegativeDiagonal_sound {n : Nat}
(weight : Fin n → Fin n → WithTop Int)
(hNegative : hasNegativeDiagonal (floydWarshall weight).ret = true) :
HasNegativeCycle weight
def hasNegativeDiagonal {n : Nat} (distance : Fin n → Fin n → WithTop Int) : Bool :=
(List.finRange n).any fun vertex => decide (distance vertex vertex < 0)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:136
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
def HasNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
∃ cycle, IsNegativeCycle weight cycle
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:63
Uses 9 · Used by 1
TheoremWithout negative cycles, Floyd–Warshall finds no negative diagonal entry#✓fully proved
Let \(w\) assign a weight in \(\mathbb{Z} \cup \{\infty\}\) to each ordered pair of vertices in \(\{0, \dots, n-1\}\), and let \(D\) be the distance matrix computed by Floyd–Warshall from \(w\). If \(w\) has no negative cycle, then the negative-diagonal check on \(D\) returns false, that is, \(D(v, v) \ge 0\) for every vertex \(v\).
theorem floydWarshall_hasNegativeDiagonal_eq_false {n : Nat}
(weight : Fin n → Fin n → WithTop Int) (hNoCycle : NoNegativeCycle weight) :
hasNegativeDiagonal (floydWarshall weight).ret = false
def NoNegativeCycle {n : Nat} (weight : Fin n → Fin n → WithTop Int) : Prop :=
¬HasNegativeCycle weight
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:67
def hasNegativeDiagonal {n : Nat} (distance : Fin n → Fin n → WithTop Int) : Bool :=
(List.finRange n).any fun vertex => decide (distance vertex vertex < 0)
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:136
@[no_expose]
def floydWarshall {n : Nat} (weight : Fin n → Fin n → WithTop Int) :
TimeM Cost (Fin n → Fin n → WithTop Int) :=
let Table := Vector (Vector (WithTop Int) n) n
let tableGet (table : Table) (i j : Fin n) : WithTop Int := (table.get i).get j
let rec initializeRow (rowIndex : Fin n) :
(j : Nat) → j ≤ n → TimeM Cost (Vector (WithTop Int) j)
| 0, _ => pure #v[]
| j + 1, hj => do
let row ← initializeRow rowIndex j (by omega)
TimeM.tick ⟨1, 0⟩
let column : Fin n := ⟨j, by omega⟩
⋯
CSLibExt/Algorithms/Lean/Graph/ShortestPath/FloydWarshall/Basic.lean:88
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.