use anyhow::Result;
use ndarray::{s, Array1};
#[derive(Debug, Clone)]
pub struct CmaesParams {
pub popsize: i32, pub xstart: Vec<f32>, pub sigma: f32, pub tol: f32, pub obj_value: f32, pub zs: f32, pub n: f32, pub mu: i32, pub weights: Array1<f32>, pub mueff: f32, pub cc: f32, pub cs: f32, pub c1: f32, pub cmu: f32, pub damps: f32, }
pub trait CmaesParamsValidator {
type Output;
fn new() -> Result<Self::Output>;
fn set_popsize(self, popsize: i32) -> Result<Self::Output>;
fn set_xstart(self, xstart: Vec<f32>) -> Result<Self::Output>;
fn set_sigma(self, sigma: f32) -> Result<Self::Output>;
}
impl CmaesParamsValidator for CmaesParams {
type Output = CmaesParams;
fn new() -> Result<Self::Output> {
let popsize = 50;
let xstart = vec![0.0; 50];
let sigma = 0.75;
let tol = 0.0001;
let obj_value = 0.0;
let zs = 0.05;
let n = xstart.len() as f32;
let k = popsize as f32;
let mu = popsize / 2;
let _iterable: Vec<f32> = (0..popsize)
.map(|_x| {
if _x < mu {
(k / 2.0 + 0.5).ln() - ((_x + 1) as f32).ln()
} else {
0.0
}
})
.collect();
let _weights: Array1<f32> = Array1::from_iter(_iterable);
let _w_sum = _weights.slice(s![..mu]).sum();
let weights: Array1<f32> = _weights.mapv(|x| x / _w_sum);
let mueff: f32 = (weights.slice(s![..mu]).sum() * weights.slice(s![..mu]).sum())
/ weights.slice(s![..mu]).mapv(|x| x * x).sum();
let cc = (4. + mueff / n) / (n + 4. + 2. * mueff / n);
let cs = (mueff + 2.) / (n + mueff + 5.);
let c1 = 2. / ((n + 1.3) * (n + 1.3) + mueff);
let cmu = (1. - c1).min(2. * (mueff - 2. + 1. / mueff) / ((n + 2.) * (n + 2.) + mueff));
let damps = 2. * mueff / k + 0.3 + cs;
let params = CmaesParams {
popsize,
xstart,
sigma,
tol,
obj_value,
zs,
n,
mu,
weights,
mueff,
cc,
cs,
c1,
cmu,
damps,
};
Ok(params)
}
fn set_popsize(mut self, popsize: i32) -> Result<Self> {
self.popsize = popsize;
Ok(self)
}
fn set_xstart(mut self, xstart: Vec<f32>) -> Result<Self::Output> {
self.xstart = xstart;
Ok(self)
}
fn set_sigma(mut self, sigma: f32) -> Result<Self::Output> {
self.sigma = sigma;
Ok(self)
}
}