|
| 1 | +/- |
| 2 | +Copyright 2026 Hyphaeic SPC. |
| 3 | +
|
| 4 | +Licensed under the Hyphaeic Public License, Version 1.0 (the |
| 5 | +"License"); you may not use this file except in compliance with |
| 6 | +the License. You may obtain a copy of the License at |
| 7 | +
|
| 8 | +https://github.com/hyphaeic/hpl |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| 13 | +implied. See the License for the specific language governing |
| 14 | +permissions and limitations under the License. |
| 15 | +
|
| 16 | +# The Routing Graph `G_ρ` |
| 17 | +
|
| 18 | +The routing dependency graph induced by a `RoutingSpecification`, together with |
| 19 | +the finite-DAG longest-path and reachability machinery used throughout Phase 8 |
| 20 | +(timing bounds, compile-time verification, synchronization). |
| 21 | +
|
| 22 | +## Mathematical Content (fdrs.md lines 6110-6167) |
| 23 | +
|
| 24 | +**Definition 119** (Routing dependency graph): vertices are junction points |
| 25 | +`(T, s)`; an edge `(A, s_A) → (B, s_B)` exists when some routing rule sends A's |
| 26 | +overflow at `s_A` to B at `s_B`. |
| 27 | +
|
| 28 | +**Definition 120** (Acyclic routing): `G_ρ` is a DAG. |
| 29 | +
|
| 30 | +**Definition 121** (Routing depth): the longest source→`(T, s)` path length. |
| 31 | +
|
| 32 | +**Proposition 108** (Finite routing depth): on a finite graph the depth is bounded. |
| 33 | +
|
| 34 | +Vertices are modelled as `ℕ × ℕ = (timeline id, cylinder code)`, matching the |
| 35 | +`RoutingRule` encoding (and the `ℕ × ℕ` vertex type already used by the |
| 36 | +reachability decision API in `Verification/CompileTime.lean`). Because a |
| 37 | +specification carries a *finite* `List` of rules, every quantity here is |
| 38 | +computable and every graph property is decidable. |
| 39 | +
|
| 40 | +## References |
| 41 | +
|
| 42 | +- fdrs.md, Phase 8, §8.4 (lines 6110-6167) |
| 43 | +-/ |
| 44 | + |
| 45 | +import FdrsFormal.Composition.Verification.Specification |
| 46 | +import Mathlib.Data.List.Dedup |
| 47 | + |
| 48 | +namespace FdrsFormal.Composition.RoutingGraph |
| 49 | + |
| 50 | +open FdrsFormal.Composition.Verification |
| 51 | + |
| 52 | +/-! ## Vertices and edges -/ |
| 53 | + |
| 54 | +/-- A vertex of `G_ρ`: a junction point `(timeline, cylinder code)`. -/ |
| 55 | +abbrev Vertex := ℕ × ℕ |
| 56 | + |
| 57 | +/-- Source endpoint `(A, s_A)` of a routing rule. -/ |
| 58 | +def ruleSrc (r : RoutingRule) : Vertex := (r.sourceTimeline, r.sourceCylinder) |
| 59 | + |
| 60 | +/-- Target endpoint `(B, s_B)` of a routing rule. -/ |
| 61 | +def ruleTgt (r : RoutingRule) : Vertex := (r.targetTimeline, r.targetCylinder) |
| 62 | + |
| 63 | +/-- |
| 64 | +**fdrs.md Definition 119**: the vertex set `V` of `G_ρ`. |
| 65 | +
|
| 66 | +All junction points mentioned by the specification (as a source or a target), |
| 67 | +deduplicated. |
| 68 | +-/ |
| 69 | +def vertices (spec : RoutingSpecification) : List Vertex := |
| 70 | + ((spec.rules.map ruleSrc) ++ (spec.rules.map ruleTgt)).dedup |
| 71 | + |
| 72 | +/-- |
| 73 | +Out-neighbours of `u`: the target of every rule whose source is `u`. |
| 74 | +
|
| 75 | +One entry per matching rule, so `(successors spec u).length` is the routing |
| 76 | +action multiplicity `|ρ(A, s_A, _, _)|` (Definition 123 / 128). |
| 77 | +-/ |
| 78 | +def successors (spec : RoutingSpecification) (u : Vertex) : List Vertex := |
| 79 | + (spec.rules.filter (fun r => decide (ruleSrc r = u))).map ruleTgt |
| 80 | + |
| 81 | +/-- |
| 82 | +In-neighbours of `v`: the source of every rule whose target is `v`. |
| 83 | +
|
| 84 | +This is the multiset of incoming edges `{(A, s_A) : ((A, s_A), v) ∈ E}` used by |
| 85 | +Definition 121 (routing depth) and Definition 129 (synchronization point). |
| 86 | +-/ |
| 87 | +def predecessors (spec : RoutingSpecification) (v : Vertex) : List Vertex := |
| 88 | + (spec.rules.filter (fun r => decide (ruleTgt r = v))).map ruleSrc |
| 89 | + |
| 90 | +/-- |
| 91 | +**fdrs.md Definition 123/128**: fanout `|ρ(A, s_A, _, _)|`, the number of |
| 92 | +routing actions out of `u`. |
| 93 | +-/ |
| 94 | +def fanout (spec : RoutingSpecification) (u : Vertex) : ℕ := (successors spec u).length |
| 95 | + |
| 96 | +/-! ## Routing depth (Definition 121) via DAG longest path -/ |
| 97 | + |
| 98 | +/-- `(l.map f).foldr max 0` is bounded by `b` when every `f x` is. -/ |
| 99 | +private theorem foldr_max_le {α : Type*} (f : α → ℕ) (b : ℕ) : |
| 100 | + ∀ (l : List α), (∀ x ∈ l, f x ≤ b) → (l.map f).foldr max 0 ≤ b := by |
| 101 | + intro l |
| 102 | + induction l with |
| 103 | + | nil => intro _; exact Nat.zero_le b |
| 104 | + | cons x xs ih => |
| 105 | + intro h |
| 106 | + simp only [List.map_cons, List.foldr_cons] |
| 107 | + exact max_le (h x (by simp)) (ih (fun y hy => h y (by simp [hy]))) |
| 108 | + |
| 109 | +/-- |
| 110 | +One longest-path relaxation pass. |
| 111 | +
|
| 112 | +A source (no predecessors) has depth `0`; otherwise depth is `1 +` the maximum |
| 113 | +predecessor depth under the current estimate `d`. |
| 114 | +-/ |
| 115 | +def depthStep (spec : RoutingSpecification) (d : Vertex → ℕ) (v : Vertex) : ℕ := |
| 116 | + if (predecessors spec v).isEmpty then 0 |
| 117 | + else 1 + ((predecessors spec v).map d).foldr max 0 |
| 118 | + |
| 119 | +/-- |
| 120 | +Iterate `depthStep` `n` times starting from the all-zero estimate. |
| 121 | +
|
| 122 | +On a finite DAG, `n = |V|` passes converge to the true longest-path length |
| 123 | +(Definition 121); on any graph the result is bounded by `n` (`depthIter_le`). |
| 124 | +-/ |
| 125 | +def depthIter (spec : RoutingSpecification) : ℕ → (Vertex → ℕ) |
| 126 | + | 0 => fun _ => 0 |
| 127 | + | n + 1 => fun v => depthStep spec (depthIter spec n) v |
| 128 | + |
| 129 | +/-- After `b`-bounded predecessor estimates, one relaxation pass stays `≤ b + 1`. -/ |
| 130 | +private theorem depthStep_le (spec : RoutingSpecification) (d : Vertex → ℕ) (v : Vertex) |
| 131 | + (b : ℕ) (h : ∀ u ∈ predecessors spec v, d u ≤ b) : depthStep spec d v ≤ b + 1 := by |
| 132 | + unfold depthStep |
| 133 | + split |
| 134 | + · exact Nat.zero_le _ |
| 135 | + · have hb : ((predecessors spec v).map d).foldr max 0 ≤ b := foldr_max_le d b _ h |
| 136 | + omega |
| 137 | + |
| 138 | +/-- Each relaxation pass adds at most one, so `n` passes stay `≤ n`. -/ |
| 139 | +theorem depthIter_le (spec : RoutingSpecification) : |
| 140 | + ∀ (n : ℕ) (v : Vertex), depthIter spec n v ≤ n := by |
| 141 | + intro n |
| 142 | + induction n with |
| 143 | + | zero => intro v; exact Nat.zero_le _ |
| 144 | + | succ n ih => |
| 145 | + intro v |
| 146 | + have hstep : depthIter spec (n + 1) v = depthStep spec (depthIter spec n) v := rfl |
| 147 | + rw [hstep] |
| 148 | + exact depthStep_le spec (depthIter spec n) v n (fun u _ => ih u) |
| 149 | + |
| 150 | +/-! ## Reachability and acyclicity (Definition 120) -/ |
| 151 | + |
| 152 | +/-- One BFS expansion: keep the current frontier and add all its successors. -/ |
| 153 | +def expand (spec : RoutingSpecification) (S : List Vertex) : List Vertex := |
| 154 | + (S ++ S.flatMap (successors spec)).dedup |
| 155 | + |
| 156 | +/-- Iterate `expand` `n` times. -/ |
| 157 | +def reachIter (spec : RoutingSpecification) : ℕ → List Vertex → List Vertex |
| 158 | + | 0, S => S |
| 159 | + | n + 1, S => reachIter spec n (expand spec S) |
| 160 | + |
| 161 | +/-- |
| 162 | +Vertices reachable from `u` in at least one routing step. |
| 163 | +
|
| 164 | +Starts from `u`'s successors (one edge taken) and saturates within `|V|` |
| 165 | +expansions, which suffices on a graph with `|V|` vertices. |
| 166 | +-/ |
| 167 | +def reachableFrom (spec : RoutingSpecification) (u : Vertex) : List Vertex := |
| 168 | + reachIter spec (vertices spec).length (successors spec u) |
| 169 | + |
| 170 | +/-- `u` reaches `v` along at least one routing edge. -/ |
| 171 | +def Reaches (spec : RoutingSpecification) (u v : Vertex) : Prop := |
| 172 | + v ∈ reachableFrom spec u |
| 173 | + |
| 174 | +instance (spec : RoutingSpecification) (u v : Vertex) : Decidable (Reaches spec u v) := |
| 175 | + inferInstanceAs (Decidable (v ∈ reachableFrom spec u)) |
| 176 | + |
| 177 | +/-- |
| 178 | +**fdrs.md Definition 120**: `G_ρ` is acyclic when no junction can reach itself. |
| 179 | +-/ |
| 180 | +def Acyclic (spec : RoutingSpecification) : Prop := |
| 181 | + ∀ v ∈ vertices spec, ¬ Reaches spec v v |
| 182 | + |
| 183 | +instance (spec : RoutingSpecification) : Decidable (Acyclic spec) := |
| 184 | + inferInstanceAs (Decidable (∀ v ∈ vertices spec, ¬ Reaches spec v v)) |
| 185 | + |
| 186 | +/-- |
| 187 | +**fdrs.md Theorem 52**: deadlock-freedom of the system is acyclicity of `G_ρ` |
| 188 | +— a set of mutually waiting timelines is exactly a cycle in the routing graph. |
| 189 | +-/ |
| 190 | +def DeadlockFree (spec : RoutingSpecification) : Prop := Acyclic spec |
| 191 | + |
| 192 | +instance (spec : RoutingSpecification) : Decidable (DeadlockFree spec) := |
| 193 | + inferInstanceAs (Decidable (Acyclic spec)) |
| 194 | + |
| 195 | +/-! ## Bounded fanout / depth (Proposition 109 items 2, 3) -/ |
| 196 | + |
| 197 | +/-- Fanout is bounded by `B` across all junctions. -/ |
| 198 | +def BoundedFanout (spec : RoutingSpecification) (B : ℕ) : Prop := |
| 199 | + ∀ u ∈ vertices spec, fanout spec u ≤ B |
| 200 | + |
| 201 | +instance (spec : RoutingSpecification) (B : ℕ) : Decidable (BoundedFanout spec B) := |
| 202 | + inferInstanceAs (Decidable (∀ u ∈ vertices spec, fanout spec u ≤ B)) |
| 203 | + |
| 204 | +/-- Routing depth is bounded by `D` across all junctions. -/ |
| 205 | +def BoundedDepth (spec : RoutingSpecification) (D : ℕ) : Prop := |
| 206 | + ∀ v ∈ vertices spec, depthIter spec (vertices spec).length v ≤ D |
| 207 | + |
| 208 | +instance (spec : RoutingSpecification) (D : ℕ) : Decidable (BoundedDepth spec D) := |
| 209 | + inferInstanceAs |
| 210 | + (Decidable (∀ v ∈ vertices spec, depthIter spec (vertices spec).length v ≤ D)) |
| 211 | + |
| 212 | +end FdrsFormal.Composition.RoutingGraph |
0 commit comments