galapagos
DocsHubLeaderboardPlaygroundNews
galapagos

six blocks · any task ·
better solutions emerge.

Platform

  • Hub
  • Leaderboard
  • Playground

Resources

  • Docs
  • API reference
  • Card spec

Community

  • GitHub
  • Contribute

Updates

  • News
  • Releases

© 2026 Galapagos. Licensed under Apache-2.0.

Build your own scaffold.

Hub/Scaffolds/OpenEvolve/OpenEvolve

OpenEvolve/openevolve

OpenEvolve

Island-model MAP-Elites evolutionary search with diff mutation (the open AlphaEvolve).

Test-time searchApache-2.0
Scaffold cardFiles and versions
openevolve/proposer.py
62 lines · 3.6 KBpythonDownload
"""OpenEvolve Proposer component — the SEARCH/REPLACE diff operator.

Faithful port of OpenEvolve's diff mechanics (``utils/code_utils.py`` ``apply_diff`` / ``extract_diffs``):
diffs are applied by **whole-line slice equality** via the shared
:func:`~galapagos.components.proposer.apply_diff_wholeline`. A response with at least one parseable
SEARCH/REPLACE block is evaluated even if it does not match the parent (OpenEvolve admits the unchanged
child); a response with NO block is a no-op (OpenEvolve's "No valid diffs found" → discard). No
full-rewrite fence fallback in diff mode.
"""
from __future__ import annotations

import logging

from ...components.proposer import (DiffProposer, Env, apply_diff_wholeline,
                                    extract_diffs, parse_full_rewrite, summarize_diff)
from ...models.base import Prompt
from ...records import Genome

log = logging.getLogger(__name__)


class OpenEvolveProposer(DiffProposer):
    """OpenEvolve's diff operator: one LLM call → SEARCH/REPLACE applied by whole-line matching.

    Also records the immediate parent's metrics and a diff summary onto the child
    (``metadata["parent_metrics"]`` / ``metadata["changes"]``), mirroring OpenEvolve's
    ``Program.metadata = {"changes": ..., "parent_metrics": parent.metrics}`` (iteration.py), which the
    PromptBuilder renders in the "Program Evolution History" section.
    """

    def propose(self, prompt: Prompt, env: Env) -> Genome:
        parent = env.selection.parent
        gen = env.model.generate(prompt)
        if env.state is not None:
            env.state.record_cost(gen.cost_usd, gen.prompt_tokens, gen.completion_tokens)
        if self.diff_based:                          # whole-line SEARCH/REPLACE (no fence fallback)
            new_code, _ = apply_diff_wholeline(parent.content, gen.text)
            # OpenEvolve discards ONLY when NO diff block parses; a present-but-non-matching block still
            # yields a child (the unchanged code) that is evaluated + admitted. So "changed" = "at least
            # one block parsed", not "the text differs" (process_parallel.py:224-228 / 263).
            changed = bool(extract_diffs(gen.text))
            changes = summarize_diff(gen.text)
        else:                                        # full-rewrite mode: the whole response is the program
            new_code, changed = parse_full_rewrite(parent.content, gen.text)
            changes = "Full rewrite"
        child = parent.child(new_code, generation=parent.metadata.get("generation", 0) + 1)
        # a regular child is never itself a migrant copy — OpenEvolve gives children a fresh metadata
        # dict; migrant copies are minted only in Population.migrate. Dropping the inherited flag lets
        # descendants of a migrant migrate again (else a whole lineage is frozen out of migration).
        child.metadata.pop("migrant", None)
        # stamp the SAMPLING island on the child (OpenEvolve add(target_island=...)) — the policy
        # publishes it via the signal rather than mutating the shared parent genome.
        isl = (env.state.signals.get("openevolve", {}) if env.state is not None else {}).get("island")
        if isinstance(isl, int):
            child.metadata["island"] = isl
        child.metadata["changed"] = changed
        child.metadata["parent_metrics"] = dict(parent.scores)
        child.metadata["changes"] = changes
        child.artifacts["response"] = gen.text
        log.debug("propose (openevolve %s) — parent=%s child=%s changed=%s",
                  "diff" if self.diff_based else "rewrite", parent.id, child.id, changed)
        return child