Skip to content

Commit a8ef31d

Browse files
feat: bounded-search-is-decidable — EchoSearch decidability bridge (#251)
## What Closes the `bounded-search-is-decidable` gap that `EchoSearch.agda` flagged under "where next" — the concrete bridge from `EchoSearch` to `EchoDecidable` (axis 8(3)). ## How `EchoS enum f y n` is *exactly* the bounded existential `Σ k. (k < n) × (f (enum k) ≡ y)`, so under decidable equality on `B` it's decidable by structural recursion on the budget `n`: ```agda bounded-search-is-decidable : (_≟_ : (x y : B) → Dec (x ≡ y)) (enum : SearchStrategy A) (f : A → B) (y : B) (n : ℕ) → Dec (EchoS enum f y n) ``` - `n = 0` → `no` (via the existing `echo-search-bound-zero`). - `n = suc n` → test the new index `n` with `_≟_`; on a hit, `yes`; otherwise recurse on `n`. The negative case refutes every index below `suc n` via `<-cmp` trichotomy: indices `< n` by the recursive `¬below`, the index `n` itself by `¬eq`, and none strictly between `n` and `suc n`. A small design touch: the refutation matches the `<` proof as `s≤s k≤n` to get `k ≤ n` directly, avoiding any `≤-pred` name dependency. ## Discipline - `--safe --without-K`, **zero postulates**, structural recursion (no `TERMINATING`). - Pinned in `Smoke.agda`; the module's "where next" note marked LANDED. `EchoSearch` was already classified (only a lemma added, no new module), so `kernel-guard.sh` PASS. - **Verified on latest `main`:** `EchoSearch.agda`, `Smoke.agda`, `All.agda` all `agda --safe --without-K` exit 0 (captured locally). ## Context This is one of only three small gaps a full proof-surface survey found still open (the rest of the historical roadmap has landed). The other two are **not** clean closes and I'm leaving them for your steer (see the session note): EchoApprox's Lipschitz bound needs an interface-design decision (a multiplicative-tolerance algebra), and EchoSearch's sequential composition needs a from-scratch `ℕ × ℕ ↔ ℕ` Cantor pairing (stdlib has none) that the module itself defers until a consumer needs it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We --- _Generated by [Claude Code](https://claude.ai/code/session_018CaSgNjNURC7ocsyjYh9We)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7721c91 commit a8ef31d

2 files changed

Lines changed: 45 additions & 6 deletions

File tree

proofs/agda/EchoSearch.agda

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,23 @@
6767
-- ∧ trace.last ≡ x ∧ f x ≡ y`. The current `EchoS` projects from
6868
-- that by collapsing the trace to its terminal index.
6969
--
70-
-- * A *bounded-search-is-decidable* lemma in the presence of
71-
-- decidable equality on `B`: search up to `n` either yields an
70+
-- * (LANDED) A *bounded-search-is-decidable* lemma in the presence
71+
-- of decidable equality on `B`: search up to `n` either yields an
7272
-- `EchoS enum f y n` or proves `¬ EchoS enum f y n`. This is the
73-
-- concrete bridge to `EchoDecidable`, kept as a separate slice
74-
-- because it needs a `_≟_` on `B` and a finite-walk recursion.
73+
-- concrete bridge to `EchoDecidable`; it needs a `_≟_` on `B` and a
74+
-- finite-walk recursion on the budget. See `bounded-search-is-decidable`
75+
-- at the bottom of this module.
7576

7677
module EchoSearch where
7778

7879
open import Function.Base using (_∘_; id)
7980
open import Data.Nat.Base using (ℕ; zero; suc; _≤_; _<_; z≤n; s≤s)
80-
open import Data.Nat.Properties using (≤-<-trans; <-≤-trans)
81+
open import Data.Nat.Properties
82+
using (≤-<-trans; <-≤-trans; <-cmp; <-trans; ≤-trans; ≤-refl; <-irrefl)
8183
open import Data.Empty using (⊥; ⊥-elim)
8284
open import Data.Product.Base using (Σ; _,_; _×_; proj₁; proj₂)
83-
open import Relation.Nullary using (¬_)
85+
open import Relation.Nullary using (¬_; Dec; yes; no)
86+
open import Relation.Binary.Definitions using (Tri; tri<; tri≈; tri>)
8487
open import Relation.Binary.PropositionalEquality
8588
using (_≡_; refl; sym; trans; cong)
8689

@@ -156,3 +159,38 @@ echo-search-postcompose :
156159
EchoS enum f y n EchoS enum (g ∘ f) (g y) n
157160
echo-search-postcompose enum f g (k , k<n , eq) =
158161
k , k<n , cong g eq
162+
163+
----------------------------------------------------------------------
164+
-- Decidability bridge
165+
----------------------------------------------------------------------
166+
167+
-- Bounded search is decidable under decidable equality on the codomain.
168+
-- Because `EchoS enum f y n` is exactly the bounded existential
169+
-- `Σ k. (k < n) × (f (enum k) ≡ y)`, searching up to the budget `n`
170+
-- either produces a bound-`n` search echo or refutes one. This is the
171+
-- concrete bridge from EchoSearch to `EchoDecidable` (axis 8(3)): no
172+
-- machine model is required, only the step budget and a `_≟_` on `B`.
173+
-- Structural recursion on `n`; the `suc` step tests the new index `n`
174+
-- and otherwise recurses, using trichotomy to refute every index below
175+
-- `suc n` in the negative case.
176+
bounded-search-is-decidable :
177+
{a b} {A : Set a} {B : Set b}
178+
(_≟_ : (x y : B) Dec (x ≡ y))
179+
(enum : SearchStrategy A) (f : A B) (y : B) (n : ℕ)
180+
Dec (EchoS enum f y n)
181+
bounded-search-is-decidable _≟_ enum f y zero =
182+
no (echo-search-bound-zero enum f y)
183+
bounded-search-is-decidable _≟_ enum f y (suc n) with f (enum n) ≟ y
184+
... | yes eq = yes (n , ≤-refl , eq)
185+
... | no ¬eq with bounded-search-is-decidable _≟_ enum f y n
186+
... | yes (k , k<n , eqk) = yes (k , <-trans k<n ≤-refl , eqk)
187+
... | no ¬below = no λ { (k , k<1+n , eqk) contra k k<1+n eqk }
188+
where
189+
-- No index below `suc n` can witness `y`: indices below `n` are
190+
-- refuted by `¬below`, the index `n` itself by `¬eq`, and there is
191+
-- no index strictly between `n` and `suc n`.
192+
contra : k k < suc n f (enum k) ≡ y
193+
contra k (s≤s k≤n) eqk with <-cmp k n
194+
... | tri< k<n _ _ = ¬below (k , k<n , eqk)
195+
... | tri≈ _ k≡n _ = ¬eq (trans (sym (cong (λ j f (enum j)) k≡n)) eqk)
196+
... | tri> _ _ n<k = <-irrefl refl (≤-trans n<k k≤n)

proofs/agda/Smoke.agda

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ open import EchoSearch using
482482
; echo-search-forget
483483
; echo-search-bound-zero
484484
; echo-search-postcompose
485+
; bounded-search-is-decidable
485486
)
486487

487488
-- Per-lemma pins for the parameterised EchoSearch via

0 commit comments

Comments
 (0)