|
| 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 | +# Synthetic place complex — the Phase-8 concretization bridge |
| 17 | +
|
| 18 | +The corpus carries two network formalizations: the concrete Phase-8 layer |
| 19 | +(`Composition/` — timeline graphs, routing tables, injection queues; June) and the |
| 20 | +abstract SU7 machine (`SyntheticPlace/Network*` — July). Unbridged, they would |
| 21 | +drift into exactly the recreation pattern the SPS series exists to prevent. This |
| 22 | +module welds them, in the SU7.0 style — the concrete layer read as an *instance* |
| 23 | +of the abstract machine: |
| 24 | +
|
| 25 | +* **Shape** — `NetworkShape.ofTimelineGraph`: a Phase-8 `TimelineGraph` IS a |
| 26 | + network shape (places = timeline nodes, coupling edges = the graph's edges). |
| 27 | +* **Grading** — `timelineDeps` + `timeline_graded`: a strictly time-monotone |
| 28 | + timeline graph's edge relation, read as a clause-3 dependency declaration, is |
| 29 | + GRADED — the potential is literally the node's `time` field. Phase 8's |
| 30 | + time-ordering and SU7.1's dependency grading are the same mathematics, now as a |
| 31 | + theorem rather than a remark. |
| 32 | +* **Rule** — `ComplexRule.ofRouting`: a per-edge `RoutingEntry` assignment reads as |
| 33 | + a coupling rule (the entry's `transform` as the grant weight, all-transport, no |
| 34 | + declared carry — the concrete layer's capacity-grant regime, D8), with |
| 35 | + `ofRouting_fanoutLawful`: its fan-out is unconditionally lawful. |
| 36 | +* **THE QUEUE DISCHARGE** — `QueueConfig`: the queue-backed edge register |
| 37 | + (issued/consumed totals + a FIFO buffer, the `Composition/Injection` discipline |
| 38 | + with monoid-valued payloads). `queueReachable_balanced`: the SU6b balance law at |
| 39 | + EVERY capacity — `issued = consumed + buffer.sum`. And the SU7.0-style instance |
| 40 | + theorem **`queueReachable_one_toCurrency`**: a capacity-one queue register IS the |
| 41 | + `CurrencyConfig` register (the projection maps reachable to reachable, issue to |
| 42 | + issue, consume to consume), with `queueBalanced_one_iff` closing the loop. The |
| 43 | + "queue-valued interfaces (capacity > 1)" open of the roadmap is hereby |
| 44 | + discharged as REUSE: the general register exists, its balance law holds, and |
| 45 | + capacity-one is the machine's proven special case. Literal weld to the Phase-8 |
| 46 | + artifact: `payloads` + `payloads_enqueue`/`payloads_dequeue` — the |
| 47 | + `InjectionQueue` operations project onto the buffer discipline. |
| 48 | +
|
| 49 | +**Honest scope.** `ofRouting` reads `transform` as a grant weight — the declared |
| 50 | +interpretation; richer routing semantics (source/sink typing, determinism) live in |
| 51 | +the concrete layer and are not re-legislated here. Swapping `CurrencyConfig` for |
| 52 | +`QueueConfig` inside `CConfig` (the capacity->1 machine) is the mechanical upgrade |
| 53 | +this module licenses but does not perform — the SU7 theorems that would need |
| 54 | +re-proving are exactly the per-edge balance transports, whose queue forms are |
| 55 | +proven here. Leaf module over SU7.1 + Composition. No `sorry`; axiom-clean. |
| 56 | +-/ |
| 57 | +import FdrsFormal.Modes.SyntheticPlace.NetworkComplexStep |
| 58 | +import FdrsFormal.Composition.TimelineGraphs.Definition |
| 59 | +import FdrsFormal.Composition.Routing.Definition |
| 60 | +import FdrsFormal.Composition.Injection.Queue |
| 61 | +import Mathlib.Data.Nat.Pairing |
| 62 | + |
| 63 | +namespace FdrsFormal.Modes.SyntheticPlace |
| 64 | + |
| 65 | +open FdrsFormal.Composition.DeadlockAnalysis |
| 66 | + |
| 67 | +/-! ## 1. Shape: a timeline graph is a network shape -/ |
| 68 | + |
| 69 | +instance : DecidableEq Composition.TimelineGraphs.TimelineNode := fun a b => |
| 70 | + decidable_of_iff (a.time = b.time ∧ a.state = b.state) (by cases a; cases b; simp) |
| 71 | + |
| 72 | +/-- A Phase-8 timeline graph, read as a network shape: places are the timeline |
| 73 | +nodes, coupling edges are the graph's edges. -/ |
| 74 | +def NetworkShape.ofTimelineGraph (G : Composition.TimelineGraphs.TimelineGraph) : |
| 75 | + NetworkShape where |
| 76 | + V := Composition.TimelineGraphs.TimelineNode |
| 77 | + E := {e : Composition.TimelineGraphs.TimelineEdge // e ∈ G.edges} |
| 78 | + src := fun e => e.1.source |
| 79 | + tgt := fun e => e.1.target |
| 80 | + |
| 81 | +/-! ## 2. Grading: Phase-8 time-ordering IS clause-3 dependency grading -/ |
| 82 | + |
| 83 | +/-- The timeline graph's edge relation as a clause-3 dependency declaration |
| 84 | +(operations coded by `Nat.pair time state`; each edge: the target waits for the |
| 85 | +source). -/ |
| 86 | +def timelineDeps (G : Composition.TimelineGraphs.TimelineGraph) : DepGraph where |
| 87 | + dependencies := |
| 88 | + {d | ∃ e ∈ G.edges, d.waiting = Nat.pair e.target.time e.target.state ∧ |
| 89 | + d.waitingFor = Nat.pair e.source.time e.source.state} |
| 90 | + |
| 91 | +/-- **The weld, grading half**: a strictly time-monotone timeline graph's |
| 92 | +dependency declaration is GRADED — the `timeOf` potential is literally the node's |
| 93 | +`time` field. Phase 8's time-ordering and SU7.1's well-formedness are one fact. -/ |
| 94 | +def timeline_graded (G : Composition.TimelineGraphs.TimelineGraph) |
| 95 | + (hstrict : ∀ e ∈ G.edges, e.source.time < e.target.time) : |
| 96 | + TimeOrderedDependencies (timelineDeps G) where |
| 97 | + timeOf := fun op => (Nat.unpair op).1 |
| 98 | + forward := by |
| 99 | + rintro d ⟨e, he, hw, hwf⟩ |
| 100 | + rw [hw, hwf] |
| 101 | + simpa [Nat.unpair_pair] using hstrict e he |
| 102 | + |
| 103 | +/-! ## 3. Rule: a routing assignment is a coupling rule -/ |
| 104 | + |
| 105 | +/-- A per-edge routing assignment read as a coupling rule: the entry's `transform` |
| 106 | +is the grant weight (default `1`), all edges transport, no declared carry (the |
| 107 | +concrete layer's capacity-grant regime, D8), content windows, dependency |
| 108 | +declarations from the graph. -/ |
| 109 | +def ComplexRule.ofRouting (N : NetworkShape) |
| 110 | + (entry : N.E → Composition.Routing.RoutingEntry) (deps : N.V → DepGraph) : |
| 111 | + ComplexRule N ℕ where |
| 112 | + nodeFiber := fun _ => none |
| 113 | + carry := fun _ => none |
| 114 | + species := fun _ => Species.transport |
| 115 | + token := fun _ => 0 |
| 116 | + fanout := fun e _ _ => (entry e).transform.getD 1 |
| 117 | + admit := fun _ g d => d < g |
| 118 | + deps := deps |
| 119 | + |
| 120 | +/-- The routing rule's fan-out is unconditionally lawful (no declared carry, no |
| 121 | +triggers — mirror of `ofRule_fanoutLawful`). -/ |
| 122 | +theorem ofRouting_fanoutLawful {N : NetworkShape} [DecidableEq N.V] [Fintype N.E] |
| 123 | + (entry : N.E → Composition.Routing.RoutingEntry) (deps : N.V → DepGraph) |
| 124 | + (cfg : CConfig N ℕ) (v : N.V) (d : ℕ) : |
| 125 | + FanoutLawful (ComplexRule.ofRouting N entry deps) cfg v d := by |
| 126 | + constructor |
| 127 | + · intro c hc |
| 128 | + exact absurd hc (by simp [ComplexRule.ofRouting]) |
| 129 | + · intro e _ hs |
| 130 | + exact absurd hs (by simp [ComplexRule.ofRouting]) |
| 131 | + |
| 132 | +/-! ## 4. The queue register: capacity->1, balance at every capacity -/ |
| 133 | + |
| 134 | +variable {M : Type*} [AddCommMonoid M] |
| 135 | + |
| 136 | +/-- The queue-backed edge register: the `Composition/Injection` FIFO discipline |
| 137 | +with monoid-valued payloads and the declared ledger. -/ |
| 138 | +structure QueueConfig (M : Type*) where |
| 139 | + issued : M |
| 140 | + consumed : M |
| 141 | + buffer : List M |
| 142 | + |
| 143 | +/-- The empty queue register. -/ |
| 144 | +def QueueConfig.init : QueueConfig M := ⟨0, 0, []⟩ |
| 145 | + |
| 146 | +/-- Issue = FIFO enqueue (the `Injection.enqueue` shape) + ledger. -/ |
| 147 | +def QueueConfig.issue (c : QueueConfig M) (g : M) : QueueConfig M := |
| 148 | + ⟨c.issued + g, c.consumed, c.buffer ++ [g]⟩ |
| 149 | + |
| 150 | +/-- Consume = FIFO dequeue (the `Injection.dequeue` shape) + ledger. -/ |
| 151 | +def QueueConfig.consume (c : QueueConfig M) : QueueConfig M := |
| 152 | + match c.buffer with |
| 153 | + | [] => c |
| 154 | + | g :: rest => ⟨c.issued, c.consumed + g, rest⟩ |
| 155 | + |
| 156 | +/-- Reachability at capacity `cap`: issue only below capacity, consume only |
| 157 | +nonempty. -/ |
| 158 | +inductive QueueReachable (cap : ℕ) : QueueConfig M → Prop |
| 159 | + | init : QueueReachable cap QueueConfig.init |
| 160 | + | issue {c : QueueConfig M} (g : M) (hlen : c.buffer.length < cap) |
| 161 | + (h : QueueReachable cap c) : QueueReachable cap (c.issue g) |
| 162 | + | consume {c : QueueConfig M} (hne : c.buffer ≠ []) |
| 163 | + (h : QueueReachable cap c) : QueueReachable cap c.consume |
| 164 | + |
| 165 | +/-- Balance for queue registers: everything issued is consumed or in the buffer. -/ |
| 166 | +def QueueBalanced (c : QueueConfig M) : Prop := |
| 167 | + c.issued = c.consumed + c.buffer.sum |
| 168 | + |
| 169 | +/-- **The SU6b law at every capacity**: every reachable queue register is balanced. -/ |
| 170 | +theorem queueReachable_balanced {cap : ℕ} {c : QueueConfig M} |
| 171 | + (h : QueueReachable cap c) : QueueBalanced c := by |
| 172 | + induction h with |
| 173 | + | init => simp [QueueBalanced, QueueConfig.init] |
| 174 | + | @issue c g hlen h ih => |
| 175 | + show c.issued + g = c.consumed + (c.buffer ++ [g]).sum |
| 176 | + rw [List.sum_append, List.sum_cons, List.sum_nil, add_zero, ih, add_assoc] |
| 177 | + | @consume c hne h ih => |
| 178 | + rcases hb : c.buffer with _ | ⟨g, rest⟩ |
| 179 | + · exact absurd hb hne |
| 180 | + · have hc : c.consume = ⟨c.issued, c.consumed + g, rest⟩ := by |
| 181 | + unfold QueueConfig.consume |
| 182 | + rw [hb] |
| 183 | + rw [QueueBalanced, hc] |
| 184 | + rw [QueueBalanced, hb] at ih |
| 185 | + simp only [List.sum_cons] at ih |
| 186 | + show c.issued = (c.consumed + g) + rest.sum |
| 187 | + rw [ih, add_assoc] |
| 188 | + |
| 189 | +/-- The capacity-one projection onto the `CurrencyConfig` register. -/ |
| 190 | +def QueueConfig.toCurrency (c : QueueConfig M) : CurrencyConfig M := |
| 191 | + ⟨c.issued, c.consumed, c.buffer.head?⟩ |
| 192 | + |
| 193 | +/-- Capacity-one buffers never exceed one entry. -/ |
| 194 | +theorem queueReachable_one_length {c : QueueConfig M} |
| 195 | + (h : QueueReachable 1 c) : c.buffer.length ≤ 1 := by |
| 196 | + induction h with |
| 197 | + | init => simp [QueueConfig.init] |
| 198 | + | @issue c g hlen h ih => |
| 199 | + simp only [QueueConfig.issue, List.length_append, List.length_cons, List.length_nil] |
| 200 | + omega |
| 201 | + | @consume c hne h ih => |
| 202 | + rcases hb : c.buffer with _ | ⟨g, rest⟩ |
| 203 | + · exact absurd hb hne |
| 204 | + · have hc : c.consume = ⟨c.issued, c.consumed + g, rest⟩ := by |
| 205 | + unfold QueueConfig.consume |
| 206 | + rw [hb] |
| 207 | + rw [hc] |
| 208 | + rw [hb] at ih |
| 209 | + simp only [List.length_cons] at ih |
| 210 | + show rest.length ≤ 1 |
| 211 | + omega |
| 212 | + |
| 213 | +/-- **THE INSTANCE THEOREM (SU7.0 style)**: a capacity-one queue register IS the |
| 214 | +`CurrencyConfig` register — the projection carries reachable states to reachable |
| 215 | +states, issues to issues, consumes to consumes. The queue open is discharged as |
| 216 | +reuse: the machine's proven register is the capacity-one special case. -/ |
| 217 | +theorem queueReachable_one_toCurrency {c : QueueConfig M} |
| 218 | + (h : QueueReachable 1 c) : |
| 219 | + CurrencyReachable (Set.univ : Set M) c.toCurrency := by |
| 220 | + induction h with |
| 221 | + | init => exact CurrencyReachable.init |
| 222 | + | @issue c g hlen h ih => |
| 223 | + have hbe : c.buffer = [] := List.length_eq_zero_iff.mp (by omega) |
| 224 | + have hstep : (c.issue g).toCurrency = c.toCurrency.issue g := by |
| 225 | + simp [QueueConfig.issue, QueueConfig.toCurrency, CurrencyConfig.issue, hbe] |
| 226 | + rw [hstep] |
| 227 | + exact CurrencyReachable.issue _ (Set.mem_univ _) |
| 228 | + (by simp [QueueConfig.toCurrency, hbe]) ih |
| 229 | + | @consume c hne h ih => |
| 230 | + rcases hb : c.buffer with _ | ⟨g, rest⟩ |
| 231 | + · exact absurd hb hne |
| 232 | + · have hre : rest = [] := by |
| 233 | + have := queueReachable_one_length h |
| 234 | + rw [hb] at this |
| 235 | + simpa using List.length_eq_zero_iff.mp (by simpa using this) |
| 236 | + have hstep : c.consume.toCurrency = c.toCurrency.consume := by |
| 237 | + simp [QueueConfig.consume, QueueConfig.toCurrency, CurrencyConfig.consume, |
| 238 | + hb, hre] |
| 239 | + rw [hstep] |
| 240 | + exact CurrencyReachable.consume (g := g) (by simp [QueueConfig.toCurrency, hb]) ih |
| 241 | + |
| 242 | +/-- Balance transfers across the capacity-one projection. -/ |
| 243 | +theorem queueBalanced_one_iff {c : QueueConfig M} (hlen : c.buffer.length ≤ 1) : |
| 244 | + QueueBalanced c ↔ CurrencyBalanced c.toCurrency := by |
| 245 | + rcases hb : c.buffer with _ | ⟨g, rest⟩ |
| 246 | + · simp [QueueBalanced, CurrencyBalanced, QueueConfig.toCurrency, hb] |
| 247 | + · have hre : rest = [] := by |
| 248 | + rw [hb] at hlen |
| 249 | + simpa using List.length_eq_zero_iff.mp (by simpa using hlen) |
| 250 | + simp [QueueBalanced, CurrencyBalanced, QueueConfig.toCurrency, hb, hre] |
| 251 | + |
| 252 | +/-! ## 5. The literal weld to the Phase-8 artifact -/ |
| 253 | + |
| 254 | +/-- Project a Phase-8 `InjectionQueue` onto its payload buffer. -/ |
| 255 | +def payloads (q : Composition.Injection.InjectionQueue) : List ℕ := |
| 256 | + q.entries.map (·.payload) |
| 257 | + |
| 258 | +theorem payloads_enqueue (q : Composition.Injection.InjectionQueue) |
| 259 | + (e : Composition.Injection.InjectionQueueEntry) : |
| 260 | + payloads (Composition.Injection.enqueue q e) = payloads q ++ [e.payload] := by |
| 261 | + simp [payloads, Composition.Injection.enqueue] |
| 262 | + |
| 263 | +theorem payloads_dequeue (q : Composition.Injection.InjectionQueue) |
| 264 | + {e : Composition.Injection.InjectionQueueEntry} |
| 265 | + {q' : Composition.Injection.InjectionQueue} |
| 266 | + (h : Composition.Injection.dequeue q = some (e, q')) : |
| 267 | + payloads q = e.payload :: payloads q' := by |
| 268 | + unfold Composition.Injection.dequeue at h |
| 269 | + rcases hq : q.entries with _ | ⟨x, xs⟩ |
| 270 | + · rw [hq] at h; exact absurd h (by simp) |
| 271 | + · rw [hq] at h |
| 272 | + simp only [Option.some.injEq, Prod.mk.injEq] at h |
| 273 | + obtain ⟨rfl, rfl⟩ := h |
| 274 | + simp [payloads, hq] |
| 275 | + |
| 276 | +/-! ## Axiom audit -/ |
| 277 | + |
| 278 | +#print axioms timeline_graded |
| 279 | +#print axioms ofRouting_fanoutLawful |
| 280 | +#print axioms queueReachable_balanced |
| 281 | +#print axioms queueReachable_one_toCurrency |
| 282 | +#print axioms queueBalanced_one_iff |
| 283 | +#print axioms payloads_dequeue |
| 284 | + |
| 285 | +end FdrsFormal.Modes.SyntheticPlace |
0 commit comments