> ## Documentation Index
> Fetch the complete documentation index at: https://proto.evodesign.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Optimizers

> Search algorithms that find optimal biological sequences through iterative generate-score-select cycles

<div class="card-strip-wrapper">
  <div class="card-strip" data-duration="36">
    <a href="/docs/language/optimizers/mcmc" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/mcmc/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/beam-search" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/beam-search/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/cycling" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/cycling/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/rejection-sampling" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/rejection-sampling/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/genetic-algorithm" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/genetic-algorithm/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/gradient" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/gradient/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/mcmc" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/mcmc/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/beam-search" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/beam-search/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/cycling" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/cycling/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/rejection-sampling" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/rejection-sampling/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/genetic-algorithm" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/genetic-algorithm/carousel.png" alt="" loading="lazy" />
    </a>

    <a href="/docs/language/optimizers/gradient" class="card-strip-item">
      <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/gradient/carousel.png" alt="" loading="lazy" />
    </a>
  </div>
</div>

# Optimizers

Optimizers are the search algorithms of Proto. They coordinate [generators](/docs/language/concepts/generators) and [constraints](/docs/language/concepts/constraints) in an iterative loop: generate proposal sequences, score them, select the best, and repeat. Different optimizers implement different search strategies, from rejection sampling to MCMC with simulated annealing.

## The Optimization Loop

Every optimizer follows the same fundamental loop:

<div className="block dark:hidden">
  <svg viewBox="0 0 720 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The optimizer generate, filter, score, select loop" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers1L" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arroptimizers1L" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#768b8e" /></marker></defs><rect x="12" y="12" width="696" height="576" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="696" height="576" rx="16" fill="url(#gridoptimizers1L)" /><path d="M238,104 L238,128" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M238,192 L238,216" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M238,280 L238,304" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M238,368 L238,392" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M238,456 L238,480" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M366,512 L446,512" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><path d="M110,512 C 60,490 60,180 110,160" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><rect x="110" y="40" width="256" height="64" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="120" y="52" width="4" height="40" rx="2" fill="#768b8e" /><text x="238" y="78" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Initialize Pools</text><rect x="110" y="128" width="256" height="64" rx="10" fill="#046e7a" /><rect x="120" y="140" width="4" height="40" rx="2" fill="#bfe2e7" /><text x="238" y="158" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Generate</text><text x="238" y="176" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#bfe2e7" textAnchor="middle">(generators propose proposals)</text><rect x="110" y="216" width="256" height="64" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="120" y="228" width="4" height="40" rx="2" fill="#C77D2E" /><text x="238" y="246" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Filter</text><text x="238" y="264" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">(hard constraints reject bad ones)</text><rect x="110" y="304" width="256" height="64" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="120" y="316" width="4" height="40" rx="2" fill="#768b8e" /><text x="238" y="334" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Score</text><text x="238" y="352" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">(soft constraints compute energy)</text><rect x="110" y="392" width="256" height="64" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="120" y="404" width="4" height="40" rx="2" fill="#768b8e" /><text x="238" y="422" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Select</text><text x="238" y="440" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">(keep best by energy)</text><rect x="110" y="480" width="256" height="64" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="120" y="492" width="4" height="40" rx="2" fill="#768b8e" /><text x="238" y="518" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Done?</text><rect x="446" y="480" width="200" height="64" rx="10" fill="#2f8f6b" /><rect x="456" y="492" width="4" height="40" rx="2" fill="#d4ebe0" /><text x="546" y="518" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Return Results</text><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="238" cy="104" r="3.2" /><circle cx="238" cy="128" r="3.2" /><circle cx="238" cy="192" r="3.2" /><circle cx="238" cy="216" r="3.2" /><circle cx="238" cy="280" r="3.2" /><circle cx="238" cy="304" r="3.2" /><circle cx="238" cy="368" r="3.2" /><circle cx="238" cy="392" r="3.2" /><circle cx="238" cy="456" r="3.2" /><circle cx="238" cy="480" r="3.2" /><circle cx="366" cy="512" r="3.2" /><circle cx="446" cy="512" r="3.2" /><circle cx="110" cy="512" r="3.2" /><circle cx="110" cy="160" r="3.2" /></g><rect x="387" y="501.25" width="38" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="406" y="516" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Yes</text><rect x="56" y="325.25" width="32" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="72" y="340" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">No</text><path d="M366,336 L410,336" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers1L)" /><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="366" cy="336" r="3.2" /></g><rect x="414" y="212" width="282" height="160" rx="14" fill="#eef5f4" stroke="#ced9d7" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="432" y="233" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#768b8e" textAnchor="start" letterSpacing="1.6">ENERGY AGGREGATION</text><text x="434" y="270" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#344649" textAnchor="start">filter fails  →  E = ∞</text><text x="434" y="304" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#344649" textAnchor="start">E = Σ wᵢ·sᵢ   (add)</text><text x="434" y="338" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#344649" textAnchor="start">E = Π wᵢ·sᵢ   (multiply)</text></svg>
</div>

