Ultra 0.9.4
Loading...
Searching...
No Matches
ultra::evolution_strategy< E > Class Template Reference

#include <evolution_strategy.h>

Inheritance diagram for ultra::evolution_strategy< E >:
ultra::alps_es< E > ultra::de_es< E > ultra::std_es< E >

Public Types

using evaluator_type = E
using fitness_t = evaluator_fitness_t<E>
using individual_t = evaluator_individual_t<E>

Public Member Functions

template<Population P>
void init (P &) const
template<Population P>
P * refinement_subgroup (P &) const noexcept
template<Population P>
void after_generation (P &, const summary< individual_t, fitness_t > &)
const problem & get_problem () const noexcept
template<Population P>
std::size_t max_parallelism (const P &) const noexcept
template<LayeredPopulation P>
bool valid_layer (P &pop, typename P::layer_iter iter)
template<Population P>
P * refinement_subgroup (P &pop) const noexcept
template<Population P>
std::size_t max_parallelism (const P &pop) const noexcept
template<Population P>
void after_generation (P &pop, const summary< individual_t, fitness_t > &sum)

Static Public Member Functions

static parameters shape (const parameters &p)

Protected Member Functions

 evolution_strategy (const problem &, E &)

Static Protected Member Functions

template<LayeredPopulation P>
static bool valid_layer (P &, typename P::layer_iter)

Protected Attributes

E & eva_
const problem & prob_

Detailed Description

template<Evaluator E>
class ultra::evolution_strategy< E >

Base class for compile-time evolutionary strategies.

An evolution_strategy encapsulates all strategy-dependent aspects of the evolutionary process, while leaving the overall control flow to the evolution driver.

This design uses static polymorphism: concrete strategies derive from evolution_strategy<E> and provide the required operations at compile time. No runtime polymorphism is involved.

The evolution driver owns the main generational loop, termination conditions, concurrency, and logging, while concrete strategies define how one evolutionary step is assembled and how generation-level maintenance is performed.

Strategies are expected to be:

  • stateless or minimally stateful;
  • reusable across runs;
  • independent from the evaluation logic.

The base class stores shared references to the optimisation problem and evaluator, and provides default no-op hooks where appropriate.

Remarks
Implementations should avoid performing expensive operations in constructors; initialisation should be deferred to init().
This is a low-level strategy interface. It does not tune or complete problem::params before using them. Callers that invoke strategies directly must ensure the parameters are already valid for that strategy. The usual public entry point is search, which fills generic defaults, applies strategy defaults, and preserves user-specified values before running evolution.

Constructor & Destructor Documentation

◆ evolution_strategy()

template<Evaluator E>
evolution_strategy::evolution_strategy ( const problem & prob,
E & eva )
protected

Constructs an evolution strategy.

Parameters
[in]probthe optimisation problem
[in]evathe evaluator used to assess individuals

Stores references to the evaluator and the optimisation problem. These references are shared by all operators composing the strategy (selection, recombination, replacement).

Remarks
No ownership is taken. No initialisation of the population is performed here.

Member Function Documentation

◆ after_generation() [1/2]

template<Evaluator E>
template<Population P>
void ultra::evolution_strategy< E >::after_generation ( P & pop,
const summary< individual_t, fitness_t > & sum )

Perform post-generation maintenance.

This hook is called once per generation, after all evolutionary steps have been executed.

Typical responsibilities include:

  • updating individual metadata (e.g. age);
  • restructuring the population (e.g. layer promotion or merging);
  • detecting stagnation or convergence.

Performs post-generation bookkeeping.

Template Parameters
Ppopulation type
Parameters
[in,out]popthe evolved population
[in]sumsummary statistics of the current generation

This method is invoked once per generation, after all evolutionary steps have completed.

Responsibilities:

  • increment the age of all individuals;
  • detect stagnation based on:
    • number of generations without improvement;
    • fitness variance within layers;
  • reset layers that are both stagnant and converged.

