Struct Nsga2
pub struct Nsga2 { /* private fields */ }Expand description
The elitist non-dominated sorting genetic algorithm (NSGA-II) as a
Sampler.
Hand it to a study through
StudyBuilder::sampler. It works for
any number of objectives — with one direction it degenerates to an ordinary
elitist GA, which is a legitimate (if unusual) single-objective sampler — and
over any mix of parameter kinds. See the module documentation for the
algorithm.
use atune_core::sampler::Nsga2;
let nsga2 = Nsga2::with_population_size(24)?;
assert_eq!(nsga2.population_size(), 24);
assert_eq!(nsga2.generation(), 0);Implementations§
§impl Nsga2
impl Nsga2
pub fn new() -> Self
pub fn new() -> Self
A sampler with DEFAULT_POPULATION_SIZE and the customary
η_c = η_m = 20.
pub fn with_population_size(population_size: usize) -> Result<Self>
pub fn with_population_size(population_size: usize) -> Result<Self>
A sampler with an explicit population size.
§Errors
Error::InvalidSpace outside MIN_POPULATION_SIZE ..=
MAX_POPULATION_SIZE. A population of one has nothing to hold a
tournament between and no front to spread along; the upper bound keeps
the persisted state blob bounded.
pub fn with_crossover_eta(self, eta: f64) -> Self
pub fn with_crossover_eta(self, eta: f64) -> Self
Sets the SBX distribution index η_c (default
DEFAULT_CROSSOVER_ETA).
A non-finite or negative value is refused back to the default rather than producing a meaningless spread factor.
pub fn with_mutation_eta(self, eta: f64) -> Self
pub fn with_mutation_eta(self, eta: f64) -> Self
Sets the polynomial-mutation distribution index η_m (default
DEFAULT_MUTATION_ETA).
pub fn with_swapping_prob(self, probability: f64) -> Self
pub fn with_swapping_prob(self, probability: f64) -> Self
Sets the categorical uniform-crossover swap probability (default
DEFAULT_SWAPPING_PROB), clamped into [0, 1].
pub fn with_mutation_rate(self, rate: f64) -> Self
pub fn with_mutation_rate(self, rate: f64) -> Self
Sets the per-gene mutation probability, overriding the customary 1/d.
Clamped into [0, 1]; a non-finite value restores the 1/d default.
pub const fn population_size(&self) -> usize
pub const fn population_size(&self) -> usize
How many children make one generation.
pub const fn crossover_eta(&self) -> f64
pub const fn crossover_eta(&self) -> f64
The SBX distribution index η_c.
pub const fn mutation_eta(&self) -> f64
pub const fn mutation_eta(&self) -> f64
The polynomial-mutation distribution index η_m.
pub const fn swapping_prob(&self) -> f64
pub const fn swapping_prob(&self) -> f64
The categorical uniform-crossover swap probability.
pub fn generation(&self) -> u64
pub fn generation(&self) -> u64
How many generations have closed (a generation closes when
population_size children have been evaluated
and survival has run).
0 while the initial population is still being evaluated. Returns 0 if
the state lock is poisoned — this is an inspection accessor, not a
decision path.
pub fn elite_values(&self) -> Vec<Vec<f64>>
pub fn elite_values(&self) -> Vec<Vec<f64>>
The current elite population’s objective vectors, in pool order.
The population NSGA-II is breeding from right now, ordered the way the survival step left it: front by front, and within each front by ascending pool index — which means surviving parents before surviving children, since the pool is the previous elite followed by the offspring. Crowding distance decides which members of the splitting front survive, not the order they come back in: the truncated front is re-sorted by index afterwards, so this order is stable and does not leak the crowding ranking. Empty while the initial population is still being evaluated. Useful for a report or a test; not a decision path.
Trait Implementations§
§impl Default for Nsga2
impl Default for Nsga2
§fn default() -> Self
fn default() -> Self
A sampler with DEFAULT_POPULATION_SIZE and the customary operator
constants.
§impl Sampler for Nsga2
impl Sampler for Nsga2
§fn infer_relative_space(&self, study: &StudyView) -> Result<SpaceSchema>
fn infer_relative_space(&self, study: &StudyView) -> Result<SpaceSchema>
The study’s declared space, verbatim.
NSGA-II evolves a fixed-dimension genome, so it wants a declared
SpaceSchema. A define-by-run study (no declared space) yields an empty
relative space, which routes every parameter through
sample_independent’s uniform fallback —
a genetic algorithm is a static-space method.
§Errors
Never.
§fn sample_relative(
&self,
study: &StudyView,
trial: &TrialMeta,
space: &SpaceSchema,
) -> Result<Assignment>
fn sample_relative( &self, study: &StudyView, trial: &TrialMeta, space: &SpaceSchema, ) -> Result<Assignment>
Breeds this trial’s configuration: one NSGA-II child.
While the initial population is being evaluated (before the first generation closes) the child is a fresh uniform point; afterwards it is two tournament-selected parents crossed and mutated.
Every returned value lies in its declared support — it is produced through
Distribution::from_unit of a
unit coordinate in [0, 1], so contains holds for every kind (log,
stepped, categorical, boolean).
§Errors
Error::InvalidSpace if a declared distribution is malformed;
Error::Sampler if the state lock is poisoned.
§fn sample_independent(
&self,
_study: &StudyView,
trial: &TrialMeta,
name: &str,
dist: &Distribution,
) -> Result<ParamValue>
fn sample_independent( &self, _study: &StudyView, trial: &TrialMeta, name: &str, dist: &Distribution, ) -> Result<ParamValue>
The uniform draw for a parameter the relative space did not cover — the
same fallback Tpe and Dehb
use, keyed on (sampler seed, name).
§Errors
Error::InvalidSpace if dist is malformed.
§fn after_trial(&self, study: &StudyView, trial: &FrozenTrial) -> Result<()>
fn after_trial(&self, study: &StudyView, trial: &FrozenTrial) -> Result<()>
Admits the finished trial to the offspring buffer and, once a full generation has been evaluated, runs elitist survival.
The trial’s pending job is taken unconditionally and first — a job is pending exactly while its trial is in flight — so every path out of this method releases it and the persisted state cannot grow without bound on the paths that admit nothing.
A child is admitted only if all of the following hold; otherwise it is dropped, which is never an error:
- the trial has an objective value with one entry per study direction,
and every entry is finite (a non-finite objective could not win a
Pareto comparison anyway, and JSON would round-trip it back as
null); - its recorded constraint values, if any, are all finite;
- the evaluated point is the bred point. The study loop samples every
trial, including one created from a
TrialTemplate(enqueued, retried or forked by PBT) whose fixed values then override the bred draw. Admission re-derives the evaluated configuration from the trial’s recorded parameters and compares it to the job’s genome, so a template’s objectives can never be recorded as the fitness of a genome nobody ran.
§Errors
Never — a failure here must not fail the trial, so a poisoned lock is swallowed (the update is simply skipped).
§fn state(&self) -> Result<Option<SamplerState>>
fn state(&self) -> Result<Option<SamplerState>>
The whole population as a versioned blob — the elite, the part-filled offspring buffer, the generation counter and the in-flight jobs.
§Errors
Error::Sampler if the state lock is poisoned or the state cannot be
serialized.
§fn restore_state(&self, blob: &SamplerState) -> Result<()>
fn restore_state(&self, blob: &SamplerState) -> Result<()>
Rebuilds the population from a persisted blob so a reopened study continues identically.
The blob is validated against the live sampler before it is adopted:
the population size must match (a population sized for a different
generation length is a different search), and every shape must be
internally consistent — one genome length, one objective count, genes
that are finite coordinates in [0, 1], finite objectives and
constraints. Adopting an inconsistent population would leave later
generations ranking vectors of mismatched arity, so it is refused rather
than silently reinitialised: discarding the saved population would throw
away the study’s whole search state without telling anyone.
§Errors
Error::Sampler if the blob is not an NSGA-II blob of the expected
version, was saved for a different population size, fails validation,
cannot be decoded, or the lock is poisoned.
§fn reseed(&self, _seed: u64)
fn reseed(&self, _seed: u64)
A no-op: NSGA-II’s randomness is keyed on
TrialMeta::sampler_seed and the
study seed, so there is no auxiliary stream for a reseed to move — the
same argument Tpe and Dehb
document.