<div className="hidden dark:block">
  <svg viewBox="0 0 720 600" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="The optimizer generate, filter, score, select loop" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers1D" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arroptimizers1D" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#7e9498" /></marker></defs><rect x="12" y="12" width="696" height="576" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="696" height="576" rx="16" fill="url(#gridoptimizers1D)" /><path d="M238,104 L238,128" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M238,192 L238,216" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M238,280 L238,304" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M238,368 L238,392" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M238,456 L238,480" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M366,512 L446,512" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><path d="M110,512 C 60,490 60,180 110,160" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><rect x="110" y="40" width="256" height="64" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="120" y="52" width="4" height="40" rx="2" fill="#7e9498" /><text x="238" y="78" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Initialize Pools</text><rect x="110" y="128" width="256" height="64" rx="10" fill="#0a7e8c" /><rect x="120" y="140" width="4" height="40" rx="2" fill="#c0e6ea" /><text x="238" y="158" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Generate</text><text x="238" y="176" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#c0e6ea" textAnchor="middle">(generators propose proposals)</text><rect x="110" y="216" width="256" height="64" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="120" y="228" width="4" height="40" rx="2" fill="#C77D2E" /><text x="238" y="246" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Filter</text><text x="238" y="264" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">(hard constraints reject bad ones)</text><rect x="110" y="304" width="256" height="64" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="120" y="316" width="4" height="40" rx="2" fill="#7e9498" /><text x="238" y="334" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Score</text><text x="238" y="352" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">(soft constraints compute energy)</text><rect x="110" y="392" width="256" height="64" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="120" y="404" width="4" height="40" rx="2" fill="#7e9498" /><text x="238" y="422" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Select</text><text x="238" y="440" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">(keep best by energy)</text><rect x="110" y="480" width="256" height="64" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="120" y="492" width="4" height="40" rx="2" fill="#7e9498" /><text x="238" y="518" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Done?</text><rect x="446" y="480" width="200" height="64" rx="10" fill="#2f8f6b" /><rect x="456" y="492" width="4" height="40" rx="2" fill="#cfeadd" /><text x="546" y="518" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Return Results</text><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="238" cy="104" r="3.2" /><circle cx="238" cy="128" r="3.2" /><circle cx="238" cy="192" r="3.2" /><circle cx="238" cy="216" r="3.2" /><circle cx="238" cy="280" r="3.2" /><circle cx="238" cy="304" r="3.2" /><circle cx="238" cy="368" r="3.2" /><circle cx="238" cy="392" r="3.2" /><circle cx="238" cy="456" r="3.2" /><circle cx="238" cy="480" r="3.2" /><circle cx="366" cy="512" r="3.2" /><circle cx="446" cy="512" r="3.2" /><circle cx="110" cy="512" r="3.2" /><circle cx="110" cy="160" r="3.2" /></g><rect x="387" y="501.25" width="38" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="406" y="516" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Yes</text><rect x="56" y="325.25" width="32" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="72" y="340" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">No</text><path d="M366,336 L410,336" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers1D)" /><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="366" cy="336" r="3.2" /></g><rect x="414" y="212" width="282" height="160" rx="14" fill="#15211f" stroke="#33474a" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="432" y="233" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#9eb4b2" textAnchor="start" letterSpacing="1.6">ENERGY AGGREGATION</text><text x="434" y="270" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#d6e1df" textAnchor="start">filter fails  →  E = ∞</text><text x="434" y="304" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#d6e1df" textAnchor="start">E = Σ wᵢ·sᵢ   (add)</text><text x="434" y="338" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="13" fontWeight="400" fill="#d6e1df" textAnchor="start">E = Π wᵢ·sᵢ   (multiply)</text></svg>
</div>

**Energy scoring** is where constraints come together. The optimizer calls `score_energy()` which:

1. Evaluates all **filter constraints** first (hard pass/fail)
2. Rejects proposals that fail any filter (`energy = inf`)
3. Evaluates **scoring constraints** only on surviving proposals
4. Combines scores: `energy = Sigma(weight_i x score_i)`

## Optimizer Comparison

|                     | **MCMC**                              | **Rejection Sampling**         | **BeamSearch**                    | **Cycling**                   | **Gradient**                                |
| ------------------- | ------------------------------------- | ------------------------------ | --------------------------------- | ----------------------------- | ------------------------------------------- |
| **Strategy**        | Random walk with acceptance criterion | Generate many, keep best       | Beam search over token generation | Iterative conditioning cycles | Continuous relaxation with gradient descent |
| **Exploration**     | High (temperature-controlled)         | Broad (many samples)           | Moderate (beam width)             | Custom (user-defined)         | Local (gradient-driven)                     |
| **Exploitation**    | Good (annealing)                      | Low (no refinement)            | Good (beam pruning)               | Depends on pipeline           | Strong (descent)                            |
| **Best for**        | General optimization, refinement      | Initial screening, exploration | Long DNA generation               | Structure-conditioned design  | Differentiable constraints                  |
| **Inherits state?** | Yes                                   | Yes                            | No (starts from prompt)           | Yes                           | Yes                                         |
| **Multi-segment?**  | Yes                                   | Yes                            | No (single segment)               | No (single segment)           | No (single segment)                         |

## Available Optimizers

<AccordionGroup>
  <Accordion title="MCMCOptimizer: Metropolis-Hastings Search">
    The general-purpose optimizer. Uses Markov Chain Monte Carlo with Metropolis-Hastings acceptance to explore sequence space. Maintains one or more parallel trajectories, proposing mutations and accepting or rejecting them based on energy improvement and temperature.

    **How it works:**

    1. For each result sequence, generate `proposals_per_result` proposals
    2. Score all proposals, pick the best one per result
    3. Accept or reject based on Metropolis-Hastings criterion:
       * Always accept if energy improves
       * Sometimes accept worse moves (controlled by temperature)
    4. Temperature anneals from `max_temperature` to `min_temperature` over the run

    **When to use:** General-purpose optimization, protein refinement, any iterative design task. A reasonable default when the choice is unclear.

    ```python python icon="python" theme={null}
    from proto_language.optimizer import MCMCOptimizer, MCMCOptimizerConfig

    config = MCMCOptimizerConfig(
        num_results=5,           # Maintain 5 parallel trajectories
        num_steps=1000,          # Run for 1000 steps
        proposals_per_result=10,  # Generate 10 proposals per result per step
        max_temperature=2.0,     # Start exploratory
        min_temperature=0.001,   # End greedy
    )

    optimizer = MCMCOptimizer(
        constructs=[construct],
        generators=[generator],
        constraints=constraints,
        config=config,
    )
    ```

    <ParamField path="num_results" type="int | None" default="None">
      Number of parallel trajectories to maintain. `num_results=1` is standard single-chain MCMC. Higher values explore more of sequence space in parallel.
    </ParamField>

    <ParamField path="num_steps" type="int" required>
      Total number of MCMC steps. More steps allow better convergence but increase runtime.
    </ParamField>

    <ParamField path="proposals_per_result" type="int" default="1">
      Number of proposals to generate per result per step. Total proposals per step = `num_results x proposals_per_result`.
    </ParamField>

    <ParamField path="max_temperature" type="float" default="1.0">
      Starting temperature. Higher = more exploration (accepts worse moves more often).
    </ParamField>

    <ParamField path="min_temperature" type="float" default="0.001">
      Final temperature. Lower = more greedy (only accepts improvements).
    </ParamField>
  </Accordion>

  <Accordion title="RejectionSamplingOptimizer: Generate Many, Keep Best">
    The simplest optimizer. Generates a large number of proposals, scores them all, and keeps the top `num_results` by lowest energy. No iterative refinement; just sampling with selection.

    **How it works:**

    1. Generate proposals in batches of `proposal_batch_size`
    2. Score them all
    3. Track the top `num_results` proposals seen so far (maintained in sorted order)
    4. Repeat until `num_samples` reached (or `energy_threshold` met)

    **When to use:** Initial exploration, quick screening, or as the first stage in a multi-stage [Program](/docs/language/concepts/programs) pipeline.

    ```python python icon="python" theme={null}
    from proto_language.optimizer import RejectionSamplingOptimizer, RejectionSamplingOptimizerConfig

    # Standard mode: generate exactly num_samples
    config = RejectionSamplingOptimizerConfig(
        num_samples=1000,          # Generate 1000 proposals total
        num_results=10,            # Keep the top 10
        proposal_batch_size=50,    # Evaluate 50 per batch
    )

    # Early stopping mode: stop when threshold is met
    config = RejectionSamplingOptimizerConfig(
        num_samples=10000,
        num_results=10,
        energy_threshold=0.1,  # Stop early if top results all below 0.1
    )

    optimizer = RejectionSamplingOptimizer(
        constructs=[construct],
        generators=[generator],
        constraints=constraints,
        config=config,
    )
    ```

    <ParamField path="num_samples" type="int" required>
      Maximum number of proposals to generate.
    </ParamField>

    <ParamField path="num_results" type="int | None" default="None">
      Number of top sequences to keep (by lowest energy). Overrides the program-level `num_results` when set.
    </ParamField>

    <ParamField path="proposal_batch_size" type="int | None" default="None">
      Number of proposal sequences to generate and evaluate per batch, capped at `num_samples`.
    </ParamField>

    <ParamField path="energy_threshold" type="float" default="None">
      If set, enables early stopping: halts when all top-k proposals have energy below this threshold.
    </ParamField>
  </Accordion>

  <Accordion title="BeamSearchOptimizer: Autoregressive Beam Search">
    Optimizer for generating long sequences with autoregressive generators such as Evo2. Splits a long segment into chunks of `beam_length` tokens and performs beam search at each boundary, pruning low-quality beams as the sequence grows.

    **How it works:**

    1. Start from `prompt` sequence
    2. Generate `beam_length` tokens with `proposals_per_result` variations per beam
    3. Score all beams with constraints
    4. Keep top `num_results` beams
    5. Repeat until segment length is reached

    **When to use:** Generating a single long DNA sequence (e.g., 2000+ bp) with quality constraints applied during generation rather than after.

    ```python python icon="python" theme={null}
    from proto_language.optimizer import (
        BeamSearchOptimizer, BeamSearchOptimizerConfig
    )

    config = BeamSearchOptimizerConfig(
        prompt="ATGCCTGAA",          # Starting sequence
        beam_length=500,             # Generate 500bp per beam step
        num_results=5,               # Keep top 5 beams
        proposals_per_result=10,    # Generate 10 variations per beam
        score_by="mean",             # Average scores across all beams
        use_kv_caching=True,         # Cache for speed
    )

    optimizer = BeamSearchOptimizer(
        target_segment=construct.segments[0],  # The single segment to generate over
        constructs=[construct],
        generators=[evo2_generator], # Must be autoregressive
        constraints=constraints,
        config=config,
    )
    ```

    <Warning>
      BeamSearch requires a single-segment construct and an autoregressive generator. It ignores previous optimizer results in a Program; it always starts fresh from its configured `prompt`.
    </Warning>

    <ParamField path="prompt" type="str" required>
      Initial sequence to begin generation from. All beams extend from this prompt.
    </ParamField>

    <ParamField path="beam_length" type="int" required>
      Number of tokens to generate per beam step.
    </ParamField>

    <ParamField path="num_results" type="int">
      Number of top beams to maintain at each step (K in beam search). Optional; defaults to the number of results requested by the program.
    </ParamField>

    <ParamField path="proposals_per_result" type="int" required>
      Number of proposal extensions per beam. Total proposals per step = `num_results x proposals_per_result`.
    </ParamField>

    <ParamField path="score_by" type="str" default="mean">
      Aggregation method: `"mean"` (average across beams, rewards consistency) or `"last"` (most recent beam only).
    </ParamField>

    <ParamField path="use_kv_caching" type="bool" default="False">
      Enable KV cache reuse for faster autoregressive generation across beam steps.
    </ParamField>
  </Accordion>

  <Accordion title="CyclingOptimizer: Iterative Conditioning Cycles">
    A generalized optimizer that alternates between a user-defined conditioning function and a generator. The conditioning function can modify generator config between iterations; for example, predicting a 3D structure from the current sequence, then using that structure to condition inverse folding for the next iteration.

    **How it works:**

    1. Run the conditioning function on current sequences
    2. The conditioning function updates generator config (e.g., sets new PDB structures)
    3. Generator produces new proposals conditioned on updated config
    4. Optionally evaluate constraints and roll back rejected proposals
    5. Repeat for `num_steps`

    **When to use:** Structure prediction + inverse folding cycles ("protein hallucination"), or any iterative conditioning workflow.

    **Built-in pipeline:** The `protein-hunter` pipeline automates the common pattern of structure prediction followed by inverse folding:

    ```python python icon="python" theme={null}
    from proto_language.optimizer import (
        CyclingOptimizer, CyclingOptimizerConfig
    )

    config = CyclingOptimizerConfig(
        num_results=10,
        num_steps=50,
        pipeline="protein-hunter",
        protein_hunter={"structure_tool": "boltz2"},
    )

    optimizer = CyclingOptimizer(
        target_segment=construct.segments[0],  # The single segment to design
        constructs=[construct],
        generators=[proteinmpnn_gen],
        constraints=constraints,
        config=config,
    )
    ```

    <ParamField path="num_results" type="int | None" default="None">
      Number of proposal trajectories to maintain across cycles.
    </ParamField>

    <ParamField path="num_steps" type="int" required>
      Number of conditioning-generation cycles to run.
    </ParamField>

    <ParamField path="pipeline" type="str" default="None">
      Named pipeline (e.g., `"protein-hunter"`) for common conditioning patterns.
    </ParamField>

    <ParamField path="conditioning_fn" type="Callable" default="None">
      Custom conditioning function for advanced use cases. Passed as a constructor argument to `CyclingOptimizer` (not a `CyclingOptimizerConfig` field), and mutually exclusive with `pipeline`.
    </ParamField>
  </Accordion>
