pub trait Strategy<B: Backend>: Send + Sync {
type Params: Clone + Debug + Send + Sync;
type State: Clone + Debug + Send;
type Genome: Clone + Send;
// Required methods
fn init(
&self,
params: &Self::Params,
rng: &mut dyn Rng,
device: &<B as BackendTypes>::Device,
) -> Self::State;
fn ask(
&self,
params: &Self::Params,
state: &Self::State,
rng: &mut dyn Rng,
device: &<B as BackendTypes>::Device,
) -> (Self::Genome, Self::State);
fn tell(
&self,
params: &Self::Params,
population: Self::Genome,
fitness: Tensor<B, 1>,
state: Self::State,
rng: &mut dyn Rng,
) -> (Self::State, StrategyMetrics);
fn best(&self, state: &Self::State) -> Option<(Self::Genome, f32)>;
}Expand description
Central evolutionary-strategy abstraction.
The trait is intentionally pure — ask and
tell return a new State rather than mutating
through &mut self. That keeps strategies free of interior
mutability (so many instances can run in parallel without locks) and
makes Clone-based checkpointing straightforward.
§Example
The example below uses GeneticAlgorithm as a concrete strategy and
drives one ask/tell cycle by hand. Concrete strategies expose their state
fields directly; generic code over S: Strategy<B> must access state
only through Strategy::best and the tuple returns of ask/tell.
use burn::backend::Flex;
use burn::tensor::TensorData;
use rlevo_evolution::Strategy;
use rlevo_evolution::algorithms::ga::{GaConfig, GeneticAlgorithm};
use rand::{rngs::StdRng, SeedableRng};
let device = Default::default();
let strategy = GeneticAlgorithm::<Flex>::new();
let params = GaConfig::default_for(64, 10);
let mut rng = StdRng::seed_from_u64(0);
let state = strategy.init(¶ms, &mut rng, &device);
// state.population is a GaState field; dims() is (pop_size, genome_dim).
assert_eq!(state.population.dims(), [64, 10]);§Type Parameters
B: Burn backend.
§Associated Types
Params: Static configuration for a run (population size, σ, F, CR, …). Adaptive algorithms mutate their adaptive quantities insideState, notParams.State: Generation-to-generation state (current population, σ, best-so-far, RNG-free sub-statistics). Must be clonable so the harness can snapshot before a risky step if needed.Genome: Genome container produced byaskand consumed bytell. Typically aTensor<B, 2>for real-valued strategies or aTensor<B, 2, Int>for binary/integer kinds.
Required Associated Types§
Required Methods§
Sourcefn init(
&self,
params: &Self::Params,
rng: &mut dyn Rng,
device: &<B as BackendTypes>::Device,
) -> Self::State
fn init( &self, params: &Self::Params, rng: &mut dyn Rng, device: &<B as BackendTypes>::Device, ) -> Self::State
Build the initial state.
Samples the initial population, primes adaptive quantities, and sets the generation counter to zero.
Sourcefn ask(
&self,
params: &Self::Params,
state: &Self::State,
rng: &mut dyn Rng,
device: &<B as BackendTypes>::Device,
) -> (Self::Genome, Self::State)
fn ask( &self, params: &Self::Params, state: &Self::State, rng: &mut dyn Rng, device: &<B as BackendTypes>::Device, ) -> (Self::Genome, Self::State)
Propose the next population.
Takes the current state and returns the genome to evaluate
together with an updated state. The returned state typically
carries pre-computed bookkeeping (e.g. the parent indices a
tournament-based GA sampled) so tell can reuse
them without re-sampling.
Sourcefn tell(
&self,
params: &Self::Params,
population: Self::Genome,
fitness: Tensor<B, 1>,
state: Self::State,
rng: &mut dyn Rng,
) -> (Self::State, StrategyMetrics)
fn tell( &self, params: &Self::Params, population: Self::Genome, fitness: Tensor<B, 1>, state: Self::State, rng: &mut dyn Rng, ) -> (Self::State, StrategyMetrics)
Consume fitness values and produce the next state.
fitness has shape (pop_size,) on the same device as the
population. Strategies pull it to host only if they need to —
e.g. for tournament index lookups.
§Invariants
When driven by EvolutionaryHarness, the fitness tensor is
canonical (maximise) and sanitized (ADR 0034): every element is finite
or f32::NEG_INFINITY — no NaN, no +∞. A tell impl may therefore
build leaders / personal-best / global-best directly from it without a
finite check. Callers that invoke tell directly, bypassing the
harness, do not get this guarantee and must apply
sanitize_fitness at every
ordering/aggregation site (rules.md §3).
Sourcefn best(&self, state: &Self::State) -> Option<(Self::Genome, f32)>
fn best(&self, state: &Self::State) -> Option<(Self::Genome, f32)>
Best-so-far accessor.
Returns None before the first tell call.
The tuple is (genome, fitness) where fitness is the canonical
(maximise-convention) scalar — the largest value seen across all
completed generations. The harness maps it back to the objective’s
declared sense before surfacing it to callers.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".