1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::prelude::*;
use alloc::vec::Vec;
pub(crate) type BestCon<F> = <F as Fitness>::Best<F>;
/// A basic context type of the algorithms.
///
/// This type provides a shared dataset if you want to implement a new method.
/// The fields maybe expanded in the future, so it marked as non-exhaustive.
///
/// # View the Progress
///
/// You can view the progress from the [`SolverBuilder::task()`] and
/// [`SolverBuilder::callback()`].
///
/// + `ctx.gen` - Get generation number.
/// + `ctx.pop_num()` - Get population number.
/// + `ctx.best.get_eval()` - Get the current best evaluation value.
/// + `ctx.best.get_xs()` - Get the current best variables.
///
/// # Implement an Algorithm
///
/// Do everything you want to do with the context. Please see [`Algorithm`] for
/// the implementation.
#[non_exhaustive]
pub struct Ctx<F: ObjFunc> {
/// Best container
pub best: BestCon<F::Ys>,
/// Current variables of all individuals
pub pool: Vec<Vec<f64>>,
/// Current fitness values of all individuals
pub pool_y: Vec<F::Ys>,
/// Objective function object
pub func: F,
/// Generation (iteration) number
pub gen: u64,
}
impl<F: ObjFunc> Ctx<F> {
pub(crate) fn from_parts(
func: F,
limit: usize,
pool: Vec<Vec<f64>>,
pool_y: Vec<F::Ys>,
) -> Self {
let mut best = BestCon::<F::Ys>::from_limit(limit);
best.update_all(&pool, &pool_y);
Self { best, pool, pool_y, func, gen: 0 }
}
pub(crate) fn from_pool(func: F, limit: usize, pool: Vec<Vec<f64>>) -> Self {
#[cfg(not(feature = "rayon"))]
let iter = pool.iter();
#[cfg(feature = "rayon")]
let iter = pool.par_iter();
let pool_y = iter.map(|xs| func.fitness(xs)).collect();
Self::from_parts(func, limit, pool, pool_y)
}
/// Get population number.
#[inline]
pub fn pop_num(&self) -> usize {
self.pool.len()
}
/// Assign the index from source.
pub fn set_from(&mut self, i: usize, xs: Vec<f64>, ys: F::Ys) {
self.pool[i] = xs;
self.pool_y[i] = ys;
}
/// Find the best, and set it globally.
pub fn find_best(&mut self) {
self.best.update_all(&self.pool, &self.pool_y);
}
}
impl<F: ObjFunc> core::ops::Deref for Ctx<F> {
type Target = F;
fn deref(&self) -> &Self::Target {
&self.func
}
}