</AccordionGroup>

<Note>
  The **Gradient** optimizer (continuous relaxation with differentiable constraints, paired with `PositionWeightGenerator`) is summarized in the comparison table above; see its full reference at [Gradient optimizer](/docs/language/optimizers/gradient).
</Note>

## Optimizer Decision Tree

<div className="block dark:hidden">
  <svg viewBox="0 0 1296 640" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Decision tree for choosing an optimizer" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers2L" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arroptimizers2L" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#768b8e" /></marker></defs><rect x="12" y="12" width="1272" height="616" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="1272" height="616" rx="16" fill="url(#gridoptimizers2L)" /><path d="M168,237 L208,237" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M328,237 C348,237 348,120 368,120" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M328,237 C348,237 348,354 368,354" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M472,120 L512,120" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M472,354 L512,354" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M662,120 C717,120 717,66 772,66" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M662,120 C717,120 717,174 772,174" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M662,354 C717,354 717,282 772,282" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M662,354 C717,354 717,426 772,426" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M912,174 C962,174 962,138 1012,138" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M912,174 C962,174 962,210 1012,210" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M912,426 C962,426 962,354 1012,354" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M912,426 L1012,426" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><path d="M912,426 C962,426 962,498 1012,498" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><rect x="40" y="208" width="128" height="58" rx="10" fill="#046e7a" /><rect x="50" y="220" width="4" height="34" rx="2" fill="#bfe2e7" /><text x="104" y="235" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">What kind of</text><text x="104" y="253" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#bfe2e7" textAnchor="middle">optimization?</text><rect x="208" y="208" width="120" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="218" y="220" width="4" height="34" rx="2" fill="#768b8e" /><text x="268" y="243" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Sequence type?</text><rect x="368" y="91" width="104" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="378" y="103" width="4" height="34" rx="2" fill="#768b8e" /><text x="420" y="126" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">DNA / RNA</text><rect x="368" y="325" width="104" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="378" y="337" width="4" height="34" rx="2" fill="#768b8e" /><text x="420" y="360" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Protein</text><rect x="512" y="91" width="150" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="522" y="103" width="4" height="34" rx="2" fill="#768b8e" /><text x="587" y="118" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Long sequence?</text><text x="587" y="136" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">(>500bp)</text><rect x="512" y="325" width="150" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="522" y="337" width="4" height="34" rx="2" fill="#768b8e" /><text x="587" y="352" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Have / want to</text><text x="587" y="370" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">design structure?</text><rect x="772" y="37" width="140" height="58" rx="10" fill="#2f8f6b" /><rect x="782" y="49" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="842" y="64" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">BeamSearch</text><text x="842" y="82" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#d4ebe0" textAnchor="middle">+ Evo2</text><rect x="772" y="145" width="140" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="782" y="157" width="4" height="34" rx="2" fill="#768b8e" /><text x="842" y="180" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Goal?</text><rect x="772" y="253" width="140" height="58" rx="10" fill="#2f8f6b" /><rect x="782" y="265" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="842" y="280" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Cycling</text><text x="842" y="298" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#d4ebe0" textAnchor="middle">(protein-hunter)</text><rect x="772" y="397" width="140" height="58" rx="10" fill="#f4f9f9" stroke="#dbe6e4" strokeWidth="1.2" /><rect x="782" y="409" width="4" height="34" rx="2" fill="#768b8e" /><text x="842" y="432" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#1d2c2f" textAnchor="middle">Goal?</text><rect x="1012" y="109" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="121" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="144" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling</text><rect x="1012" y="181" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="193" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="216" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">MCMC</text><rect x="1012" y="325" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="337" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="360" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling</text><rect x="1012" y="397" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="409" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="432" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">MCMC</text><rect x="1012" y="469" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="481" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="496" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling then MCMC</text><text x="1132" y="514" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#d4ebe0" textAnchor="middle">(use Program)</text><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="168" cy="237" r="3.2" /><circle cx="208" cy="237" r="3.2" /><circle cx="328" cy="237" r="3.2" /><circle cx="368" cy="120" r="3.2" /><circle cx="368" cy="354" r="3.2" /><circle cx="472" cy="120" r="3.2" /><circle cx="512" cy="120" r="3.2" /><circle cx="472" cy="354" r="3.2" /><circle cx="512" cy="354" r="3.2" /><circle cx="662" cy="120" r="3.2" /><circle cx="772" cy="66" r="3.2" /><circle cx="772" cy="174" r="3.2" /><circle cx="662" cy="354" r="3.2" /><circle cx="772" cy="282" r="3.2" /><circle cx="772" cy="426" r="3.2" /><circle cx="912" cy="174" r="3.2" /><circle cx="1012" cy="138" r="3.2" /><circle cx="1012" cy="210" r="3.2" /><circle cx="912" cy="426" r="3.2" /><circle cx="1012" cy="354" r="3.2" /><circle cx="1012" cy="426" r="3.2" /><circle cx="1012" cy="498" r="3.2" /></g><rect x="698" y="77.25" width="38" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="717" y="92" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Yes</text><rect x="701" y="136.25" width="32" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="717" y="151" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">No</text><rect x="668" y="297.5" width="98" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="717" y="312.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Iterative</text><text x="717" y="325.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">hallucination</text><rect x="701" y="379.25" width="32" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="717" y="394" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">No</text><rect x="934" y="136.5" width="56" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="151.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Quick</text><text x="962" y="164.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">screen</text><rect x="928" y="183.25" width="68" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="198" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Optimize</text><rect x="934" y="370.5" width="56" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="385.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Quick</text><text x="962" y="398.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">screen</text><rect x="916" y="408.5" width="92" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="423.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Detailed</text><text x="962" y="436.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">optimization</text><rect x="919" y="451.25" width="86" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="466" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Multi-stage</text><path d="M912,426 C962,426 962,570 1012,570" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers2L)" /><rect x="1012" y="541" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="553" width="4" height="34" rx="2" fill="#d4ebe0" /><text x="1132" y="568" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Gradient</text><text x="1132" y="586" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#d4ebe0" textAnchor="middle">differentiable constraints</text><rect x="916" y="524.25" width="92" height="21.5" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="962" y="539" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Differentiable</text><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="1012" cy="570" r="3.2" /></g></svg>
