Skip to main content

Nsga2

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

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>

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

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

Sets the polynomial-mutation distribution index η_m (default DEFAULT_MUTATION_ETA).

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

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

How many children make one generation.

pub const fn crossover_eta(&self) -> f64

The SBX distribution index η_c.

pub const fn mutation_eta(&self) -> f64

The polynomial-mutation distribution index η_m.

pub const fn swapping_prob(&self) -> f64

The categorical uniform-crossover swap probability.

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>>

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 Debug for Nsga2

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Default for Nsga2

§

fn default() -> Self

A sampler with DEFAULT_POPULATION_SIZE and the customary operator constants.

§

impl Sampler for Nsga2

§

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>

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>

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<()>

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>>

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<()>

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)

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.

§

fn snapshots_space(&self) -> bool

Whether this sampler enumerates a snapshot of the space it was constructed with, rather than the space each ask presents. Read more

Auto Trait Implementations§

§

impl !Freeze for Nsga2

§

impl RefUnwindSafe for Nsga2

§

impl Send for Nsga2

§

impl Sync for Nsga2

§

impl Unpin for Nsga2

§

impl UnsafeUnpin for Nsga2

§

impl UnwindSafe for Nsga2

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more