Defining the search space and decision variables for an AlphaEvolve use case requires proper formulation of the problem as code and providing a working baseline solution that the evolutionary heuristic can iterate on and improve.
This process includes:
Providing the target context: Establish the background, domain rules, and performance boundaries for the optimization use case.
Providing a clean baseline: Supply clear and well-structured code that correctly implements a baseline solution for the target problem.
Tagging degrees of freedom: Annotate the codebase with explicit
EVOLVE-BLOCKcomments to mark the specific decision variables, logic structures, or routines that the agent can mutate and explore to identify higher-performing solutions.
Structure of an initial program
An initial program is composed of two primary block types that determine the boundaries of the evolutionary search:
Immutable code blocks: Boilerplate code, helper functions, and dependencies that constrain the search space or execute tasks that don't impact solution performance (such as standard preprocessing steps or data handling routines).
Mutable code blocks (
EVOLVE-BLOCK): The targeted regions containing specific decision variables, logic structures, or analytical expressions that the agent is allowed to explore and mutate.import numpy as np # Code to constrain the search space (Immutable) def def_preprocessing(): """Feature engineering and preprocessing.""" pass # EVOLVE-BLOCK-START # Mutable block: Provides degrees of freedom for AlphaEvolve to optimize def model_tuning(): """Model tuning function: parametrized to take features.""" pass # EVOLVE-BLOCK-END # Boilerplate code that does not impact solution performance (Immutable) def batch_predictions(): """Inference function: batch predictions to test performance.""" pass
Best practices for constraining the search space
How you arrange your immutable imports and place your evolve blocks explicitly shows AlphaEvolve's operational boundaries.
Manage library imports and dependencies
AlphaEvolve cannot inherently determine which external libraries are valid for your production environment.
To allow open exploration: If any machine learning or mathematical package is
acceptable to maximize your metric, place the imports inside the mutable
EVOLVE-BLOCK. This gives AlphaEvolve freedom to substitute alternative
frameworks (such as replacing sklearn with TensorFlow or xgboost).
To enforce strict tool chains: If all models must come from a specific package, declare that package as an immutable import outside the evolve block. If AlphaEvolve requires additional internal modules from that package during search, it can still import them locally within its mutable space without violating the global constraint.
Avoid an over-constrained search space
Formulate as many hard constraints as possible as immutable code blocks in the initial program or within the additional user-provided text context. This minimizes the chances of the agent exploring structurally infeasible solutions.
However, don't narrow the search space to the point where an evolutionary approach becomes redundant. For example, forcing AlphaEvolve to only use single-parameter linear regressions reduces the problem to a narrow configuration space that could be parsed by standard grid-search utilities. Instead, use soft constraints as negative penalties in your evaluation criteria to guide exploration without choking it.
Strategic block placement for targeted objectives
Varying the scope of your EVOLVE-BLOCK shifts the entire optimization
objective of your pipeline:
Optimizing out-of-sample (OOS) calibration: If your goal is broad algorithmic discovery, wrap the block around the entire model tuning and initialization routine.
Optimizing structural fit: If you want to preserve a linear framework but discover complex analytical expressions or custom mathematical transformations, isolate your mutable block strictly around the feature transformation logic, keeping the downstream model architecture fixed and immutable.
Preserving modular hierarchy (HDL/Verilog examples): When optimizing structural
code block configurations, keep the EVOLVE-BLOCK-START and EVOLVE-BLOCK-END
tags strictly inside the module definition boundaries. This prevents the search
heuristic from making structurally invalid moves, such as trying to replace a
single cleanly contained module with multiple unmapped, floating sub-modules.