</div>

<div className="hidden dark:block">
  <svg viewBox="0 0 1296 640" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Decision tree for choosing an optimizer" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers2D" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arroptimizers2D" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#7e9498" /></marker></defs><rect x="12" y="12" width="1272" height="616" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="1272" height="616" rx="16" fill="url(#gridoptimizers2D)" /><path d="M168,237 L208,237" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M328,237 C348,237 348,120 368,120" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M328,237 C348,237 348,354 368,354" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M472,120 L512,120" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M472,354 L512,354" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M662,120 C717,120 717,66 772,66" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M662,120 C717,120 717,174 772,174" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M662,354 C717,354 717,282 772,282" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M662,354 C717,354 717,426 772,426" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M912,174 C962,174 962,138 1012,138" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M912,174 C962,174 962,210 1012,210" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M912,426 C962,426 962,354 1012,354" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M912,426 L1012,426" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><path d="M912,426 C962,426 962,498 1012,498" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><rect x="40" y="208" width="128" height="58" rx="10" fill="#0a7e8c" /><rect x="50" y="220" width="4" height="34" rx="2" fill="#c0e6ea" /><text x="104" y="235" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">What kind of</text><text x="104" y="253" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#c0e6ea" textAnchor="middle">optimization?</text><rect x="208" y="208" width="120" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="218" y="220" width="4" height="34" rx="2" fill="#7e9498" /><text x="268" y="243" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Sequence type?</text><rect x="368" y="91" width="104" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="378" y="103" width="4" height="34" rx="2" fill="#7e9498" /><text x="420" y="126" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">DNA / RNA</text><rect x="368" y="325" width="104" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="378" y="337" width="4" height="34" rx="2" fill="#7e9498" /><text x="420" y="360" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Protein</text><rect x="512" y="91" width="150" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="522" y="103" width="4" height="34" rx="2" fill="#7e9498" /><text x="587" y="118" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Long sequence?</text><text x="587" y="136" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">(>500bp)</text><rect x="512" y="325" width="150" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="522" y="337" width="4" height="34" rx="2" fill="#7e9498" /><text x="587" y="352" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Have / want to</text><text x="587" y="370" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">design structure?</text><rect x="772" y="37" width="140" height="58" rx="10" fill="#2f8f6b" /><rect x="782" y="49" width="4" height="34" rx="2" fill="#cfeadd" /><text x="842" y="64" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">BeamSearch</text><text x="842" y="82" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#cfeadd" textAnchor="middle">+ Evo2</text><rect x="772" y="145" width="140" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="782" y="157" width="4" height="34" rx="2" fill="#7e9498" /><text x="842" y="180" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Goal?</text><rect x="772" y="253" width="140" height="58" rx="10" fill="#2f8f6b" /><rect x="782" y="265" width="4" height="34" rx="2" fill="#cfeadd" /><text x="842" y="280" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Cycling</text><text x="842" y="298" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#cfeadd" textAnchor="middle">(protein-hunter)</text><rect x="772" y="397" width="140" height="58" rx="10" fill="#1a2a2b" stroke="#33474a" strokeWidth="1.2" /><rect x="782" y="409" width="4" height="34" rx="2" fill="#7e9498" /><text x="842" y="432" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#eef5f4" textAnchor="middle">Goal?</text><rect x="1012" y="109" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="121" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="144" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling</text><rect x="1012" y="181" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="193" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="216" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">MCMC</text><rect x="1012" y="325" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="337" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="360" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling</text><rect x="1012" y="397" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="409" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="432" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">MCMC</text><rect x="1012" y="469" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="481" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="496" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Rejection Sampling then MCMC</text><text x="1132" y="514" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#cfeadd" textAnchor="middle">(use Program)</text><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="168" cy="237" r="3.2" /><circle cx="208" cy="237" r="3.2" /><circle cx="328" cy="237" r="3.2" /><circle cx="368" cy="120" r="3.2" /><circle cx="368" cy="354" r="3.2" /><circle cx="472" cy="120" r="3.2" /><circle cx="512" cy="120" r="3.2" /><circle cx="472" cy="354" r="3.2" /><circle cx="512" cy="354" r="3.2" /><circle cx="662" cy="120" r="3.2" /><circle cx="772" cy="66" r="3.2" /><circle cx="772" cy="174" r="3.2" /><circle cx="662" cy="354" r="3.2" /><circle cx="772" cy="282" r="3.2" /><circle cx="772" cy="426" r="3.2" /><circle cx="912" cy="174" r="3.2" /><circle cx="1012" cy="138" r="3.2" /><circle cx="1012" cy="210" r="3.2" /><circle cx="912" cy="426" r="3.2" /><circle cx="1012" cy="354" r="3.2" /><circle cx="1012" cy="426" r="3.2" /><circle cx="1012" cy="498" r="3.2" /></g><rect x="698" y="77.25" width="38" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="717" y="92" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Yes</text><rect x="701" y="136.25" width="32" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="717" y="151" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">No</text><rect x="668" y="297.5" width="98" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="717" y="312.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Iterative</text><text x="717" y="325.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">hallucination</text><rect x="701" y="379.25" width="32" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="717" y="394" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">No</text><rect x="934" y="136.5" width="56" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="151.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Quick</text><text x="962" y="164.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">screen</text><rect x="928" y="183.25" width="68" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="198" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Optimize</text><rect x="934" y="370.5" width="56" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="385.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Quick</text><text x="962" y="398.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">screen</text><rect x="916" y="408.5" width="92" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="423.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Detailed</text><text x="962" y="436.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">optimization</text><rect x="919" y="451.25" width="86" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="466" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Multi-stage</text><path d="M912,426 C962,426 962,570 1012,570" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers2D)" /><rect x="1012" y="541" width="240" height="58" rx="10" fill="#2f8f6b" /><rect x="1022" y="553" width="4" height="34" rx="2" fill="#cfeadd" /><text x="1132" y="568" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Gradient</text><text x="1132" y="586" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#cfeadd" textAnchor="middle">differentiable constraints</text><rect x="916" y="524.25" width="92" height="21.5" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="962" y="539" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Differentiable</text><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="1012" cy="570" r="3.2" /></g></svg>
