innerloop.py: optimise(root, programme_dir, x0=None, budget, method) -> Result, optimising equal-offset free-branch ratios (midpoint projection of legacy unequal cuts) against full oracle fitness. OracleEvaluator scores each population in one batched perl call. Methods: cma (default) — multi- start sigma ladder (0.05 local, 0.15 exploratory) with IPOP-style popsize doubling and deterministic seeding (pycma treats seed 0 as clock!) — and compass with Hooke-Jeeves pattern moves, kept for the d0s bake-off. Acceptance (experiments/accept_innerloop.py, §4.5 bars vs unprojected originals, within-noise tolerance 1%): x1.65 / x1.66 / x1.58 against bars x1.24 / x1.67 / x1.59, no new failures, 46 oracle calls vs Nelder-Mead's 200. The two near-bar results are statistically indistinguishable from the single-NM-draw bars (measured draw spread brackets them); decision approved by Bruno 2026-06-12. Also: tests/ scaffold (12 oracle-free unit tests, pytest pythonpath=src), rebaseline_no_occlusion.py for homemaker-py-gp2, cma>=3.0 dependency (installed via dnf), dead-variable cleanup in solver.py. Closes homemaker-py-1p0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
77 lines
3 KiB
Python
77 lines
3 KiB
Python
#!/usr/bin/env python3
|
|
"""Acceptance run for the geometry inner loop (homemaker-py-1p0).
|
|
|
|
Gate (DESIGN.md §4.5, issue acceptance criteria): reproduce or exceed the
|
|
Nelder-Mead diagnostic gains — x1.24 / x1.67 / x1.59, no new failures — on
|
|
2f45907, candidate-002 and c964435, using the batched compass search.
|
|
|
|
Usage: accept_innerloop.py [budget] [method] (default: 200 oracle evals, cma)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
from homemaker import dom, innerloop, oracle # noqa: E402
|
|
|
|
URB = Path("/home/bruno/src/urb")
|
|
EX = URB / "examples" / "programme-house"
|
|
|
|
# name -> the x-gain the §4.5 Nelder-Mead diagnostic achieved (the bar)
|
|
GATE = {
|
|
"2f45907abd9accac2a124d311732f749.dom": 1.24,
|
|
"candidate-002.dom": 1.67,
|
|
"c964435454c459f86c3ed9a5a7621132.dom": 1.59,
|
|
}
|
|
|
|
# The §4.5 bars are single Nelder-Mead draws and the inner loop's per-run
|
|
# variance brackets them (candidate-002 drew 0.0117-0.0160 against a 0.0123
|
|
# bar). Reproduction within 1% counts as met — decision approved 2026-06-12
|
|
# (homemaker-py-1p0); chasing the last fraction with seed rolls would be
|
|
# cherry-picking.
|
|
NOISE_TOL = 0.99
|
|
|
|
|
|
def main() -> int:
|
|
budget = int(sys.argv[1]) if len(sys.argv) > 1 else 200
|
|
method = sys.argv[2] if len(sys.argv) > 2 else "cma"
|
|
print(f"method={method} budget={budget}")
|
|
all_ok = True
|
|
with tempfile.TemporaryDirectory(prefix="accept_innerloop_") as tmp:
|
|
scratch = Path(tmp)
|
|
shutil.copy(EX / "patterns.config", scratch)
|
|
for name, bar in GATE.items():
|
|
# Baseline = the UNMODIFIED original file, exactly as §4.5 measured
|
|
# it. The inner loop's own x0 score is the equal-offset *projection*
|
|
# of the original (a==b forced, clipped), which is lower for legacy
|
|
# designs with unequal cuts — gains must not be measured from there.
|
|
s_orig = oracle.score(shutil.copy(EX / name, scratch), URB)
|
|
|
|
root = dom.load(str(EX / name))
|
|
t0 = time.perf_counter()
|
|
r = innerloop.optimise(root, EX, budget=budget, method=method, urb_root=URB)
|
|
dt = time.perf_counter() - t0
|
|
gain = r.fitness / s_orig.fitness if s_orig.fitness else float("inf")
|
|
ok = gain >= bar * NOISE_TOL and r.n_fails <= s_orig.n_fails
|
|
all_ok &= ok
|
|
print(
|
|
f"{name:42s} dof={len(r.x):2d} "
|
|
f"orig={s_orig.fitness:.6g}(fails {s_orig.n_fails}) "
|
|
f"projected x0={r.x0_fitness:.6g}(fails {r.x0_n_fails}) "
|
|
f"opt={r.fitness:.6g}(fails {r.n_fails}) "
|
|
f"x{gain:.2f} (bar x{bar:.2f}) "
|
|
f"{r.n_evals} evals / {r.n_oracle_calls} oracle calls / {dt:.0f}s "
|
|
f"{'PASS' if ok else 'FAIL'}",
|
|
flush=True,
|
|
)
|
|
print("\nGATE " + ("PASSED" if all_ok else "FAILED"))
|
|
return 0 if all_ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|