Python rewrite of the Urb/Homemaker stack
Make the required programme room set a constructive invariant instead of something the topology search must stumble onto by random divide+retype. - operators.constructive_topology: bootstrap seeder that sizes each storey to its required rooms (partitioned by level; level-free rooms distributed), +1 core C and +1 O per storey, then assigns types. Stochastic for population diversity. Wired into driver bootstrap when the programme has required spaces. - operators.mutate_place_missing: repair op that inserts a missing required space by dividing a host leaf into [room | remainder]. Lex-safe host ranking (generic O first, never displace a required room); honours required level. Weight 2.0 in the mutation mix; noops cheaply once the set is complete. A/B on harbor-house (20k evals, seed 0, identical config): old random-bootstrap 133 fails (103 missing, 77%) new constructive 105 fails ( 12 missing, 11%) -21% total, missing-stack collapsed; seed head-start 163->139. §4.10 regression PASS: warmstart-2f4 still reaches a 1-fail population at 50k. Verdict (DESIGN.md §11.2): construction is necessary and reframes the bottleneck to quality-fail packing of a complete dense design (crinkliness/ size/access/edge) -> unblocks §11.3 staging, motivates §11.4 graded objective. Follow-up filed (homemaker-py-s44): adjacency-aware seeding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .beads | ||
| .claude | ||
| examples | ||
| experiments | ||
| src/homemaker_layout | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| DESIGN.md | ||
| pyproject.toml | ||
| README.md | ||
homemaker-layout
Programme-driven building-layout search over slicing trees. A clean-room Python successor to the Perl Urb project, intended to eventually be 100% Python.
Why a rewrite
Urb represents a building as a binary slicing tree where room sizes are derived top-down from division ratios. That makes room area an emergent property of every cut above it, which:
- gives the genome low locality (a cut near the root rescales every descendant),
- makes target room sizes nearly impossible to hit, so the gaussian size penalty dominates fitness, and
- defeats crossover (transplanted subtrees lose their proportions).
homemaker inverts this: leaves carry target dimensions from the programme and division ratios are solved bottom-up for a fixed topology. The evolutionary search then only explores topology + types + adjacency.
Phase plan
Solver experiment: port Urb's geometry, re-solve ratios from programme targets, score the result against the original via the Perl oracle.✓Native Python fitness (retire the Perl oracle).✓- Memetic search (current): canonical slicing genome + high-locality operators + Nelder-Mead inner loop.
Layout
src/homemaker_layout/dom.py— read/write Urb.domYAML into aNodetree.src/homemaker_layout/geometry.py— faithful port of Urb's top-down geometry.src/homemaker_layout/programme.py— parsepatterns.configspace requirements.src/homemaker_layout/solver.py— bottom-up ratio solve (scipy).src/homemaker_layout/fitness.py— native Python fitness evaluator.src/homemaker_layout/fitness_cmd.py—homemaker-fitnessCLI (drop-in forurb-fitness.pl).src/homemaker_layout/graph.py— leaf-adjacency graph for programme-driven checks.src/homemaker_layout/genome.py— topology genome: base-floor tree + per-storey deltas.src/homemaker_layout/operators.py— high-locality mutation and subtree crossover.src/homemaker_layout/innerloop.py— ratio optimisation inner loop (Nelder-Mead / CMA-ES).src/homemaker_layout/driver.py— memetic search outer loop.src/homemaker_layout/evolve.py—homemaker-evolveCLI entry point.src/homemaker_layout/oracle.py— legacy Perl shim, kept for cross-validation only.