A layer is reset when (and of the points):

  • stagnation() > max_stuck_gen;
  • the fitness variance of the layer is approximately zero.
Note
Layer reset preserves the number of layers.

◆ after_generation() [2/2]

template<Evaluator E>
template<Population P>
void ultra::evolution_strategy< E >::after_generation ( P & pop,
const summary< individual_t, fitness_t > & sum )

Performs post-generation bookkeeping.

Template Parameters
Ppopulation type
Parameters
[in,out]popthe evolved population
[in]sumsummary statistics of the current generation

This method is invoked once per generation, after all evolutionary steps have completed.

Responsibilities:

  • increment the age of all individuals;
  • detect stagnation based on:
    • number of generations without improvement;
    • fitness variance within layers;
  • reset layers that are both stagnant and converged.

A layer is reset when (and of the points):

  • stagnation() > max_stuck_gen;
  • the fitness variance of the layer is approximately zero.
Note
Layer reset preserves the number of layers.

◆ init()

template<Evaluator E>
template<Population P>
void ultra::evolution_strategy< E >::init ( P & ) const
inline

Initialises the strategy before the first generation.

This method is called once, before the evolutionary loop begins. It allows the strategy to:

  • initialise internal state;
  • prepare population structures (e.g. layers, age counters);
  • validate configuration parameters.

◆ max_parallelism() [1/2]

template<Evaluator E>
template<Population P>
std::size_t ultra::evolution_strategy< E >::max_parallelism ( const P & pop) const
nodiscardnoexcept

Returns the maximum useful parallelism for this strategy.

Parameters
[in]poppopulation being evolved
Returns
maximum number of worker threads useful for this strategy

The default strategy assumes that the population topology is stable during the run. For layered populations, each layer can be evolved independently, so the useful worker count is the current number of layers. Non-layered populations have a single scheduling unit.

◆ max_parallelism() [2/2]

template<Evaluator E>
template<Population P>
std::size_t ultra::evolution_strategy< E >::max_parallelism ( const P & pop) const
noexcept

Returns the maximum useful parallelism for this strategy.

Parameters
[in]poppopulation being evolved
Returns
maximum number of worker threads useful for this strategy

The default strategy assumes that the population topology is stable during the run. For layered populations, each layer can be evolved independently, so the useful worker count is the current number of layers. Non-layered populations have a single scheduling unit.

◆ refinement_subgroup() [1/2]

template<Evaluator E>
template<Population P>
P * ultra::evolution_strategy< E >::refinement_subgroup ( P & pop) const
nodiscardnoexcept

Returns the population subgroup eligible for refinement.

Parameters
[in,out]poppopulation managed by the evolutionary process
Returns
pointer to the population subgroup to refine, or nullptr to skip refinement

This hook lets an evolutionary strategy restrict refinement to a specific part of the population.

The returned pointer is non-owning and must refer to a population-like object whose lifetime is tied to pop. Returning nullptr means that the strategy currently has no suitable refinement candidates and refinement should be skipped.

The default implementation returns the whole population.

◆ refinement_subgroup() [2/2]

template<Evaluator E>
template<Population P>
P * ultra::evolution_strategy< E >::refinement_subgroup ( P & pop) const
noexcept

Returns the population subgroup eligible for refinement.

Parameters
[in,out]poppopulation managed by the evolutionary process
Returns
pointer to the population subgroup to refine, or nullptr to skip refinement

This hook lets an evolutionary strategy restrict refinement to a specific part of the population.

The returned pointer is non-owning and must refer to a population-like object whose lifetime is tied to pop. Returning nullptr means that the strategy currently has no suitable refinement candidates and refinement should be skipped.

The default implementation returns the whole population.

◆ shape()

template<Evaluator E>
parameters ultra::evolution_strategy< E >::shape ( const parameters & p)
inlinestaticnodiscard

Sets strategy-specific parameters. The default implementation doesn't change the user-specified parameters. Some evolution strategies force parameters to specific values.


The documentation for this class was generated from the following files: