1-- Set-theoretic weighted paths: the specification for shortest paths.2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.GraphTheory.WeightedPaths8import Reachability9import Nat.Order1011predicate WeightedGraph (V E weights : Set) :=12 RelationOn(E, V) ∧ FunctionBetween(weights, E, ℕ)1314predicate WeightedEdge (E weights u v cost : Set) :=15 Adjacent(E, u, v) ∧Nat(cost) ∧ weights((u, v)) = cost1617-- A path result is the set-theoretic pair (ending vertex, total cost).18-- Each level is bounded by V × ℕ, and the union over finite levels19-- specifies all finite walks, including those in infinite graphs.20def costStep (V E weights previous : Set) : Set:=21 { p ∈ V × ℕ |∃ u ∈ V, ∃ v ∈ V, ∃ c ∈ ℕ, ∃ k ∈ ℕ,22 (u, c) ∈ previous ∧ WeightedEdge(E, weights, u, v, k) ∧23 p = (v, add(c, k)) }2425def pathsOfLength (V E weights source : Set, n : Nat) →Set26| V, E, weights, source, zero => {(source, 0)}27| V, E, weights, source, succ(n) =>28 costStep(V, E, weights, pathsOfLength(V, E, weights, source, n))2930predicate HasPathCost (V E weights source target cost : Set) :=31∃ n ∈ ℕ, (target, cost) ∈ pathsOfLength(V, E, weights, source, n)3233predicate ShortestPathCost (V E weights source target cost : Set) :=34Nat(cost) ∧ HasPathCost(V, E, weights, source, target, cost) ∧35 (∀ other ∈ ℕ, HasPathCost(V, E, weights, source, target, other) →36 LessEqual(cost, other))3738theorem ShortestPathCost.unique (V E weights source target a b : Set)39requires first : ShortestPathCost(V, E, weights, source, target, a)40requires second : ShortestPathCost(V, E, weights, source, target, b)41shows a = b42proof43rcases first with⟨aNat, aPath, aMinimal⟩44rcases second with⟨bNat, bPath, bMinimal⟩45have aIn := nat.omega.forward with aNat46have bIn := nat.omega.forward with bNat47have ab := aMinimal with b, bIn, bPath48have ba := bMinimal with a, aIn, aPath49exact LessEqual.antisymmetric with aNat, bNat, ab, ba5051theorem pathsOfLength.zero (V E weights source : Set)52shows pathsOfLength(V, E, weights, source, 0) = {(source, 0)}53proof54unfold pathsOfLength55rfl5657theorem pathsOfLength.successor (V E weights source : Set, n : Nat)58shows pathsOfLength(V, E, weights, source, succ(n)) =59 costStep(V, E, weights, pathsOfLength(V, E, weights, source, n))60proof61unfold pathsOfLength62rfl6364theorem HasPathCost.source (V E weights source : Set)65shows HasPathCost(V, E, weights, source, source, 0)66proof67unfold HasPathCost68have zeroNat := nat.omega.forward with Naturals.constructor.zero69have initial : (source, 0) ∈ pathsOfLength(V, E, weights, source, 0)70rw pathsOfLength.zero71exact singleton.self72refine⟨0, zeroNat, initial⟩7374theorem HasPathCost.extend (V E weights source u v c k : Set)75requires hu : u ∈ V76requires hv : v ∈ V77requires hc : Nat(c)78requires hk : Nat(k)79requires reached : HasPathCost(V, E, weights, source, u, c)80requires edge : WeightedEdge(E, weights, u, v, k)81shows HasPathCost(V, E, weights, source, v, add(c, k))82proof83rcases reached with⟨n, hn, previous⟩84have cIn := nat.omega.forward with hc85have kIn := nat.omega.forward with hk86have sumNat := add.closed at k, c with hk87have sumIn := nat.omega.forward with sumNat88have pair := product.pair with hv, sumIn89have stepped : (v, add(c, k)) ∈ costStep(V, E, weights,90 pathsOfLength(V, E, weights, source, n))91exact costStep.membership.backward with⟨pair, u, hu, v, hv, c, cIn, k, kIn, previous, edge, rfl⟩92have nNat := nat.omega.backward with hn93have nextNat := Naturals.constructor.succ with nNat94have nextIn := nat.omega.forward with nextNat95witness succ(n)96constructor97 . exact nextIn98 . rw pathsOfLength.successor99exact stepped100101-- A feasible potential is a lower bound on the cost of *every* walk.102predicate PathPotential (V E weights source labels : Set) :=103 FunctionBetween(labels, V, ℕ) ∧ labels(source) =0∧104 (∀ u ∈ V, ∀ v ∈ V, ∀ k ∈ ℕ,105 WeightedEdge(E, weights, u, v, k) →106 LessEqual(labels(v), add(labels(u), k)))107108theorem PathPotential.lower_bound (V E weights source labels : Set, n : Nat)109requires potential : PathPotential(V, E, weights, source, labels)110shows∀ v ∈ V, ∀ c ∈ ℕ,111 (v, c) ∈ pathsOfLength(V, E, weights, source, n) →112 LessEqual(labels(v), c)113proof114induction n115| zero =>116intros v hv c hc path117rw pathsOfLength.zero at path118have equal := singleton.membership.forward with path119obtain⟨vs, c0⟩:= orderedPair.injective with equal120rcases potential with⟨function, initial, edges⟩121rw [vs, c0, initial]122exact LessEqual.reflexive with Naturals.constructor.zero123| succ(m) using ih =>124intros v hv c hc path125rw pathsOfLength.successor at path126have parts := costStep.membership.forward with path127rcases parts with⟨bounded, u, hu, y, hy, prior, hprior,128 k, hk, earlier, edge, pairShape⟩129obtain⟨vy, cSum⟩:= orderedPair.injective with pairShape130rcases potential with⟨function, initial, edges⟩131have priorBound := ih with u, hu, prior, hprior, earlier132have edgeBound := edges with u, hu, y, hy, k, hk, edge133have uNat := FunctionBetween.apply_closed with function, hu134have yNat := FunctionBetween.apply_closed with function, hy135have uNumber := nat.omega.backward with uNat136have yNumber := nat.omega.backward with yNat137have priorNat := nat.omega.backward with hprior138have kNat := nat.omega.backward with hk139have rightRefl := LessEqual.reflexive with kNat140have sumBound := LessEqual.add with uNumber, priorNat, kNat, kNat, priorBound, rightRefl141have result := LessEqual.transitive with yNumber, *{2}, edgeBound, sumBound142rw [vy, cSum]143exact result144145-- A feasible labeling plus a witnessed path of the same weight is a146-- complete shortest-path certificate, for paths of arbitrary finite length.147theorem PathPotential.certifies_shortest (V E weights source labels target cost : Set)148requires potential : PathPotential(V, E, weights, source, labels)149requires targetIn : target ∈ V150requires costNat : Nat(cost)151requireswitness : HasPathCost(V, E, weights, source, target, cost)152requires value : labels(target) = cost153shows ShortestPathCost(V, E, weights, source, target, cost)154proof155constructor156 . exact costNat157 . constructor158 . exactwitness159 . intros other otherIn otherPath160rcases otherPath with⟨n, nIn, path⟩161have nNat := nat.omega.backward with nIn162have lower := PathPotential.lower_bound with nNat, potential163have bound := lower with target, targetIn, other, otherIn, path164 rwa value at bound165