pub struct EvolutionEngine {Show 13 fields
pub gene_pool: GenePool,
pub rng: StdRng,
pub cache: LruCache<String, OracleVerdict>,
pub budget: Budget,
pub in_flight: HashMap<u64, (u64, Chromosome, Instant)>,
pub stats: SearchStats,
pub target_health: TargetHealthMonitor,
pub checkpoint_path: Option<PathBuf>,
pub request_count: usize,
pub gene_stats: Vec<(String, String, u32, u32)>,
pub fitness_history: VecDeque<f64>,
pub stagnation_counter: u32,
pub corpus: BypassCorpus,
/* private fields */
}Expand description
The evolutionary engine that maintains a population and evolves it.
Fields§
§gene_pool: GenePoolGene pool for creating/mutating chromosomes.
rng: StdRngSeeded random number generator.
cache: LruCache<String, OracleVerdict>Payload→verdict LRU cache.
budget: BudgetHard budget limits.
in_flight: HashMap<u64, (u64, Chromosome, Instant)>Candidates currently being evaluated:
engine_eval_id → (algorithm_candidate_id, Chromosome, sent_at).
algorithm_candidate_id is the ID the search algorithm
originally minted in request_evaluations and the same ID it
expects to see back in submit_evaluations. Population-based
algorithms (MapElites, NoveltySearch) keep their own private
in_flight keyed by that ID — if we forwarded the engine’s
eval_id instead, their lookup misses and the evaluation is
silently dropped (the grid / archive never gets updated).
stats: SearchStatsSearch statistics.
target_health: TargetHealthMonitorTarget health monitor.
checkpoint_path: Option<PathBuf>Optional path for automatic checkpointing.
request_count: usizeTotal oracle requests issued.
gene_stats: Vec<(String, String, u32, u32)>Per-gene success tracking: (gene_name, gene_value, successes, attempts).
fitness_history: VecDeque<f64>Fitness history: average fitness per generation (sliding window).
stagnation_counter: u32Number of consecutive generations with no improvement.
corpus: BypassCorpusSaved bypass corpus.
Implementations§
Source§impl EvolutionEngine
impl EvolutionEngine
Move this engine behind the canonical SharedEngine pointer.
Equivalent to Arc::new(RwLock::new(self)) — exists so the
shared-access pattern is discoverable on the type itself
rather than buried in module-level docs.
Source§impl EvolutionEngine
impl EvolutionEngine
Sourcepub fn new(population_size: usize) -> Self
pub fn new(population_size: usize) -> Self
Create a new engine with the given algorithm and population size.
Sourcepub fn new_seeded(population_size: usize, seed: u64) -> Self
pub fn new_seeded(population_size: usize, seed: u64) -> Self
Create a new engine with a seeded RNG.
population_size is clamped to the inclusive range [1, 10_000]:
0 would leave the selection helpers (tournament/roulette) with
nothing to index — a contract violation that used to panic.
10_000 caps memory at construction so a misconfigured caller
can’t OOM the process by passing usize::MAX.
Sourcepub fn with_algorithm(
algorithm_name: &str,
gene_pool: GenePool,
rng: StdRng,
budget: Budget,
) -> Result<Self, EvolutionError>
pub fn with_algorithm( algorithm_name: &str, gene_pool: GenePool, rng: StdRng, budget: Budget, ) -> Result<Self, EvolutionError>
Create an engine with a specific algorithm by name.
Sourcepub fn next_id(&self) -> u64
pub fn next_id(&self) -> u64
Read-only view of the engine’s next eval-id counter. Exposed so checkpoint round-trip tests can verify the counter is preserved across save/load. The field itself stays private so external callers can’t desync it.
Sourcepub fn next_candidate(&mut self) -> Option<(usize, &Chromosome)>
pub fn next_candidate(&mut self) -> Option<(usize, &Chromosome)>
Get the next candidate to try (legacy sequential API).
Returns a synthetic index and a reference to the stored candidate.
Sourcepub fn batch_candidates(&mut self, n: usize) -> Vec<(usize, Chromosome)>
pub fn batch_candidates(&mut self, n: usize) -> Vec<(usize, Chromosome)>
Request a batch of up to n candidates for parallel evaluation.
Checks cache, budget, and target health before returning candidates.
n is also clamped to the remaining budget.max_requests headroom
so a single batch call can never overshoot the hard request budget
(the underlying algorithm is free to request whatever it likes
internally; the engine bounds the request count it actually
surfaces).
Sourcepub fn prune_stale_in_flight(&mut self, max_age: Duration) -> usize
pub fn prune_stale_in_flight(&mut self, max_age: Duration) -> usize
Drop entries from the in-flight map that have been outstanding
longer than max_age. The proxy / scan loop should call this
periodically (or when a Worker pool is reaped) so a dropped
evaluation doesn’t permanently consume a budget slot.
Audit (2026-05-10): pre-fix in_flight grew without any TTL —
every dropped eval permanently consumed a max_requests slot,
so a long scan with even moderate eval-loss would terminate
prematurely with budget exhausted while the in-flight map
silently accumulated. Returns the number of pruned entries.
Sourcepub fn submit_batch(
&mut self,
results: Vec<(usize, OracleVerdict)>,
) -> Result<(), EvolutionError>
pub fn submit_batch( &mut self, results: Vec<(usize, OracleVerdict)>, ) -> Result<(), EvolutionError>
Submit a batch of evaluation results.
§Errors
Returns an error if an evaluation ID is not in the in-flight set.
Sourcepub fn record_feedback(
&mut self,
chromosome_index: usize,
passed: bool,
) -> Result<(), EvolutionError>
pub fn record_feedback( &mut self, chromosome_index: usize, passed: bool, ) -> Result<(), EvolutionError>
Record legacy boolean feedback for a candidate.
Sourcepub fn record_verdict(
&mut self,
chromosome_index: usize,
verdict: &OracleVerdict,
) -> Result<(), EvolutionError>
pub fn record_verdict( &mut self, chromosome_index: usize, verdict: &OracleVerdict, ) -> Result<(), EvolutionError>
Record rich oracle verdict feedback.
Sourcepub fn record_target_error(
&mut self,
error: String,
) -> Result<(), EvolutionError>
pub fn record_target_error( &mut self, error: String, ) -> Result<(), EvolutionError>
Record target-error feedback.
Sourcepub fn should_terminate(&self) -> bool
pub fn should_terminate(&self) -> bool
Check if evolution should terminate.
Sourcepub fn best(&self) -> Option<&Chromosome>
pub fn best(&self) -> Option<&Chromosome>
Get the best-performing chromosome.
Sourcepub fn save_checkpoint(&self, path: &Path) -> Result<(), EvolutionError>
pub fn save_checkpoint(&self, path: &Path) -> Result<(), EvolutionError>
Save engine state to disk.
Sourcepub fn load_checkpoint(&mut self, path: &Path) -> Result<(), EvolutionError>
pub fn load_checkpoint(&mut self, path: &Path) -> Result<(), EvolutionError>
Load engine state from disk.
Sourcepub fn learned_summary(&self) -> String
pub fn learned_summary(&self) -> String
Get a human-readable summary.
Sourcepub fn seed_population(&mut self, population: Vec<Chromosome>)
pub fn seed_population(&mut self, population: Vec<Chromosome>)
Seed the underlying algorithm with an explicit population — the public path callers use to warm-start search from a known good corpus (or to inject a synthetic population from tests).
Sourcepub fn population_snapshot(&self) -> Vec<Chromosome>
pub fn population_snapshot(&self) -> Vec<Chromosome>
Snapshot the algorithm’s live population (test/diagnostic surface). Population-based algorithms return their full pool; single-state algorithms return the singleton current/best.
Sourcepub fn diversity_score(&self) -> f64
pub fn diversity_score(&self) -> f64
Population diversity in [0.0, 1.0] — drives adaptive mutation
pressure (see crossover::diversity::adaptive_mutation_rate).
Strategy:
- Snapshot the algorithm’s live population and union it with
the engine’s
in_flightcandidates. - If
len() >= 2, return mean pairwise gene-mismatch ratio viacrossover::diversity::diversity_score. - Otherwise (single-state algorithm with nothing in-flight),
fall back to gene-pool exploration entropy from
Self::gene_stats_diversity— measures how broadly the engine has explored the gene space rather than how varied the current population is. With no exploration history either, return 1.0 (max-safe default — keeps mutation pressure conservative on a fresh engine).
Sourcepub fn gene_stats_diversity(&self) -> f64
pub fn gene_stats_diversity(&self) -> f64
Shannon-entropy style diversity over the engine’s per-gene exploration history.
For each unique gene name in gene_stats, computes the
normalised entropy of its value distribution weighted by
attempts. The per-gene entropies are averaged. Range
[0.0, 1.0]: 0.0 means we tried only one value for every
gene (no exploration), 1.0 means a uniform distribution
across the maximum-cardinality gene’s value space.
Useful as a fallback signal when the active search algorithm is single-state (e.g. simulated annealing) and the population snapshot is too small to give meaningful pairwise distance.