Skip to content

Commit 136b23e

Browse files
orebasclaude
andcommitted
Fix :generic_start MP fan-out cascade: completeness target is a SOLUTION count
codex report (17h cstr_0_1em8 cell, pre-campaign code; adjudicated REAL, untouched by the campaign): when a fan-out fell short and fresh-solved, the loop-persistent completeness target was bumped to the fresh solve's only_finite=false endpoint count — the homotopy PATH bound (~Bezout/BKK incl. at-infinity; cstr MP: 393) — while every subsequent fan-out tracks only the N generic anchor solutions (n_accounted <= N = 3 by construction). `3 < 393` was permanently true, so EVERY later MP point needlessly fresh-solved: 135 combos x fresh polyhedral solve (~15.4h of the 17h cell). Performance bug only — the fresh solves still found the solutions. Fix: bump with the fresh solve's FINITE solution count. Complete-anchor case (fresh finite == N): target stays N, fan-outs judged fairly, cascade dead. Genuine-undercoverage case (fresh finite > N): target rises (correct — fan-outs of N really are incomplete) and a @warn tripwire fires. The fan-out decision itself still counts at-infinity endpoints (1d0569b's good half is preserved); only the bump quantity changes. Verification: full suite 755/755 (easy models never execute the bump). cstr efficacy probe: the `genuinely short (N < path-bound)` discard pattern is structurally impossible now; this probe's config sits fully in the at-infinity blind spot (finite-kept=0 every point) so its fresh-solves are genuine and identical pre/post — the original cell's collapse is implied by its logged discarded-finite pattern + the arithmetic. BONUS: the tripwire fired on its first run (fresh 7 finite vs anchor N=3) — first observed anchor-undercoverage specimen; the monodromy_solve+trace-test anchor-repair design (postcampaign review doc, verified against installed HC.jl, O(N)-tracks cost) is now non-speculative. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5ab54fb commit 136b23e

3 files changed

Lines changed: 59 additions & 5 deletions

File tree

docs/2026-06-10_postcampaign_review.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,40 @@ surface (261 unique exports) plus two god files remain the big structural debts.
171171

172172
---
173173

174+
## Designed follow-up — :generic_start anchor repair (Oren's go-back question, 2026-06-10)
175+
176+
The MP fan-out perf fix (target bumps with the fresh FINITE count, never the path
177+
count) leaves a designed-but-unbuilt follow-up. If the new `@warn` tripwire
178+
("fresh solve found more finite solutions than the generic-start anchor count")
179+
EVER fires in a real run, the anchor undercovered. **STATUS: first firing OBSERVED
180+
2026-06-10 on the cstr efficacy probe itself** (point 4 of an MP combo: fresh found
181+
7 finite vs anchor N=3; all complex/projected — dedup-verify step 1 below matters
182+
before trusting the 7). The follow-up is no longer speculative. — and since #isolated-finite at
183+
any parameter ≤ the generic count, that means the p0 anchor solve LOST roots, which
184+
also silently invalidates earlier points' "complete" fan-out verdicts. Plan (build
185+
on first observed firing, not speculatively):
186+
1. Dedup/verify the fresh M-solution set (clustered singular endpoints can inflate it).
187+
2. Repair the ANCHOR: γ-track the M solutions p_i → p0 (complex), merge into
188+
`generic_start_solutions` → corrected N for all future points.
189+
3. Re-fan-out the repaired anchor to points 1..i-1 and dedup-merge into their kept
190+
sets (tracking-priced, not fresh-solve-priced; all results are assembled before
191+
return so go-back is local to solve_with_hc_parameterized).
192+
4. The deeper systematic fix is anchor-side completeness, and it is CHEAP (verified
193+
against installed HC.jl, 2026-06-10): after the one-time anchor solve at p0, run
194+
`monodromy_solve(...; trace_test = true)` seeded with the anchor solutions —
195+
tops up missing roots AND certifies completeness via the trace test (LRS18);
196+
standalone checker `verify_solution_completeness`. Cost is O(N_true) path-tracks
197+
(~seconds at N=3..18), vs the mixed-cells + BKK-paths fresh solve (CPU-hours;
198+
cstr MP: 393 paths for 3 solutions; receptor: 6402 for 18). Caveats: numerical
199+
certificate (pass ⇒ high confidence; fail ⇒ investigate — false negatives
200+
possible per HC's own docs); multi-component families make the trace fail
201+
honestly (seed more, e.g. from one fresh solve's finite set). FREE cross-check
202+
for SP systems: auto-M (quotient-basis dim) is already computed — anchor_N ≠ M
203+
is an exact undercoverage detector. Column-scaled anchor solve additionally
204+
reduces blind-spot path loss at p0 (receptor lesson). Detection via fan-out
205+
shortfall alone is opportunistic and misses the all-fan-outs-track-cleanly
206+
undercoverage case — the certificate closes that hole.
207+
174208
## Suggested execution order
175209

176210
1. **Now:** P0#4 test-target deps (one line, our regression) → commit.

docs/2026-06-10_session_handoff.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,18 @@ left an unloadable tree once). `Pkg.test` ≠ the local include gate — verify
4949

5050
## OPEN FINDING — :generic_start MP fanout perf bug (codex report 2026-06-10)
5151

52-
Reported by codex on a 17h cstr_0_1em8 cell; adjudicated this session as **REAL,
53-
pre-existing, NOT touched by the campaign, still present** — a PERFORMANCE bug, not
54-
correctness. Detail in the answer below; not yet fixed (was a query, not a fix
55-
request). Lives at `src/core/homotopy_continuation.jl:943-964`.
52+
Reported by codex on a 17h cstr_0_1em8 cell; adjudicated as **REAL, pre-existing,
53+
NOT touched by the campaign** — a PERFORMANCE bug, not correctness.
54+
**FIXED 2026-06-10** (commit following this doc's): the completeness target now
55+
bumps with the fresh solve's FINITE solution count, never the only_finite=false
56+
path/endpoint count; plus an undercoverage `@warn` tripwire — which FIRED on its
57+
first probe run (fresh 7 finite vs anchor N=3 on a cstr MP combo), making the
58+
anchor-repair follow-up (monodromy_solve + trace test, design in the postcampaign
59+
review doc) non-speculative. Efficacy probe verified mechanics (no count-branch
60+
fresh-solves possible; this reduced config sits fully in the at-infinity blind spot
61+
so its fresh-solves are genuine); the original cell's 15h collapse is implied by
62+
codex's logged `3 < 393 genuinely short` discarded-finite pattern + arithmetic,
63+
not re-measured. Was at `src/core/homotopy_continuation.jl:943-964`.
5664

5765
Root cause: in the `:generic_start` (default) MP path, after point 1's fanout comes
5866
up short and triggers a fresh `_hc_solve`, line 964 bumps the loop-persistent

src/core/homotopy_continuation.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,19 @@ function solve_with_hc_parameterized(poly_system, solve_vars, data_vars, param_v
961961
end
962962
result = _hc_solve(hc_system; target_parameters = current_params, show_progress = show_progress)
963963
all_solutions = HomotopyContinuation.solutions(result; only_nonsingular = false)
964-
initial_solution_count = max(initial_solution_count, length(HomotopyContinuation.solutions(result; only_nonsingular = false, only_finite = false)))
964+
# Completeness target must stay a SOLUTION count (≈ the generic count N), NOT the fresh
965+
# solve's only_finite=false endpoint count. The fan-out only ever tracks N generic
966+
# solutions, so n_accounted ≤ N; bumping the target to the fresh solve's path/endpoint
967+
# count (the homotopy path bound ~Bezout/BKK incl. at-infinity — e.g. 393) made
968+
# `n_accounted < target` permanently true ⇒ EVERY subsequent point needlessly fresh-solved
969+
# (the 15h-cstr blowup; report 2026-06-10). Use the FRESH FINITE count: it raises the
970+
# target only on genuine generic-anchor undercoverage (fresh finds > N real solutions),
971+
# the one case where fan-outs of N really are incomplete and should keep fresh-solving.
972+
fresh_finite = length(all_solutions)
973+
if fresh_finite > initial_solution_count
974+
@warn "[HC-PARAM] Fresh solve found more finite solutions ($fresh_finite) than the generic-start anchor count ($initial_solution_count): generic anchor undercovered; subsequent fan-outs will fresh-solve." maxlog = 3
975+
end
976+
initial_solution_count = max(initial_solution_count, fresh_finite)
965977
elseif debug
966978
real_count = length(HomotopyContinuation.solutions(result, only_real = true, real_tol = real_tol))
967979
println("[HC-PARAM] Point $i: fan-out complete ($n_accounted accounted, $(length(all_solutions)) finite, $real_count real)")

0 commit comments

Comments
 (0)