Skip to content

Commit eacce15

Browse files
theory: AntiEcho × IsArgmin tropical decomposition (#72)
## Summary Cashes the headline claim from `/tmp/echo-types-exploration/coecho.md` §3 ("Resolution of the EchoTropical tension") at the structural level: `TropEcho` / `IsArgmin` decompose into Echo evidence + a Π-quantified complement bound, with an AntiEcho-flavoured corollary exposing that bound as a Π of negative data over the candidate set. New module `proofs/agda/AntiEchoTropical.agda`. Neither `AntiEcho.agda` (from #69) nor `EchoTropical.agda` is modified — the bridge stays isolated so PR scope is tight. ### Headline theorem (both directions, both round-trips `refl`, packaged as `_↔_`) ```agda antiecho-tropical-decompose : ∀ (y : ℕ) → TropEcho y ↔ (Echo score y × (∀ z → y ≤ score z)) ``` The forward direction projects `(x , p , bnd) ↦ ((x , p) , bnd)` — pure Σ-re-association because the optimality factor `∀ z → y ≤ score z` doesn't depend on `x`. The backward direction undoes it. Both round-trips are definitionally `refl`. No decidability, no funext, no path algebra. Packaged via stdlib `Function.Bundles._↔_` and `mk↔ₛ′`, matching the convention from `Echo-comp-iso` / `cancel-iso`. ### `IsArgmin`-level restatement (the per-element identity) ```agda isargmin-decompose : ∀ (x : Candidate) (y : ℕ) → IsArgmin x y ↔ ((score x ≡ y) × (∀ z → y ≤ score z)) ``` `IsArgmin` IS the product by definition, so the iso to the product is the identity. Pinned for callers thinking in `IsArgmin`-shaped terms. ### AntiEcho-flavoured corollary (the Π-bound as a Π of misses) The optimality factor `∀ z → y ≤ score z` is equivalent on ℕ to the AntiEcho-shaped statement "no candidate witnesses a value strictly below `y`": ```agda optimality-as-antiecho-flavour-to : (∀ z → y ≤ score z) → (∀ z → score z < y → ⊥) optimality-as-antiecho-flavour-from : (∀ z → score z < y → ⊥) → (∀ z → y ≤ score z) ``` with the small order-conversion lemmas `≤⇒¬<` / `¬<⇒≤` shipped in-module. Composite version (Echo + Π-of-negation): ```agda tropdecomp-antiecho-to : TropEcho y → Echo score y × (∀ z → score z < y → ⊥) tropdecomp-antiecho-from : Echo score y × (∀ z → score z < y → ⊥) → TropEcho y ``` This is the *Π-form* AntiEcho variant from `coecho.md` §1(c) (`AntiEcho_Π = ¬ Echo`), specialised to the strict-below stratum. The Σ-form `AntiEcho` carrier from `AntiEcho.agda` is the witness-recording primitive; the Π-form above is the exhaustive global statement that names what `IsArgmin` was carrying implicitly. ### Scope notes - Specialised to the concrete `Candidate → ℕ` setting of `EchoTropical.agda`. A generic-codomain version would need a `≤`-bearing ordered codomain and the decidability hypothesis from `coecho.md` §3 closing remark — deferred. - `Smoke.agda` pins all 14 headlines via `using` so silent renames or a slide back to ad-hoc tropical decoration trips CI fast. - `--safe --without-K` clean. No postulates. No funext. No path algebra beyond constructor-driven trichotomy on `_≤_`/`_<_`. ### PR base / stacking Branched from `origin/theory/antiecho-thin-slice` (so `AntiEcho` is in scope) but **PR base is `main`** per the stacked-PR-orphan-trap policy. The cumulative diff currently includes #69's content; when #69 merges the diff simplifies automatically. ## Test plan - [ ] CI runs `agda -i proofs/agda proofs/agda/All.agda` — exits 0. - [ ] CI runs `agda -i proofs/agda proofs/agda/Smoke.agda` — exits 0. - [ ] All 14 pinned headlines in `Smoke.agda` resolve. - [ ] No new postulates / escape pragmas introduced. **Note on local verification.** Settings restrictions in this sandbox blocked local `agda` invocation on this worktree (the project's `Bash(agda *)` allow rule did not apply to this session). Proofs are pure Σ-currying / pattern-matching + two small ℕ order-conversion lemmas — expected to typecheck on the existing CI gate. ## Refs - Refs #69 — depends on the `AntiEcho` module from the AntiEcho thin slice. - Refs `docs/echo-types/roadmap.md` CoEcho entry ("Possibly resolves the quantitative / structural tension hinted at by `EchoTropical`"). - Refs `/tmp/echo-types-exploration/coecho.md` §3 ("Resolution of the EchoTropical tension") + §5 obligation 6 (`coecho-tropical-decompose`). Does NOT Close anything. The CoEcho roadmap entry stays open until decided by the owner; this PR cashes the structural half. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 35e1739 commit eacce15

3 files changed

Lines changed: 238 additions & 0 deletions

File tree

proofs/agda/All.agda

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ open import EchoEpistemic
1414
open import EchoLinear
1515
open import EchoGraded
1616
open import EchoTropical
17+
open import AntiEchoTropical
1718
open import EchoIntegration
1819
open import EchoCNOBridge
1920

proofs/agda/AntiEchoTropical.agda

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
{-# OPTIONS --safe --without-K #-}
2+
3+
-- AntiEcho × EchoTropical — the tropical decomposition.
4+
--
5+
-- Headline (this module). The tropical argmin carrier `TropEcho y`
6+
-- from `EchoTropical.agda` decomposes definitionally into Echo
7+
-- evidence and a Π-quantified complement bound:
8+
--
9+
-- TropEcho y ↔ Echo score y × (∀ z → y ≤ score z)
10+
--
11+
-- Both round-trips are `refl` once the Σ-shape of `IsArgmin` is
12+
-- unfolded — no decidability, no funext, no path algebra. This
13+
-- cashes the headline claim from `/tmp/echo-types-exploration/coecho.md`
14+
-- §3 ("Resolution of the EchoTropical tension") at the structural
15+
-- level: `IsArgmin` is exactly Echo (positive provenance witness)
16+
-- conjoined with a uniform negative bound over the codomain
17+
-- complement — the structure that motivated naming `AntiEcho` in the
18+
-- first place. See `coecho.md` §5 obligation 6
19+
-- (`coecho-tropical-decompose`).
20+
--
21+
-- AntiEcho flavour of the optimality side. The Π-bound
22+
-- `∀ z → y ≤ score z` is equivalent (on ℕ) to the AntiEcho-shaped
23+
-- "no candidate produces a strict-below miss":
24+
--
25+
-- ∀ z → score z < y → ⊥
26+
--
27+
-- which reads "for every candidate `z`, the assumption that `z`
28+
-- scores strictly below `y` is empty" — a Π of negative data over
29+
-- the candidate set, exactly the AntiEcho idiom. The forward
30+
-- direction (`≤ ⇒ ¬<`) is uniform and unconditional; the backward
31+
-- direction (`¬< ⇒ ≤`) uses the decidable trichotomy on ℕ and so
32+
-- ships as a separate lemma in the AntiEcho-flavour corollary.
33+
--
34+
-- Scope. New module, neither `AntiEcho.agda` nor `EchoTropical.agda`
35+
-- is modified. Specialised to the concrete `Candidate → ℕ` setting
36+
-- of `EchoTropical.agda`; a generic-codomain version is deferred
37+
-- (would need a `≤`-bearing ordered codomain).
38+
39+
module AntiEchoTropical where
40+
41+
open import Data.Empty using (⊥; ⊥-elim)
42+
open import Data.Nat.Base using (ℕ; zero; suc; _≤_; _<_; z≤n; s≤s)
43+
open import Data.Product.Base using (Σ; _×_; _,_; proj₁; proj₂)
44+
open import Function.Bundles using (_↔_; mk↔ₛ′)
45+
open import Relation.Binary.PropositionalEquality using (_≡_; refl)
46+
47+
open import Echo using (Echo)
48+
open import AntiEcho using (AntiEcho)
49+
open import EchoTropical using (Candidate; score; IsArgmin; TropEcho)
50+
51+
----------------------------------------------------------------------
52+
-- The headline decomposition: TropEcho ↔ Echo × Π-bound.
53+
--
54+
-- `TropEcho y` unfolds to
55+
-- Σ Candidate (λ x → score x ≡ y × (∀ z → y ≤ score z))
56+
-- and the inner second conjunct does not depend on `x`. So
57+
-- Σ-currying / re-association gives the iso with
58+
-- Echo score y × (∀ z → y ≤ score z)
59+
-- on the nose: both round-trips are `refl`, no decidability needed.
60+
--
61+
-- This is the structural half of the
62+
-- "Echo × Π AntiEcho ≃ IsArgmin" claim from `coecho.md` §3 — pure
63+
-- product re-shape. The AntiEcho reading of the Π factor is the
64+
-- corollary that follows.
65+
66+
antiecho-tropical-decompose-to :
67+
{y : ℕ} TropEcho y Echo score y × ( z y ≤ score z)
68+
antiecho-tropical-decompose-to (x , p , bnd) = (x , p) , bnd
69+
70+
antiecho-tropical-decompose-from :
71+
{y : ℕ} Echo score y × ( z y ≤ score z) TropEcho y
72+
antiecho-tropical-decompose-from ((x , p) , bnd) = x , p , bnd
73+
74+
antiecho-tropical-decompose-to-from :
75+
{y : ℕ} (r : Echo score y × ( z y ≤ score z))
76+
antiecho-tropical-decompose-to (antiecho-tropical-decompose-from r) ≡ r
77+
antiecho-tropical-decompose-to-from ((x , p) , bnd) = refl
78+
79+
antiecho-tropical-decompose-from-to :
80+
{y : ℕ} (t : TropEcho y)
81+
antiecho-tropical-decompose-from (antiecho-tropical-decompose-to t) ≡ t
82+
antiecho-tropical-decompose-from-to (x , p , bnd) = refl
83+
84+
-- Packaged as a stdlib `_↔_` (bijection / bi-invertible map),
85+
-- matching the convention used for `Echo-comp-iso` and `cancel-iso`
86+
-- in `Echo.agda`.
87+
antiecho-tropical-decompose :
88+
(y : ℕ) TropEcho y ↔ (Echo score y × ( z y ≤ score z))
89+
antiecho-tropical-decompose y =
90+
mk↔ₛ′
91+
(λ t antiecho-tropical-decompose-to {y = y} t)
92+
(λ r antiecho-tropical-decompose-from {y = y} r)
93+
(λ r antiecho-tropical-decompose-to-from {y = y} r)
94+
(λ t antiecho-tropical-decompose-from-to {y = y} t)
95+
96+
----------------------------------------------------------------------
97+
-- `IsArgmin`-level restatement.
98+
--
99+
-- The decomposition above lives at the `TropEcho` level (the Σ over
100+
-- candidates). The per-element version on `IsArgmin` is even more
101+
-- trivial: `IsArgmin x y` IS the product `score x ≡ y × (∀ z → y ≤ score z)`
102+
-- by definition, so the iso to the same product is the identity.
103+
-- Pinned for use by callers who think in `IsArgmin`-shaped terms.
104+
105+
isargmin-decompose-to :
106+
{x : Candidate} {y : ℕ}
107+
IsArgmin x y (score x ≡ y) × ( z y ≤ score z)
108+
isargmin-decompose-to (p , bnd) = p , bnd
109+
110+
isargmin-decompose-from :
111+
{x : Candidate} {y : ℕ}
112+
(score x ≡ y) × ( z y ≤ score z) IsArgmin x y
113+
isargmin-decompose-from (p , bnd) = p , bnd
114+
115+
isargmin-decompose :
116+
(x : Candidate) (y : ℕ)
117+
IsArgmin x y ↔ ((score x ≡ y) × ( z y ≤ score z))
118+
isargmin-decompose x y =
119+
mk↔ₛ′
120+
(λ a isargmin-decompose-to {x = x} {y = y} a)
121+
(λ r isargmin-decompose-from {x = x} {y = y} r)
122+
(λ _ refl)
123+
(λ _ refl)
124+
125+
----------------------------------------------------------------------
126+
-- AntiEcho-flavoured corollary: the Π-bound as a Π of negative data.
127+
--
128+
-- The optimality factor `∀ z → y ≤ score z` is equivalent on ℕ to
129+
-- the AntiEcho-shaped statement
130+
--
131+
-- ∀ z → score z < y → ⊥
132+
--
133+
-- "every candidate, treated as a potential strict-below witness
134+
-- against `y`, lands in the empty type" — a Π of AntiEcho-style
135+
-- negative evidence over the candidate set. This makes the Π factor
136+
-- of the decomposition syntactically AntiEcho-flavoured rather than
137+
-- just structurally a Π.
138+
--
139+
-- Forward direction (`bound → no-strict-below-miss`) is uniform on
140+
-- ℕ and unconditional. Backward direction (`no-strict-below-miss →
141+
-- bound`) uses the decidable trichotomy on ℕ; both directions are
142+
-- discharged here from the constructors of `_≤_` / `_<_` (no extra
143+
-- imports needed because the candidate-side `score` lands in ℕ
144+
-- explicitly, so we only need the two small order conversions
145+
-- below).
146+
--
147+
-- Per `coecho.md` §3 closing remark, the *generic-codomain* backward
148+
-- direction would need a decidable order on the codomain. Here we
149+
-- avoid that hypothesis by working over ℕ concretely (the codomain
150+
-- of `score`); decidable trichotomy on ℕ is pattern-matchable, so
151+
-- the conversion is constructive.
152+
153+
-- y ≤ n → n < y → ⊥
154+
≤⇒¬< : {y n : ℕ} y ≤ n n < y
155+
≤⇒¬< z≤n ()
156+
≤⇒¬< (s≤s p) (s≤s q) = ≤⇒¬< p q
157+
158+
-- ¬ (n < y) → y ≤ n
159+
¬<⇒≤ : {y n : ℕ} (n < y ⊥) y ≤ n
160+
¬<⇒≤ {y = zero} _ = z≤n
161+
¬<⇒≤ {y = suc _} {n = zero} ¬p = ⊥-elim (¬p (s≤s z≤n))
162+
¬<⇒≤ {y = suc _} {n = suc _} ¬p = s≤s (¬<⇒≤ (λ q ¬p (s≤s q)))
163+
164+
-- The optimality factor, in AntiEcho-shaped form. A Π over
165+
-- candidates of a constructive miss-witness against any value
166+
-- strictly below `y`.
167+
optimality-as-antiecho-flavour-to :
168+
{y : ℕ} ( z y ≤ score z) ( z score z < y ⊥)
169+
optimality-as-antiecho-flavour-to bnd z lt = ≤⇒¬< (bnd z) lt
170+
171+
optimality-as-antiecho-flavour-from :
172+
{y : ℕ} ( z score z < y ⊥) ( z y ≤ score z)
173+
optimality-as-antiecho-flavour-from no-miss z = ¬<⇒≤ (no-miss z)
174+
175+
----------------------------------------------------------------------
176+
-- Composite: TropEcho ↔ Echo × (Π-of-AntiEcho-flavoured-misses).
177+
--
178+
-- The forward direction is the cleanest landing of the headline:
179+
-- TropEcho data yields Echo evidence + a Π of negative data of
180+
-- AntiEcho shape over the candidate set. The backward direction
181+
-- ships via `¬<⇒≤` on ℕ (decidable codomain hypothesis discharged
182+
-- concretely, not assumed abstractly).
183+
184+
tropdecomp-antiecho-to :
185+
{y : ℕ} TropEcho y
186+
Echo score y × ( z score z < y ⊥)
187+
tropdecomp-antiecho-to t with antiecho-tropical-decompose-to t
188+
... | (e , bnd) = e , optimality-as-antiecho-flavour-to bnd
189+
190+
tropdecomp-antiecho-from :
191+
{y : ℕ}
192+
Echo score y × ( z score z < y ⊥)
193+
TropEcho y
194+
tropdecomp-antiecho-from (e , no-miss) =
195+
antiecho-tropical-decompose-from
196+
(e , optimality-as-antiecho-flavour-from no-miss)
197+
198+
----------------------------------------------------------------------
199+
-- Note on the AntiEcho carrier appearance.
200+
--
201+
-- The Π factor `∀ z → score z < y → ⊥` does not name `AntiEcho`
202+
-- directly because `AntiEcho score y'` for a *specific* `y'` is
203+
-- "some candidate misses `y'`" — a Σ. The dual statement we need
204+
-- here is "no candidate witnesses a value strictly below `y`",
205+
-- which is a Π of *negations* of `score z ≡ y'` for `y' < y`.
206+
-- That is the *Π-form* AntiEcho variant (`coecho.md` §1(c),
207+
-- catalogued as `AntiEcho_Π = ¬ Echo`), specialised to the
208+
-- strict-below stratum. The Σ-form `AntiEcho` from `AntiEcho.agda`
209+
-- is the witness-recording primitive; the Π-form above is the
210+
-- exhaustive global statement. The headline of this module is the
211+
-- structural decomposition (TropEcho ↔ Echo × Π-bound); the
212+
-- AntiEcho-flavoured restatement is the syntactic bridge.

proofs/agda/Smoke.agda

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,31 @@ open import EchoTropical using
324324
; distinct-candidates-same-visible-distinct-echo
325325
)
326326

327+
-- AntiEcho × EchoTropical (theory/antiecho-tropical-decompose):
328+
-- the headline "Echo × Π-bound" decomposition of TropEcho /
329+
-- IsArgmin from `coecho.md` §3 / §5 obligation 6. Both
330+
-- round-trips are `refl` once IsArgmin's Σ-shape is unfolded;
331+
-- the AntiEcho-flavoured corollary expresses the Π-bound as
332+
-- Π of negative data over the candidate set (Π-form AntiEcho,
333+
-- `coecho.md` §1(c)). Pinned so a rename or a slide back to
334+
-- ad-hoc tropical decoration fails CI fast.
335+
open import AntiEchoTropical using
336+
( antiecho-tropical-decompose-to
337+
; antiecho-tropical-decompose-from
338+
; antiecho-tropical-decompose-to-from
339+
; antiecho-tropical-decompose-from-to
340+
; antiecho-tropical-decompose
341+
; isargmin-decompose-to
342+
; isargmin-decompose-from
343+
; isargmin-decompose
344+
; ≤⇒¬<
345+
; ¬<⇒≤
346+
; optimality-as-antiecho-flavour-to
347+
; optimality-as-antiecho-flavour-from
348+
; tropdecomp-antiecho-to
349+
; tropdecomp-antiecho-from
350+
)
351+
327352
open import EchoIntegration using
328353
( knowledge-preserved-under-choreo
329354
; merged-at-residue

0 commit comments

Comments
 (0)