Skip to content

Commit 177c272

Browse files
theory: EchoApprox composition rung — first slice (retract direction) (#70)
## Summary Extends `proofs/agda/EchoApprox.agda` with the first slice of the axis-2 composition rung from the design note (drafted in `/tmp/echo-types-exploration/axis2-approximate.md`, §7 obligations 2 + 6, plus the canonical-split retract direction). Refs `docs/echo-types/roadmap.md` Axis 2 entry and `docs/echo-types/composition.md` §Q3 — does **not** close either. ## Obligations landed - **`echo-strict→approx`** (§7 #2). General strict ⇒ zero-tolerance approximate. Generalises `echo-approx-intro` from own-fibre points to arbitrary `y` via the codomain equation `p : f x ≡ y`. One extra `subst` along `p`. - **`echo-approx-comp-sound`** (§7 #6). Sound RHS-to-LHS direction of the retract shape from `composition.md` §Q3 / design-note §5. Unpacks the existential and calls `echo-approx-compose`. - **`echo-approx-comp-retract-to`**. Canonical-split LHS → RHS-Σ section of the retract: picks `b := f x`, `ε₁ := zero`, `ε₂ := ε`. Uses `echo-approx-intro` for the inner echo, original bound for the outer. - **`echo-approx-comp-retract-A`**. A-component round-trip `proj₁ ∘ sound ∘ retract-to ≡ proj₁`, proved by `refl`. The retraction direction holds definitionally on the A-component as the design note (§5) predicts. ## Obligations deferred (out of this rung) - §7 #7 separated zero-collapse — needs a separation predicate on the `PseudoMetric` record. - §7 #8 axis-1 shadow agreement — cross-axis classification. - Full retract B-component and tolerance-budget round-trip — needs a `+`-left-identity axiom on `Tolerance` (`zero + ε ≡ ε`) not in the current record. Adding it commits the carrier to a left-unital monoid; deferred as a separate decision. - Lipschitz generalisation (`L_g ≠ 1`) — needs scalar multiplication on `Tol`. ## Docs updated - `docs/echo-types/composition.md` §Q3 promoted from "entirely speculative" to landed-retract-shape with deferred items called out. - `docs/echo-types/roadmap.md` adds a "landed" entry for the composition rung first slice. ## Invariants preserved - `--safe --without-K` - No postulates - No escape pragmas - Funext untouched ## Test plan - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/All.agda` exits 0 - [x] `LC_ALL=C.UTF-8 agda -i proofs/agda proofs/agda/Smoke.agda` exits 0 - [x] No new `postulate`, no escape pragmas, funext not imported - [x] `Smoke.agda` already pins `module Approx` following project convention (per-lemma pins inside parameterised modules require instantiation, which the project does not do for `EchoApprox`). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 482c7a9 commit 177c272

3 files changed

Lines changed: 164 additions & 7 deletions

File tree

docs/echo-types/composition.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,27 @@ is a Lipschitz constant of `g`. This is a crude first guess — the
150150
right form may involve sup-norms, dilation-operators, or
151151
coarser bounds.
152152

153-
*Status.* Entirely speculative. Requires a formal definition of
154-
approximate echo first.
153+
*Status (updated).* No longer entirely speculative. The
154+
non-expansive case (`L_g = 1`) is landed as
155+
`EchoApprox.Approx.echo-approx-compose` in additive form
156+
`(ε₁ + ε₂)-echo(g ∘ f)`. The compositional *shape* — whether the
157+
forward/backward maps form a strict iso analogous to
158+
`Echo-comp-iso` — is settled in the negative: it is a *retract*,
159+
not an iso, because the RHS Σ admits multiple splits of the budget
160+
and the chosen intermediate `b` is not pinned by the input. The
161+
axis-2 design note (`/tmp/echo-types-exploration/axis2-approximate.md`
162+
§5) gives the full discussion.
163+
164+
First slice of the retract landed in `EchoApprox.agda`:
165+
`echo-approx-comp-sound` (RHS-Σ → LHS via `echo-approx-compose`),
166+
`echo-approx-comp-retract-to` (canonical-split LHS → RHS-Σ section
167+
at `b := f x`, `ε₁ := zero`, `ε₂ := ε`), and
168+
`echo-approx-comp-retract-A` (A-component round-trip preserves the
169+
witness up to `refl`). The B-component round-trip and the
170+
tolerance-budget round-trip need a `+`-left-identity axiom on
171+
`Tolerance` (`zero + ε ≡ ε`) — not in the current record. The full
172+
retract proof and the Lipschitz generalisation (`L_g ≠ 1`) are
173+
deferred to subsequent rungs.
155174

156175
### Q4. Associativity — landed
157176

docs/echo-types/roadmap.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ Paths marked **[unblocked]** can proceed today. Paths marked
9292
(monotone in ε), and `echo-approx-compose` (additive composition
9393
under a non-expansive outer leg, realising the taxonomy §2
9494
conjecture). Wired into `All.agda` and `Smoke.agda`.
95+
- **[landed]** Composition rung first slice (Axis 2): the §Q3
96+
retract-shape. `EchoApprox.agda` now also ships
97+
`echo-strict→approx` (general strict ⇒ zero-tolerance, generalises
98+
`echo-approx-intro` from own-fibre to arbitrary `y` via the
99+
codomain equation), `echo-approx-comp-sound` (RHS-Σ → LHS via
100+
`echo-approx-compose`), `echo-approx-comp-retract-to`
101+
(canonical-split LHS → RHS-Σ section, picking `b := f x`,
102+
`ε₁ := zero`, `ε₂ := ε`), and `echo-approx-comp-retract-A` (the
103+
A-component round-trip `proj₁ ∘ sound ∘ retract-to ≡ proj₁`,
104+
proved by `refl`). The retraction direction on the A-witness holds
105+
definitionally as the design note (§5) predicts. The B-component
106+
and tolerance-budget round-trips are deferred to a subsequent
107+
rung — they need a `+`-left-identity axiom on `Tolerance`
108+
(`zero + ε ≡ ε`) which the current record does not supply.
109+
§7 obligations 7 (separated zero-collapse) and 8 (axis-1 shadow
110+
agreement) likewise deferred.
95111
- **[landed]** Per-decoration composition lemmas across the
96112
five-decoration family — **sweep complete** (2026-04-28):
97113
`EchoGraded.degrade-compose`, `EchoLinear.degradeMode-compose`,

proofs/agda/EchoApprox.agda

Lines changed: 127 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,48 @@
1212
--
1313
-- Headline lemmas:
1414
--
15-
-- * echo-approx-intro -- exact match is a zero-tolerance approximate echo
16-
-- * echo-approx-relax -- ε is monotone: ε₁ ≤ ε₂ ⇒ EchoR ε₁ ⊑ EchoR ε₂
17-
-- * echo-approx-compose -- non-expansive composition with additive error,
18-
-- realising the taxonomy §2 conjecture
15+
-- * echo-approx-intro -- exact own-fibre match is zero-tolerance
16+
-- * echo-strict→approx -- general strict ⇒ zero-tolerance (any y)
17+
-- * echo-approx-relax -- ε is monotone: ε₁ ≤ ε₂ ⇒ EchoR ε₁ ⊑ EchoR ε₂
18+
-- * echo-approx-compose -- non-expansive composition with additive
19+
-- error, realising the taxonomy §2 conjecture
20+
-- * echo-approx-comp-sound -- repackages compose into the retract RHS-Σ
21+
-- shape from `composition.md` §Q3 (§5 of the
22+
-- axis-2 design note)
23+
-- * echo-approx-comp-retract-to -- canonical-split LHS → RHS section:
24+
-- picks b := f x, ε₁ := zero, ε₂ := ε
25+
-- * echo-approx-comp-retract-A -- A-component round-trip (sound ∘ retract-to)
26+
-- preserves the A-witness up to `refl`,
27+
-- witnessing the retraction direction
28+
-- definitionally
1929
--
2030
-- The non-expansiveness side condition on the outer leg is the
2131
-- minimal hypothesis under which tolerances accumulate additively;
2232
-- without it the conjecture has no general proof (an amplifying
2333
-- second leg can blow ε₁ up arbitrarily on the way through).
34+
--
35+
-- Composition-track context (§5 of the axis-2 design note,
36+
-- `/tmp/echo-types-exploration/axis2-approximate.md`). The approximate
37+
-- analogue of `Echo-comp-iso` is a *retraction*, not a strict
38+
-- isomorphism: the RHS Σ-shape admits multiple splits of the ε
39+
-- budget and the chosen intermediate `b` is not pinned by the input.
40+
-- This module ships the first slice of that retract — soundness (#6),
41+
-- the canonical-split forward section, and an A-component round-trip
42+
-- witness. The B-component round-trip and the full tolerance round-trip
43+
-- need a `+`-left-identity axiom on `Tolerance` (`zero + ε ≡ ε`, not
44+
-- currently in the record); §7 obligations 7 (zero-collapse under
45+
-- separation) and 8 (axis-1 shadow agreement) are deferred to
46+
-- subsequent rungs.
2447

2548
module EchoApprox where
2649

2750
open import Level using (Level; _⊔_; suc)
2851
open import Function.Base using (_∘_; id)
29-
open import Data.Product.Base using (Σ; _,_; proj₁; proj₂)
52+
open import Data.Product.Base using (Σ; _,_; _×_; proj₁; proj₂)
3053
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; subst)
3154

55+
open import Echo using (Echo)
56+
3257
----------------------------------------------------------------------
3358
-- Tolerance carrier and pseudo-metric structure
3459
----------------------------------------------------------------------
@@ -89,6 +114,28 @@ module Approx
89114
echo-approx-intro f x =
90115
x , subst (_≤ zero) (sym (dist-self (f x))) ≤-refl
91116

117+
----------------------------------------------------------------------
118+
-- Headline 1ʹ: general strict ⇒ zero-tolerance approximate.
119+
--
120+
-- Realises §7 obligation 2 of the axis-2 design note: every strict
121+
-- echo `Echo f y` lifts to a zero-tolerance approximate echo
122+
-- `EchoR zero f y` (any y, not just own-fibre points). When `y ≡ f x`
123+
-- with `p ≡ refl` this collapses to `echo-approx-intro`; otherwise
124+
-- the codomain equation `p : f x ≡ y` is used to transport the
125+
-- self-distance bound from `(f x, f x)` to `(f x, y)`.
126+
--
127+
-- This generalises `echo-approx-intro` from own-fibre points
128+
-- `(f x)` to arbitrary `y` reached via a strict echo. The cost of
129+
-- the generalisation is one extra `subst` along `p`.
130+
----------------------------------------------------------------------
131+
132+
echo-strict→approx :
133+
{f : A B} {y : B} Echo f y EchoR zero f y
134+
echo-strict→approx {f = f} (x , p) =
135+
x , subst (λ z dist (f x) z ≤ zero)
136+
p
137+
(subst (_≤ zero) (sym (dist-self (f x))) ≤-refl)
138+
92139
----------------------------------------------------------------------
93140
-- Headline 2: tolerance is monotone in `ε`. A tighter approximation
94141
-- is also a looser one. The proof is one transitivity step.
@@ -139,3 +186,78 @@ module Approx
139186

140187
bound : dist (g (f x)) y ≤ (ε₁ + ε₂)
141188
bound = ≤-trans leg contract
189+
190+
----------------------------------------------------------------------
191+
-- Retraction-shaped composition (composition.md §Q3 / design-note §5).
192+
--
193+
-- The approximate analogue of `Echo-comp-iso` is *retract-shaped*:
194+
--
195+
-- LHS := EchoR ε (g ∘ f) y
196+
-- RHS := Σ B (λ b EchoR ε₁ f b × dist (g b) y ≤ ε₂)
197+
--
198+
-- with the budget split `ε = ε₁ + ε₂`. The RHS admits multiple
199+
-- splits of the budget and the chosen intermediate `b` is not
200+
-- pinned by the input, so a full iso fails by design. What does
201+
-- hold is a retraction: a forward section that picks a canonical
202+
-- representative on the RHS and a backward map (`echo-approx-comp-sound`,
203+
-- a thin repackaging of `echo-approx-compose`) that round-trips
204+
-- the A-witness definitionally.
205+
--
206+
-- This block lands the first slice: soundness (#6), the canonical-
207+
-- split forward section, and the A-component round-trip. The
208+
-- B-component and tolerance-budget round-trips need a `+`-left-
209+
-- identity axiom on `Tolerance` (`zero + ε ≡ ε`, not in the record).
210+
----------------------------------------------------------------------
211+
212+
-- §7 obligation 6: sound RHS-to-LHS direction.
213+
-- Unpacks the existential and calls `echo-approx-compose`.
214+
echo-approx-comp-sound :
215+
{ε₁ ε₂ : Tol}
216+
(f : A B) (g : B B)
217+
NonExpansive g
218+
{y : B}
219+
Σ B (λ b EchoR ε₁ f b × dist (g b) y ≤ ε₂)
220+
EchoR (ε₁ + ε₂) (g ∘ f) y
221+
echo-approx-comp-sound f g g-nonexp (b , ef , dgby≤ε₂) =
222+
echo-approx-compose f g g-nonexp {b = b} ef dgby≤ε₂
223+
224+
-- Canonical-split LHS-to-RHS section of the retract.
225+
--
226+
-- Given an `EchoR ε (g ∘ f) y` witness `(x , p : dist (g (f x)) y ≤ ε)`,
227+
-- produce the RHS Σ-shape at the canonical split `(ε₁, ε₂) := (zero, ε)`:
228+
--
229+
-- * intermediate `b := f x` (the canonical lift),
230+
-- * inner echo `EchoR zero f (f x)` via `echo-approx-intro`,
231+
-- * outer bound is just the original `p`.
232+
--
233+
-- This is the "section" half of the retract: a one-sided splitting
234+
-- of the §Q3 conjecture that always exists, with no extra hypothesis
235+
-- beyond what `EchoR ε (g ∘ f) y` already supplies. The "wrong"
236+
-- intermediates are not enumerable, which is precisely why the
237+
-- approximate analogue is a retract and not a full iso.
238+
echo-approx-comp-retract-to :
239+
: Tol} (f : A B) (g : B B) {y : B}
240+
EchoR ε (g ∘ f) y
241+
Σ B (λ b EchoR zero f b × dist (g b) y ≤ ε)
242+
echo-approx-comp-retract-to f g (x , dgfx≤ε) =
243+
f x , echo-approx-intro f x , dgfx≤ε
244+
245+
-- A-component round-trip. Starting from an `EchoR ε (g ∘ f) y`,
246+
-- pushing through the canonical-split section then through
247+
-- soundness lands back on the *same A-witness `x`* (the tolerance
248+
-- budget weakens from `ε` to `zero + ε`, which is why this is a
249+
-- retraction in the A-component rather than a full equality of
250+
-- echoes). The proof is `refl` — the A-component is preserved
251+
-- definitionally because every step of the round-trip keeps
252+
-- `proj₁` pinned to the original `x`.
253+
--
254+
-- This pins the "retract direction holds definitionally" promise
255+
-- of the design note: the witness-on-A round-trips on the nose,
256+
-- even though the tolerance and intermediate-B components do not.
257+
echo-approx-comp-retract-A :
258+
: Tol} (f : A B) (g : B B) (g-nonexp : NonExpansive g)
259+
{y : B} (e : EchoR ε (g ∘ f) y)
260+
proj₁ (echo-approx-comp-sound f g g-nonexp
261+
(echo-approx-comp-retract-to f g e))
262+
≡ proj₁ e
263+
echo-approx-comp-retract-A f g g-nonexp (x , _) = refl

0 commit comments

Comments
 (0)