Skip to main content
each cycle: condition on sequences → generate → keep proposals passing all filtersSequenceStructurepredict structure (conditioning_fn)inverse folding (generator)↻ × num_stepspredict structureredesign sequence
each cycle: condition on sequences → generate → keep proposals passing all filtersSequenceStructurepredict structure (conditioning_fn)inverse folding (generator)↻ × num_stepspredict structureredesign sequence

This optimizer is open source. Any third-party models, product names, or trademarks referenced are the property of their respective owners, and Proto is not affiliated with them.


Source
proto-bio/proto-language/proto_language/optimizer/cycling_optimizer.py
View source
Cycling optimizer for iterative sequence refinement. A generalized optimizer that cycles between a user-defined conditioning function and a generator:
  1. Call conditioning function with current sequences (from result_sequences)
  2. Pass conditioning output to generator’s sample() method (into proposal_sequences)
  3. Accept passing proposals into result_sequences (failed stay unchanged)
  4. Repeat for num_steps
This enables flexible optimization patterns such as:
  • Protein Hunter: Structure prediction -> inverse folding cycles
  • Evo2 with feedback: Constraint-guided prompt modification -> generation cycles
  • Constraints are optional; if provided, must be filter constraints (have threshold set) - only passing proposals update result_sequences

How It Works

Cycling alternates a conditioning function with a generator, looping between two views of the design (for protein-hunter, sequence and structure) and keeping only proposals that pass every filter. Cycling alternates a conditioning function with a generator. Each cycle conditions on the current sequences, generates proposals from that conditioning, and keeps only proposals that pass every filter:
for cycle in 1..num_steps:
    data      = conditioning_fn(result_sequences)
    proposals = generator.sample(data)
    result_i ← proposal_i   ⇔   proposal_i passes all filters   (else keep prior)
Cycling takes filter-only constraints (each needs a threshold; a scoring constraint raises an error). The built-in protein-hunter pipeline sets conditioning_fn to structure prediction (Boltz-2 / Chai-1 / AlphaFold3) feeding inverse folding: predict a structure, then redesign the sequence for it.

API Reference

ConfigCyclingOptimizerConfig Source
Configuration for CyclingOptimizer.This optimizer cycles between a conditioning function and a generator. On each cycle, the conditioning function receives the current proposal sequences, produces conditioning data, which is then passed to the generator’s sample() method.The conditioning function can be provided either:
  1. Directly via the conditioning_fn parameter (programmatic use)
  2. Via the pipeline field using a predefined pipeline (API/JSON use)
  • Pipeline-specific constraints:
    • protein-hunter requires an inverse_folding generator
  • Constraints are optional but if provided must be filter constraints (must have threshold set)
num_steps
integer
required
Number of conditioning-then-generation cycles to run.
num_results
integer
Candidate design trajectories for this optimizer. Overrides program-level count.
pipeline
string
Predefined conditioning pipeline. ‘protein-hunter’ uses structure prediction -> inverse folding.
protein_hunter
ProteinHunterPipelineConfig
Configuration for protein-hunter pipeline. Only used when pipeline=‘protein-hunter’.
seed
integer
Random seed for reproducible optimization, generator, and constraint tool streams.
tracking_interval
integer
default:"1"
Save history and log progress every N steps. Step 0 and final step always saved.
track_proposals
boolean
default:"False"
Save granular per-proposal results (accept/reject) in history snapshots.
verbose
boolean
default:"False"
Emit per-step debug information about proposals, scores, and acceptance through the logger.

Usage

python
>>> def my_conditioning_fn(sequences):
...     return [process(seq) for seq in sequences]
>>> optimizer = CyclingOptimizer(
...     target_segment=segment,
...     constructs=[construct],
...     generators=[generator],
...     constraints=[],
...     config=CyclingOptimizerConfig(num_steps=5, num_results=4),
...     conditioning_fn=my_conditioning_fn,
... )
>>> optimizer.run()

Metadata

PropertyValue
Keycycling
ClassCyclingOptimizer
Targets Single SegmentTrue
Uses GPUFalse