use std::any::type_name;
use color_eyre::Section;
use derivative::Derivative;
use serde::Serialize;
use crate::{
component::ExecResult,
components::Component,
identifier::{Global, Identifier, PhantomId},
population::BestIndividual,
problems::{MultiObjectiveProblem, SingleObjectiveProblem},
state::{common, StateReq},
Problem, State,
};
#[derive(Serialize, Derivative)]
#[serde(bound = "")]
#[derivative(Clone(bound = ""))]
pub struct PopulationEvaluator<I: Identifier = Global>(PhantomId<I>);
impl<I> PopulationEvaluator<I>
where
I: Identifier,
{
pub fn from_params() -> Self {
Self(PhantomId::default())
}
pub fn new_with<P: Problem>() -> Box<dyn Component<P>> {
Box::new(Self::from_params())
}
}
impl PopulationEvaluator<Global> {
pub fn new<P: Problem>() -> Box<dyn Component<P>> {
Box::new(Self::from_params())
}
}
impl<P, I: Identifier> Component<P> for PopulationEvaluator<I>
where
P: Problem,
I: Identifier,
{
fn init(&self, _problem: &P, state: &mut State<P>) -> ExecResult<()> {
state.insert(common::Evaluations(0));
Ok(())
}
fn require(&self, _problem: &P, state_req: &StateReq<P>) -> ExecResult<()> {
state_req.require::<Self, common::Populations<P>>()?;
state_req
.require::<Self, common::Evaluator<P, I>>()
.with_suggestion(|| {
format!(
"add an evaluator with identifier {} to the state",
type_name::<I>()
)
})?;
Ok(())
}
fn execute(&self, problem: &P, state: &mut State<P>) -> ExecResult<()> {
let population = state.populations_mut().try_pop();
if let Some(mut population) = population {
state.holding::<common::Evaluator<P, I>>(
|evaluator: &mut common::Evaluator<P, I>, state| {
evaluator
.as_inner_mut()
.evaluate(problem, state, &mut population);
Ok(())
},
)?;
*state.borrow_value_mut::<common::Evaluations>() += population.len() as u32;
state.populations_mut().push(population);
}
Ok(())
}
}
#[derive(Clone, Serialize)]
pub struct BestIndividualUpdate;
impl BestIndividualUpdate {
pub fn from_params() -> Self {
Self
}
pub fn new<P: SingleObjectiveProblem>() -> Box<dyn Component<P>> {
Box::new(Self)
}
}
impl<P: SingleObjectiveProblem> Component<P> for BestIndividualUpdate {
fn init(&self, _problem: &P, state: &mut State<P>) -> ExecResult<()> {
state.insert(common::BestIndividual::<P>::default());
Ok(())
}
fn execute(&self, _problem: &P, state: &mut State<P>) -> ExecResult<()> {
let populations = state.populations();
let population = populations.current();
let best = population.best_individual();
if let Some(best) = best {
state.borrow_mut::<common::BestIndividual<P>>().update(best);
}
Ok(())
}
}
#[derive(Clone, Serialize)]
pub struct ParetoFrontUpdate;
impl ParetoFrontUpdate {
pub fn from_params() -> Self {
Self
}
pub fn new<P: MultiObjectiveProblem>() -> Box<dyn Component<P>> {
Box::new(Self)
}
}
impl<P: MultiObjectiveProblem> Component<P> for ParetoFrontUpdate {
fn init(&self, _problem: &P, state: &mut State<P>) -> ExecResult<()> {
state.insert(common::ParetoFront::<P>::default());
Ok(())
}
fn execute(&self, _problem: &P, state: &mut State<P>) -> ExecResult<()> {
let populations = state.populations();
let mut front = state.borrow_mut::<common::ParetoFront<P>>();
for individual in populations.current() {
front.update(individual);
}
Ok(())
}
}