mod weights;
use nalgebra::DVector;
use std::time::Duration;
pub use weights::Weights;
use crate::mode::Mode;
use crate::{termination, CMAESOptions};
use weights::{FinalWeights, InitialWeights};
#[derive(Clone, Debug)]
pub(crate) struct TerminationParameters {
pub max_function_evals: Option<usize>,
pub max_generations: Option<usize>,
pub max_time: Option<Duration>,
pub fun_target: Option<f64>,
pub tol_fun: f64,
pub tol_fun_rel: f64,
pub tol_fun_hist: f64,
pub tol_x: f64,
pub tol_stagnation: usize,
pub tol_x_up: f64,
pub tol_condition_cov: f64,
}
impl TerminationParameters {
pub(crate) fn from_options(options: &CMAESOptions) -> Self {
let dimensions = options.initial_mean.len();
let tol_x = options.tol_x.unwrap_or(1e-12 * options.initial_step_size);
let default_tol_stagnation =
termination::get_default_tol_stagnation_option(dimensions, options.population_size);
let tol_stagnation = options.tol_stagnation.unwrap_or(default_tol_stagnation);
Self {
max_function_evals: options.max_function_evals,
max_generations: options.max_generations,
max_time: options.max_time,
fun_target: options.fun_target,
tol_fun: options.tol_fun,
tol_fun_rel: options.tol_fun_rel,
tol_fun_hist: options.tol_fun_hist,
tol_x,
tol_stagnation,
tol_x_up: options.tol_x_up,
tol_condition_cov: options.tol_condition_cov,
}
}
}
#[derive(Clone, Debug)]
pub struct Parameters {
mode: Mode,
dim: usize,
lambda: usize,
mu: usize,
initial_sigma: f64,
mu_eff: f64,
weights: FinalWeights,
cc: f64,
c1: f64,
cs: f64,
cmu: f64,
cm: f64,
damp_s: f64,
termination: TerminationParameters,
seed: u64,
parallel_update: bool,
}
impl Parameters {
pub(crate) fn new(
options: &CMAESOptions,
seed: u64,
termination: TerminationParameters,
) -> Self {
let dim = options.initial_mean.len();
let initial_weights = InitialWeights::new(options.population_size, options.weights);
let mu = initial_weights.mu();
let mu_eff = initial_weights.mu_eff();
let a_cov = 2.0;
let cc = (4.0 + mu_eff / dim as f64) / (dim as f64 + 4.0 + 2.0 * mu_eff / dim as f64);
let c1 = a_cov / ((dim as f64 + 1.3).powi(2) + mu_eff);
let cmu = (1.0 - c1).min(
a_cov * (mu_eff - 2.0 + 1.0 / mu_eff)
/ ((dim as f64 + 2.0).powi(2) + a_cov * mu_eff / 2.0),
);
let final_weights = initial_weights.finalize(dim, c1, cmu);
let cs = (mu_eff + 2.0) / (dim as f64 + mu_eff + 5.0);
let damp_s = 1.0 + cs + 2.0 * (((mu_eff - 1.0) / (dim as f64 + 1.0)).sqrt() - 1.0).max(0.0);
Parameters {
mode: options.mode,
dim,
lambda: options.population_size,
mu,
initial_sigma: options.initial_step_size,
mu_eff,
weights: final_weights,
cc,
c1,
cs,
cmu,
cm: options.cm,
damp_s,
termination,
seed,
parallel_update: options.parallel_update,
}
}
pub(crate) fn from_options(options: &CMAESOptions, seed: u64) -> Self {
Self::new(options, seed, TerminationParameters::from_options(options))
}
pub fn mode(&self) -> Mode {
self.mode
}
pub fn dim(&self) -> usize {
self.dim
}
pub fn lambda(&self) -> usize {
self.lambda
}
pub fn mu(&self) -> usize {
self.mu
}
pub fn initial_sigma(&self) -> f64 {
self.initial_sigma
}
pub fn mu_eff(&self) -> f64 {
self.mu_eff
}
pub fn weights(&self) -> &DVector<f64> {
&self.weights
}
pub fn weights_setting(&self) -> Weights {
self.weights.setting()
}
pub fn cc(&self) -> f64 {
self.cc
}
pub fn c1(&self) -> f64 {
self.c1
}
pub fn cs(&self) -> f64 {
self.cs
}
pub fn cmu(&self) -> f64 {
self.cmu
}
pub fn cm(&self) -> f64 {
self.cm
}
pub fn damp_s(&self) -> f64 {
self.damp_s
}
pub fn max_function_evals(&self) -> Option<usize> {
self.termination.max_function_evals
}
pub fn max_generations(&self) -> Option<usize> {
self.termination.max_generations
}
pub fn max_time(&self) -> Option<Duration> {
self.termination.max_time
}
pub fn fun_target(&self) -> Option<f64> {
self.termination.fun_target
}
pub fn tol_fun(&self) -> f64 {
self.termination.tol_fun
}
pub fn tol_fun_rel(&self) -> f64 {
self.termination.tol_fun_rel
}
pub fn tol_fun_hist(&self) -> f64 {
self.termination.tol_fun_hist
}
pub fn tol_x(&self) -> f64 {
self.termination.tol_x
}
pub fn tol_stagnation(&self) -> usize {
self.termination.tol_stagnation
}
pub fn tol_x_up(&self) -> f64 {
self.termination.tol_x_up
}
pub fn tol_condition_cov(&self) -> f64 {
self.termination.tol_condition_cov
}
pub fn seed(&self) -> u64 {
self.seed
}
pub fn parallel_update(&self) -> bool {
self.parallel_update
}
}