From e4f56c30d880de6617e2ddfdfc2774e2b40df927 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Jun 2026 23:20:17 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20echo-search-product=20=E2=80=94=20bound?= =?UTF-8?q?ed=20product=20(sequential)=20search=20composition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the last "where next" gap in EchoSearch. The original sketch (`EchoS … f b n₁ → EchoS … g y n₂ → EchoS … (g∘f) y (n₁*n₂)`) is ill-typed — the second search's witness is not tied to the first's output — so the well-typed form is the PRODUCT of two independent searches over `A₁ × A₂` with budget `n₁ * n₂`: productEnum n₂ enum₁ enum₂ k = (enum₁ (k / n₂) , enum₂ (k % n₂)) echo-search-product : EchoS enum₁ f₁ y₁ n₁ → EchoS enum₂ f₂ y₂ n₂ → EchoS (productEnum n₂ enum₁ enum₂) (productMap f₁ f₂) (y₁,y₂) (n₁*n₂) The witness pairs the two step indices row-major as `k₂ + k₁*n₂`, which stays `< n₁*n₂` exactly when `k₁ Claude-Session: https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We --- proofs/agda/EchoSearch.agda | 78 +++++++++++++++++++++++++++++++++---- proofs/agda/Smoke.agda | 3 ++ 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/proofs/agda/EchoSearch.agda b/proofs/agda/EchoSearch.agda index 892d880..dbfca39 100644 --- a/proofs/agda/EchoSearch.agda +++ b/proofs/agda/EchoSearch.agda @@ -57,10 +57,15 @@ -- -- Where next: -- --- * Sequential composition `EchoS enum f b n₁ → EchoS enum' g y n₂ --- → EchoS (paired-enum) (g ∘ f) y (n₁ * n₂)` under a pairing --- enumerator on `ℕ × ℕ`. Honest but needs a bijection --- `ℕ × ℕ ↔ ℕ`; defer to the slice that wants it. +-- * (LANDED) Product / sequential composition. The original sketch +-- `EchoS enum f b n₁ → EchoS enum' g y n₂ → EchoS … (g ∘ f) y (n₁ * n₂)` +-- is ill-typed (the second search's witness is not tied to the first's +-- output `b`); the well-typed form is the PRODUCT of two independent +-- searches, `echo-search-product` below, over `A₁ × A₂` with budget +-- `n₁ * n₂`. The `n₁ * n₂` budget provably needs a budget-dependent +-- row-major pairing (a global `ℕ × ℕ ↔ ℕ` cannot keep +-- `pair (n₁-1) (n₂-1) < n₁ * n₂`), so it divides by `n₂` and requires +-- `NonZero n₂`. See `productEnum` / `echo-search-product` at the bottom. -- -- * A real abstract-machine refinement: configurations + a step -- relation, with `EchoS` recovered as `∃ trace . trace.length < n @@ -77,15 +82,18 @@ module EchoSearch where open import Function.Base using (_∘_; id) -open import Data.Nat.Base using (ℕ; zero; suc; _≤_; _<_; z≤n; s≤s) +open import Data.Nat.Base using (ℕ; zero; suc; _≤_; _<_; _+_; _*_; z≤n; s≤s; NonZero) open import Data.Nat.Properties - using (≤-<-trans; <-≤-trans; <-cmp; <-trans; ≤-trans; ≤-refl; <-irrefl) + using (≤-<-trans; <-≤-trans; <-cmp; <-trans; ≤-trans; ≤-refl; <-irrefl; +-monoˡ-<; *-monoˡ-≤) +open import Data.Nat.DivMod + using (_/_; _%_; [m+kn]%n≡m%n; m) open import Relation.Binary.PropositionalEquality - using (_≡_; refl; sym; trans; cong) + using (_≡_; refl; sym; trans; cong; cong₂) open import Echo using (Echo) @@ -194,3 +202,59 @@ bounded-search-is-decidable _≟_ enum f y (suc n) with f (enum n) ≟ y ... | tri< k _ _ n