AdaEvolve
Hierarchical adaptive search: G-signal exploration intensity, UCB island allocation, and LLM meta-guidance on stagnation.
"""AdaEvolve Proposer component — the SEARCH/REPLACE diff (with full-rewrite fallback) operator.
One file per component (see scaffold.py). AdaEvolve mutates with ``diff_based_generation`` +
``allow_full_rewrites``: one LLM call → SEARCH/REPLACE diffs applied to the parent (upstream
``extract_diffs``/``apply_diff``), falling back to a full rewrite (``parse_full_rewrite``) —
exactly what the shared :class:`~galapagos.components.proposer.DiffProposer` implements. Cost is
recorded via ``env.state.record_cost`` and the child sets ``metadata["changed"]`` (no-op
detection), both inherited.
The one AdaEvolve-specific addition: the child is stamped with the CURRENT sampling island
(``state.signals["adaevolve"]["island"]``, published by the policy's ``select``), mirroring the
upstream ``add()`` routing to ``current_island``. ``Genome.child`` copies the parent's metadata
wholesale, so without the stamp a paradigm-overridden parent (the global best, possibly archived
on another island) would misroute its children; stamping here also avoids mutating archived
parents' metadata in ``select``. Migrants and spawn seeds keep their explicitly stamped island
(they never pass through ``propose``).
"""
from __future__ import annotations
from ...components.proposer import DiffProposer, Env
from ...records import Genome
class AdaEvolveProposer(DiffProposer):
"""SEARCH/REPLACE diff with full-rewrite fallback + mandatory no-op detection. Children are
routed to the CURRENT island via ``metadata["island"]`` (see module docstring).
Upstream ``_execute_generation`` applies a parsed diff by WHOLE-LINE matching
(``extract_diffs``/``apply_diff``) and falls back to ``parse_full_rewrite`` when no block parses
— so whole-line + fallback are both on (vs the base substring ``apply_edit``)."""
diff_wholeline = True
diff_wholeline_fallback = True
def propose(self, prompt, env: Env) -> Genome:
child = super().propose(prompt, env)
sig = (env.state.signals.get("adaevolve", {}) if env.state is not None else {}) or {}
island = sig.get("island")
if isinstance(island, int):
child.metadata["island"] = island
return child