- src/homemaker/ → src/homemaker_layout/; all imports updated - pyproject.toml: name = homemaker-layout, entry point updated - .beads/config.yaml: dolt sync.remote updated to homemaker-layout.git - Delete temporary debug/perl scripts from project root - README.md, DESIGN.md: package path references updated - GitHub repo renamed; git remote updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
79 lines
2.8 KiB
Python
79 lines
2.8 KiB
Python
"""Population sweep: warm-start refine every evolved candidate and tally results.
|
||
|
||
For each real .dom in the example dir, score it, run the solver as a geometry
|
||
optimiser (warm-start, no strip), and re-score. Reports how often bottom-up
|
||
sizing improves vs regresses total fitness, plus aggregate fail-count change.
|
||
|
||
This is a breadth check on the solver-as-optimiser role; raw fitness is still
|
||
confounded by the 0.5^n failure cliff and any topological defects, so the
|
||
fail-count and per-candidate detail matter as much as the win/loss tally.
|
||
"""
|
||
|
||
import shutil
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
||
|
||
from homemaker_layout import dom, oracle, programme, solver # noqa: E402
|
||
|
||
URB = Path("/home/bruno/src/urb")
|
||
EX = URB / "examples/programme-house"
|
||
|
||
|
||
def _is_candidate(p: Path) -> bool:
|
||
# real designs: 32-hex hashes or candidate-NNN; skip init and our scratch
|
||
name = p.stem
|
||
return name not in {"init", "original", "roundtrip", "solved", "refined"}
|
||
|
||
|
||
def main() -> None:
|
||
scratch = Path(__file__).resolve().parents[1] / "scratch"
|
||
scratch.mkdir(exist_ok=True)
|
||
shutil.copy(EX / "patterns.config", scratch / "patterns.config")
|
||
targets = programme.load_programme(str(EX / "patterns.config"))
|
||
|
||
doms = sorted(p for p in EX.glob("*.dom") if _is_candidate(p))
|
||
win = loss = tie = 0
|
||
fails_before = fails_after = 0
|
||
rows = []
|
||
for src in doms:
|
||
try:
|
||
shutil.copy(src, scratch / "orig.dom")
|
||
s0 = oracle.score(scratch / "orig.dom", URB)
|
||
root = dom.load(str(src))
|
||
# gentlest refiner: nudge cut POSITIONS for programme-room area only,
|
||
# keep evolved cut angles and leave circulation/shape untouched.
|
||
solver.solve_ratios(
|
||
root, targets, strip=False, perpendicular=False,
|
||
weight_width=0.0, weight_proportion=0.0, min_width_generic=0.0,
|
||
)
|
||
dom.dump(root, str(scratch / "ref.dom"))
|
||
s1 = oracle.score(scratch / "ref.dom", URB)
|
||
except Exception as e: # noqa: BLE001
|
||
rows.append(f" {src.name:40s} ERROR {e}")
|
||
continue
|
||
fails_before += s0.n_fails
|
||
fails_after += s1.n_fails
|
||
if s1.fitness > s0.fitness * 1.001:
|
||
win += 1
|
||
mark = "+"
|
||
elif s1.fitness < s0.fitness * 0.999:
|
||
loss += 1
|
||
mark = "-"
|
||
else:
|
||
tie += 1
|
||
mark = "="
|
||
rows.append(
|
||
f" {mark} {src.name:40s} {s0.fitness:.4g} -> {s1.fitness:.4g}"
|
||
f" fails {s0.n_fails}->{s1.n_fails}"
|
||
)
|
||
|
||
print("\n".join(rows))
|
||
n = win + loss + tie
|
||
print(f"\n{n} candidates: {win} improved, {loss} regressed, {tie} tied")
|
||
print(f"total fails: {fails_before} -> {fails_after}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|