|
| 1 | +// SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | += Echidna design-search findings — Phase 1.3 + unbudgeted wf-<ᵇʳᶠ_ |
| 3 | +:date: 2026-04-28 |
| 4 | +:toc: |
| 5 | + |
| 6 | +This document captures the output of running Echidna's new |
| 7 | +`design search` strategy against two open targets in the Buchholz / |
| 8 | +Brouwer programme. It is a *recommendation handoff*, not a proof — |
| 9 | +the Agda translation is the next session's work. |
| 10 | + |
| 11 | +== Background |
| 12 | + |
| 13 | +Two open milestones in `docs/buchholz-plan.adoc`: |
| 14 | + |
| 15 | +* **Phase 1.3** — monotonicity lemmas for `Ordinal.Brouwer.Arithmetic` |
| 16 | + (`osuc-mono-≤`, `⊕-mono-≤-right`). Blocked because the current |
| 17 | + `data _≤_` axiomatisation makes `osuc-mono-≤` non-trivial in the |
| 18 | + `≤-lim` case. |
| 19 | +* **Unbudgeted `wf-<ᵇʳᶠ_`** — `Ordinal.Buchholz.RecursiveSurfaceBudget` |
| 20 | + carries a `BudgetedBT = ℕ × BT` budget alongside each derivation; |
| 21 | + the goal is `WellFounded _<ᵇʳᶠ_` directly without the budget. |
| 22 | + |
| 23 | +These were attacked using a new Echidna capability stack (built in |
| 24 | +this session): |
| 25 | + |
| 26 | +. `echidna corpus ingest` — structural index of every named |
| 27 | + declaration in `proofs/agda/Ordinal/**.agda`, plus dependency DAG |
| 28 | + and axiom-hazard flags. |
| 29 | +. `echidna design search <problem>` — simulated annealing over |
| 30 | + *design space* (axiomatisation shapes / rank shapes), not tactic |
| 31 | + space. Energy is symbolic, computed from the corpus + heuristic |
| 32 | + predicates. |
| 33 | +. `echidna design swarm <problem>` — N parallel SA agents with |
| 34 | + cross-pollination through a coordinator. Used to validate that the |
| 35 | + single-chain SA result was robust. |
| 36 | + |
| 37 | +== Phase 1.3 — recommended `_≤_` redesign |
| 38 | + |
| 39 | +=== What Echidna found |
| 40 | + |
| 41 | +`echidna design search brouwer-leq --top 12 --iterations 2000` |
| 42 | +agrees across all top candidates: switch `_≤_` to a *recursive* |
| 43 | +definition. |
| 44 | + |
| 45 | +Energy `[0, 0, 1, 0]` — zero monotonicity blockers, zero K-elim |
| 46 | +hazards, single seed constructor, recursive style. |
| 47 | + |
| 48 | +Data-style alternatives (with `LimBelow` added) score `[2, 0, 4, 1]` |
| 49 | +or worse; my hand-trace of `osuc-mono-≤` under `data + LimBelow` |
| 50 | +confirms the SA's verdict — in the `≤-lim n q` case, neither |
| 51 | +`≤-suc → ≤-lim k` nor `LimBelow` recovers a path from |
| 52 | +`q : x ≤ f n` to `osuc x ≤ osuc (olim f)`. The recursive form makes |
| 53 | +`osuc-mono-≤ p = p` because the equation |
| 54 | +`osuc α ≤ osuc β = α ≤ β` reduces the goal definitionally. |
| 55 | + |
| 56 | +=== Recommended axiomatisation |
| 57 | + |
| 58 | +Sketched (proof bodies omitted — see "Proof obligations" below): |
| 59 | + |
| 60 | +[source,agda] |
| 61 | +---- |
| 62 | +_≤_ : Ord → Ord → Set |
| 63 | +oz ≤ _ = ⊤ |
| 64 | +osuc α ≤ oz = ⊥ |
| 65 | +osuc α ≤ osuc β = α ≤ β |
| 66 | +osuc α ≤ olim f = Σ ℕ λ n → osuc α ≤ f n |
| 67 | +olim f ≤ β = ∀ n → f n ≤ β |
| 68 | +---- |
| 69 | + |
| 70 | +=== Proof obligations under this axiomatisation |
| 71 | + |
| 72 | +. `≤-refl : ∀ {α} → α ≤ α` — structural induction on `α`. |
| 73 | +. `≤-step : ∀ {α β} → α ≤ β → α ≤ osuc β` — non-trivial; case-splits on |
| 74 | + both arguments. |
| 75 | +. `≤-trans : ∀ {α β γ} → α ≤ β → β ≤ γ → α ≤ γ` — induct on `γ` first |
| 76 | + (most reductions branch on the right argument). |
| 77 | +. `f-in-lim : ∀ f n → f n ≤ olim f` — pattern on `f n`; for the |
| 78 | + successor case, supply `Σ` witness `(n , ≤-refl)`. |
| 79 | +. `osuc-mono-≤ p = p` — *identity* by definitional reduction. **The |
| 80 | + whole point of the redesign.** |
| 81 | +. `⊕-mono-≤-right : ∀ {α} {x y} → x ≤ y → α ⊕ x ≤ α ⊕ y` — structural |
| 82 | + on `α` (since `_⊕_` is left-recursive). |
| 83 | +. `wf-< : WellFounded _<_` — needs re-proof under the recursive |
| 84 | + definition. The structural-induction proof in the current |
| 85 | + `Brouwer.agda` uses `Acc _<_` constructed from |
| 86 | + `pred-of-osuc`/`pred-of-olim`; adapt those to the recursive `_≤_`. |
| 87 | + |
| 88 | +=== Risks I noticed during hand-tracing |
| 89 | + |
| 90 | +* The `≤-step` lemma — currently a single line `≤-step = ≤-suc` — is |
| 91 | + non-trivial under recursive `_≤_`. Specifically the case |
| 92 | + `α = osuc α', β = olim f` requires `α' ≤ osuc (olim f)`, which |
| 93 | + case-splits to `Σ n. osuc α' ≤ f n` — needs careful witness picking. |
| 94 | +* `pred-of-olim` — currently uses pattern match on `≤-lim n q`; under |
| 95 | + recursive `_≤_`, the relation isn't pattern-matchable, so this |
| 96 | + becomes a structural fact about `Σ`-elimination. |
| 97 | + |
| 98 | +These don't block the redesign — they're well-trodden constructive |
| 99 | +ordinal proofs in literature — but they represent real proof work, |
| 100 | +not a one-line refactor. |
| 101 | + |
| 102 | +== Unbudgeted `wf-<ᵇʳᶠ_` — recommended rank shape |
| 103 | + |
| 104 | +=== What Echidna found |
| 105 | + |
| 106 | +`echidna design search buchholz-rank --top 5` and |
| 107 | +`echidna design swarm buchholz-rank --agents 4` both converge on the |
| 108 | +same minimal-blocker shape with energy `[3, 0, 1]`: |
| 109 | + |
| 110 | +[source,agda] |
| 111 | +---- |
| 112 | +rank : BT → Ord |
| 113 | +rank bzero = oz |
| 114 | +rank (bOmega ν) = ω-rank ν |
| 115 | +rank (bplus x y) = rank x ⊕ rank y |
| 116 | +rank (bpsi ν α) = psi-rank ν (rank α) |
| 117 | +---- |
| 118 | + |
| 119 | +The three blockers are the three `_<ᵇʳᶠ_` constructor cases of |
| 120 | +`rank-mono`. Two of them (`<ᵇʳᶠ-ψα`, `<ᵇʳᶠ-+2`) reduce to the same |
| 121 | +new lemma `⊕-mono-<-right` (a Phase-1.3 deliverable). The third |
| 122 | +(`<ᵇʳᶠ-core`) reduces to Phase-2.2's `rank-mono-<ᵇ` for the base |
| 123 | +Buchholz order. |
| 124 | + |
| 125 | +=== Closing the goal |
| 126 | + |
| 127 | +Once Phase-1.3 monotonicity and Phase-2.2 rank-mono land: |
| 128 | + |
| 129 | +[source,agda] |
| 130 | +---- |
| 131 | +rank-mono : ∀ {x y} → x <ᵇʳᶠ y → rank x < rank y |
| 132 | +rank-mono (<ᵇʳᶠ-core p) = rank-mono-<ᵇ p |
| 133 | +rank-mono (<ᵇʳᶠ-ψα p) = -- ψ-strict-mono via osuc-strict-mono |
| 134 | + -- on (ω-rank ν ⊕ rank α) |
| 135 | + -- ⟹ ⊕-mono-<-right |
| 136 | +rank-mono (<ᵇʳᶠ-+2 p) = ⊕-mono-<-right p |
| 137 | +
|
| 138 | +wf-<ᵇʳᶠ : WellFounded _<ᵇʳᶠ_ |
| 139 | +wf-<ᵇʳᶠ = Subrelation.wellFounded rank-mono |
| 140 | + (InverseImage.wellFounded rank wf-<) |
| 141 | +---- |
| 142 | + |
| 143 | +(`Subrelation`, `InverseImage` from `Induction.WellFounded`. `wf-<` |
| 144 | +is the existing Brouwer well-foundedness — itself unchanged by the |
| 145 | +Phase-1.3 redesign so long as the redesign keeps it well-founded.) |
| 146 | + |
| 147 | +== Proof-obligation graph |
| 148 | + |
| 149 | +The two milestones share dependencies. In the order I'd attack them: |
| 150 | + |
| 151 | +. **`osuc-mono-<` (strict version) and `⊕-mono-<-right`** in |
| 152 | + `Ordinal.Brouwer` + `Ordinal.Brouwer.Arithmetic`. Phase-1.3 |
| 153 | + deliverables. Recursive `_≤_` makes `osuc-mono-<` trivial; `⊕-mono-<- |
| 154 | + right` is structural on `α`. |
| 155 | +. **Re-prove `wf-<` under the recursive `_≤_`.** Structural on `Ord` |
| 156 | + with adapted `pred-of-osuc` / `pred-of-olim`. |
| 157 | +. **`rank-mono-<ᵇ : x <ᵇ y → rank x < rank y`** in a new |
| 158 | + `Ordinal.Buchholz.Rank` module. Phase-2.2 deliverable. Constructor- |
| 159 | + by-constructor induction over the 13-shape admitted core of `_<ᵇ_`. |
| 160 | +. **Drop `RecursiveSurfaceBudget`** in favour of direct |
| 161 | + `wf-<ᵇʳᶠ : WellFounded _<ᵇʳᶠ_` via the `Subrelation` chain. The |
| 162 | + budget infrastructure becomes vestigial. |
| 163 | + |
| 164 | +== SA energy assumptions (for sanity-checking) |
| 165 | + |
| 166 | +The SA's energy is symbolic, not from running Agda. Two predicates |
| 167 | +might be wrong; spot-check before fully trusting the recommendation: |
| 168 | + |
| 169 | +* **`mono_osuc_ok` (in `learning/design_search.rs`)**: claims that |
| 170 | + `_≤_` is `Recursive` *or* contains `≤-cong-suc` ⟹ `osuc-mono-≤` |
| 171 | + is trivial. I verified by hand for the `Recursive` case. The |
| 172 | + `≤-cong-suc` claim is also straightforward (apply the constructor). |
| 173 | + No data-style + `LimBelow` path is recognised — confirmed by hand |
| 174 | + trace. |
| 175 | +* **`blockers` (in `learning/buchholz_rank.rs`)**: claims that |
| 176 | + `<ᵇʳᶠ-+2` always needs `⊕-mono-<-right`, regardless of whether |
| 177 | + `bplus` rank is `LeftSum` or `OsucSum`. The `OsucSum` case |
| 178 | + technically needs `osuc-strict-mono ∘ ⊕-mono-<-right` — the outer |
| 179 | + `osuc` is still strict-monotonic, so the dependency reduces to |
| 180 | + `⊕-mono-<-right` either way. Confirmed. |
| 181 | + |
| 182 | +== References |
| 183 | + |
| 184 | +* `data/synonyms/agda.toml` (in `echidna`) — the vocabulary table the |
| 185 | + follow-up agent should consult for tactic-name alternatives. |
| 186 | +* `data/corpus/agda.json` (in `echidna`, gitignored — regenerate with |
| 187 | + `echidna corpus ingest --root proofs/agda` from this repo) — the |
| 188 | + full dependency DAG over the project. |
| 189 | +* `src/rust/learning/design_search.rs` — Brouwer-leq problem. |
| 190 | +* `src/rust/learning/buchholz_rank.rs` — rank-function problem. |
| 191 | +* `src/rust/agent/swarm.rs` — parallel-search dispatcher. |
| 192 | + |
| 193 | +== Repro |
| 194 | + |
| 195 | +[source,bash] |
| 196 | +---- |
| 197 | +# In the echidna repo: |
| 198 | +cargo run --bin echidna -- corpus ingest \ |
| 199 | + --root /path/to/echo-types/proofs/agda |
| 200 | +
|
| 201 | +cargo run --bin echidna -- design search brouwer-leq --top 12 |
| 202 | +
|
| 203 | +cargo run --bin echidna -- design search buchholz-rank --top 5 |
| 204 | +
|
| 205 | +cargo run --bin echidna -- design swarm brouwer-leq --agents 6 |
| 206 | +
|
| 207 | +cargo run --bin echidna -- design swarm buchholz-rank --agents 4 |
| 208 | +---- |
0 commit comments