</div>

## Pool Architecture

Understanding the dual-pool system is key to understanding how optimizers work:

<Columns>
  <Column>
    ### `proposal_sequences`

    The **working pool**. Generators write proposals here. Constraints evaluate sequences from here. Size = `num_proposals`.

    It acts as an inbox: new proposals arrive, are evaluated, and the best ones graduate to the result pool.
  </Column>

  <Column>
    ### `result_sequences`

    The **results pool**. Contains the best sequences found so far. Size = `num_results`.

    It acts as a hall of fame: only the best-scoring sequences are retained here.
  </Column>
</Columns>

### Pool Initialization (Cycling)

When an optimizer starts, either fresh or after receiving results from a previous optimizer in a [Program](/docs/language/concepts/programs), both pools are initialized by **cycling** through the source sequences:

```
Source sequences: [A, B, C]  (3 from previous optimizer)
num_results = 5

result_sequences:  [A, B, C, A, B]    # Cycles to fill 5 slots
proposal_sequences: [A, B, C, A, B, C, A, B, C, A]  # Cycles to fill num_proposals
```

This cycling preserves diversity when pool sizes differ between optimizers. Some optimizers (like Rejection Sampling) keep their results sorted by energy; others preserve their natural ordering.

## Constraint Evaluation & Performance

The `score_energy()` method implements a two-pass evaluation strategy that skips expensive GPU computations on already-rejected proposals:

**Pass 1, Filters:** All filter constraints (those with a `threshold`) are evaluated first. Proposals that fail *any* filter are immediately rejected with `energy = inf` and marked with the rejecting constraint's label. This is an AND gate; a proposal must pass every filter to survive.

**Pass 2, Scoring:** Scoring constraints (those with a `weight`) are only evaluated on proposals that passed all filters. This means expensive GPU evaluations (structure prediction, binding strength) are never run on proposals that already failed a cheap filter (homopolymer check, GC content range).

