Commit graph

5 commits

Author SHA1 Message Date
a0f56b7cdf Add homemaker-evolve CLI tool (homemaker-py-2wc)
python -m homemaker.evolve seed.dom [--budget N] [--pop N] [--workers N] ...
Installed as homemaker-evolve entry point via pyproject.toml.

Takes a single .dom file; infers programme dir from its parent. All parameters
available as --flags or HOMEMAKER_* env vars. Output defaults to
<seed_stem>_evolved.dom; use --output - for stdout. SIGINT/SIGTERM returns
best-so-far via new driver.SearchResult.interrupted flag.

Also adds dom.dumps() for string serialisation and refactors dom.dump() to use it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 07:48:13 +01:00
7ee51caf62 Parallelise outer search population evaluation (homemaker-py-5l6)
Add n_workers parameter to driver.search(). When n_workers > 1, a
ProcessPoolExecutor evaluates the bootstrap batch and main-loop children
in parallel, giving near-linear speedup with core count. The geometry
module-level cache is cleared in each worker after fork to prevent stale
id-keyed entries. Serial behaviour (n_workers=1, default) is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 06:55:58 +01:00
33d79be3fe Cold-start bootstrap: diverse initial population for blank-slate search
When the seed is an undivided bare plot (init.dom), auto-generate pop_size
random topologies before the memetic loop starts, each evaluated at
child_budget.  This crosses the zero-feasibility region that single-seed
chaining cannot escape — the programme-house cold start was stalling at 18
fails after 2000 evals vs urb-evolve's 6.

Auto-detection via seed_root.divided preserves the existing single-seed
path for warm starts from existing designs; all previous tests pass unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 23:29:12 +01:00
f160c6dc9e Use Urb's canonical UPPERCASE generic types (C/O); case-insensitive class checks
Bruno's correction: 'C' was never a 'covered' type — Is_Covered is a
geometric predicate. Urb generics are canonically uppercase (get_space_types
qw/C O S/; corpus 100% uppercase). The driver/operator type pool emitted
lowercase 'c'/'o', creating mixed-case designs that fragmented Dom->Ratios
class buckets and fired the latent ratio_type first-match nondeterminism
(which the search promptly reward-hacked). Operators now emit uppercase
generics only and class checks match case-insensitively (t[0].lower() in
'cos', cf. Is_Circulation/Is_Outside). The Urb-side class-sum patch remains
as defensive hardening, zero-impact on canonical designs (35/35 parity).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 19:01:53 +01:00
0beb005a23 Memetic search driver: steady-state GA over topology, warm-started inner loop
driver.py (homemaker-py-b39): tournament selection, operators.mutate (storey
ops down-weighted) + area-matched crossover, every child's geometry
delegated to the warm-started inner loop (Lamarckian write-back; children
use a single local CMA phase - the exploratory ladder phase exists for cold
projections children never face). Budget stated and accounted in oracle
evaluations; near-duplicate fitness guard against population collapse
(neutral mutations are common, per 8cs).

free_with_keys/ratio_map/warm_x0 promoted from the 8cs experiment into
innerloop.py as the Lamarckian inheritance API; alignment with
solver.free_branches asserted across the corpus.

tests/test_driver.py fakes the inner loop: budget accounting, monotone
improvement history, warm-start + sigma plumbing, valid .dom output.
31 tests pass. experiments/run_search.py is the end-to-end acceptance run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:22:26 +01:00