```
50 proposals generated
  → 12 rejected by homopolymer filter     (CPU, <1ms)
  → 5 rejected by GC content filter       (CPU, <1ms)
  → 33 survive to scoring
  → ESMFold pLDDT evaluated on 33         (GPU, skipped 17)
  → Boltz2 binding evaluated on 33        (GPU, skipped 17)
```

**GPU memory for constraint evaluation** is managed at the tool level, not the framework level. Unlike generators (which have a framework-level `batch_size`), constraints receive all passing proposals in a single call. Each tool handles its own memory internally: ESMFold splits by residue count, Boltz2 processes complexes sequentially, and so on. Users control this through tool-specific config fields (e.g., `max_batch_residues` for ESMFold) rather than a constraint-level parameter.

<Tip>
  Constraints are ordered with cheap filters first (sequence composition checks) and expensive scoring constraints last (structure prediction, binding). The two-pass strategy ensures rejected proposals never trigger GPU evaluations.
</Tip>

## Temperature and Acceptance

Temperature controls the exploration-exploitation trade-off in MCMC. It determines how willing the optimizer is to accept a proposal that is *worse* than the current best:

```
Acceptance probability = min(1, exp(-delta_energy / temperature))
```

<div className="block dark:hidden">
  <svg viewBox="0 0 760 390" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Temperature annealing from exploration to refinement" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers3L" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#344649" fillOpacity="0.10" /></pattern><marker id="arroptimizers3L" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#768b8e" /></marker></defs><rect x="12" y="12" width="736" height="366" rx="16" fill="#f9fcfc" stroke="#dee9e8" strokeWidth="1.2" /><rect x="12" y="12" width="736" height="366" rx="16" fill="url(#gridoptimizers3L)" /><rect x="64" y="70" width="244" height="256" rx="14" fill="#eef5f4" stroke="#ced9d7" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="82" y="91" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#768b8e" textAnchor="start" letterSpacing="1.6">High Temperature (T=1.0)</text><rect x="438" y="70" width="256" height="256" rx="14" fill="#eef5f4" stroke="#ced9d7" strokeWidth="1.3" fillOpacity="0.55" strokeDasharray="5 4" /><text x="456" y="91" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#768b8e" textAnchor="start" letterSpacing="1.6">Low Temperature (T=0.001)</text><path d="M308,198 L438,198" fill="none" stroke="#9eb4b2" strokeWidth="1.6" markerEnd="url(#arroptimizers3L)" /><rect x="88" y="114" width="196" height="54" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="98" y="126" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="147" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Accepts most moves</text><rect x="88" y="184" width="196" height="54" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="98" y="196" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="217" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Explores broadly</text><rect x="88" y="254" width="196" height="54" rx="10" fill="#eef2f4" stroke="#dbe3e6" strokeWidth="1.2" /><rect x="98" y="266" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="279" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#344649" textAnchor="middle">Good for escaping</text><text x="186" y="297" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#768b8e" textAnchor="middle">local minima</text><rect x="462" y="114" width="196" height="54" rx="10" fill="#046e7a" /><rect x="472" y="126" width="4" height="30" rx="2" fill="#bfe2e7" /><text x="560" y="139" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Only accepts</text><text x="560" y="157" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#bfe2e7" textAnchor="middle">improvements</text><rect x="462" y="184" width="196" height="54" rx="10" fill="#046e7a" /><rect x="472" y="196" width="4" height="30" rx="2" fill="#bfe2e7" /><text x="560" y="217" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Exploits locally</text><rect x="462" y="254" width="196" height="54" rx="10" fill="#046e7a" /><rect x="472" y="266" width="4" height="30" rx="2" fill="#bfe2e7" /><text x="560" y="279" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Good for final</text><text x="560" y="297" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#bfe2e7" textAnchor="middle">polishing</text><g fill="#ffffff" stroke="#9eb4b2" strokeWidth="1.4"><circle cx="308" cy="198" r="3.2" /><circle cx="438" cy="198" r="3.2" /></g><rect x="321" y="180.5" width="104" height="35" rx="6" fill="#f9fcfc" stroke="#e2e9ea" strokeWidth="1" /><text x="373" y="195.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">Annealing</text><text x="373" y="208.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#506467" textAnchor="middle">over num\_steps</text></svg>
</div>

<div className="hidden dark:block">
  <svg viewBox="0 0 760 390" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Temperature annealing from exploration to refinement" style={{width:"100%",height:"auto",display:"block"}}><defs><pattern id="gridoptimizers3D" width="22" height="22" patternUnits="userSpaceOnUse"><circle cx="2" cy="2" r="1.2" fill="#9eb4b2" fillOpacity="0.10" /></pattern><marker id="arroptimizers3D" viewBox="0 0 10 10" refX="8.5" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 L3,5 z" fill="#7e9498" /></marker></defs><rect x="12" y="12" width="736" height="366" rx="16" fill="#0e1718" stroke="#2b3c3e" strokeWidth="1.2" /><rect x="12" y="12" width="736" height="366" rx="16" fill="url(#gridoptimizers3D)" /><rect x="64" y="70" width="244" height="256" rx="14" fill="#15211f" stroke="#33474a" strokeWidth="1.3" fillOpacity="0.5" strokeDasharray="5 4" /><text x="82" y="91" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#7e9498" textAnchor="start" letterSpacing="1.6">High Temperature (T=1.0)</text><rect x="438" y="70" width="256" height="256" rx="14" fill="#15211f" stroke="#33474a" strokeWidth="1.3" fillOpacity="0.5" strokeDasharray="5 4" /><text x="456" y="91" fontFamily="'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace" fontSize="10.5" fontWeight="500" fill="#7e9498" textAnchor="start" letterSpacing="1.6">Low Temperature (T=0.001)</text><path d="M308,198 L438,198" fill="none" stroke="#566b6e" strokeWidth="1.6" markerEnd="url(#arroptimizers3D)" /><rect x="88" y="114" width="196" height="54" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="98" y="126" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="147" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Accepts most moves</text><rect x="88" y="184" width="196" height="54" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="98" y="196" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="217" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Explores broadly</text><rect x="88" y="254" width="196" height="54" rx="10" fill="#1b2829" stroke="#33474a" strokeWidth="1.2" /><rect x="98" y="266" width="4" height="30" rx="2" fill="#B4453F" /><text x="186" y="279" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#d6e1df" textAnchor="middle">Good for escaping</text><text x="186" y="297" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#9eb4b2" textAnchor="middle">local minima</text><rect x="462" y="114" width="196" height="54" rx="10" fill="#0a7e8c" /><rect x="472" y="126" width="4" height="30" rx="2" fill="#c0e6ea" /><text x="560" y="139" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Only accepts</text><text x="560" y="157" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#c0e6ea" textAnchor="middle">improvements</text><rect x="462" y="184" width="196" height="54" rx="10" fill="#0a7e8c" /><rect x="472" y="196" width="4" height="30" rx="2" fill="#c0e6ea" /><text x="560" y="217" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Exploits locally</text><rect x="462" y="254" width="196" height="54" rx="10" fill="#0a7e8c" /><rect x="472" y="266" width="4" height="30" rx="2" fill="#c0e6ea" /><text x="560" y="279" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="14" fontWeight="600" fill="#ffffff" textAnchor="middle">Good for final</text><text x="560" y="297" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11.5" fontWeight="400" fill="#c0e6ea" textAnchor="middle">polishing</text><g fill="#13201f" stroke="#566b6e" strokeWidth="1.4"><circle cx="308" cy="198" r="3.2" /><circle cx="438" cy="198" r="3.2" /></g><rect x="321" y="180.5" width="104" height="35" rx="6" fill="#13201f" stroke="#33474a" strokeWidth="1" /><text x="373" y="195.25" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">Annealing</text><text x="373" y="208.75" fontFamily="Geist, ui-sans-serif, system-ui, -apple-system, sans-serif" fontSize="11" fontWeight="400" fill="#9eb4b2" textAnchor="middle">over num\_steps</text></svg>
</div>

MCMC uses exponential annealing: `T(step) = T_max x (T_min / T_max)^((step - 1) / (num_steps - 1))`, so step 1 is exactly `T_max` and the final step is exactly `T_min`.

<Tip>
  A common pattern is to start with high temperature for exploration, then anneal to low temperature for refinement. For multi-stage optimization, use a [Program](/docs/language/concepts/programs) with explicit temperature stages instead of relying solely on annealing.
</Tip>

## Tool Cache Management

Constraints that call expensive [bioinformatics tools](/docs/language/concepts/tools) (structure prediction, sequence alignment) benefit from caching. The optimizer manages a shared tool cache:

```python python icon="python" theme={null}
MCMCOptimizer(
    ...,
    # Prune cache when it exceeds 100MB (default)
    clear_tool_cache=100 * 1024 * 1024,

    # Or: clear every step (aggressive, for memory-constrained runs)
    clear_tool_cache=True,

    # Or: only clear specific tools
    clear_tool_cache=["esmfold", "boltz2"],
)
```

## History Tracking

Optimizers record snapshots of their state at configurable intervals for post-hoc analysis:

```python python icon="python" theme={null}
optimizer.run()

# Iterate over history snapshots
for snapshot in optimizer.history:
    step = snapshot["time_step"]
    energies = [r["energy_score"] for r in snapshot["results"] if r["energy_score"] is not None]
    print(f"Step {step}: best={min(energies):.4f}, mean={sum(energies)/len(energies):.4f}")
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Programs" icon="list-tree" href="/docs/language/concepts/programs">
    Chain multiple optimizers into multi-stage pipelines
  </Card>

  <Card title="Generators" icon="cpu" href="/docs/language/concepts/generators">
    The models that propose candidate sequences
  </Card>

  <Card title="Constraints" icon="square-function" href="/docs/language/concepts/constraints">
    The quality checklist optimizers minimize
  </Card>

  <Card title="Optimizer Reference" icon="code" href="/docs/language/optimizers/mcmc">
    Full API reference for each optimizer
  </Card>
</CardGroup>

## Optimizer Catalog

<div class="tool-catalog-grid">
  <a href="/docs/language/optimizers/beam-search" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/beam-search/carousel.png" alt="" loading="lazy" />
  </a>

  <a href="/docs/language/optimizers/cycling" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/cycling/carousel.png" alt="" loading="lazy" />
  </a>

  <a href="/docs/language/optimizers/genetic-algorithm" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/genetic-algorithm/carousel.png" alt="" loading="lazy" />
  </a>

  <a href="/docs/language/optimizers/gradient" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/gradient/carousel.png" alt="" loading="lazy" />
  </a>

  <a href="/docs/language/optimizers/mcmc" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/mcmc/carousel.png" alt="" loading="lazy" />
  </a>

  <a href="/docs/language/optimizers/rejection-sampling" class="tool-catalog-card">
    <img noZoom class="card-art" src="https://proto-bio.github.io/proto-assets/images/optimizer/rejection-sampling/carousel.png" alt="" loading="lazy" />
  </a>
</div>
