use std::{
cell::{Ref, RefMut},
marker::PhantomData,
ops::Deref,
};
use better_any::TidAble;
use derive_more::{Deref, DerefMut};
use crate::{
component::ExecResult,
identifier,
identifier::Identifier,
logging,
logging::log::Log,
problems::{Evaluate, MultiObjectiveProblem, SingleObjectiveProblem},
Individual, Problem, SingleObjective,
};
pub mod common;
pub mod random;
pub mod registry;
mod require;
pub use random::Random;
pub use registry::{CustomState, StateError, StateRegistry, StateResult};
pub use require::StateReq;
#[derive(Deref, DerefMut)]
pub struct State<'a, P> {
#[deref]
#[deref_mut]
registry: StateRegistry<'a>,
marker: PhantomData<P>,
}
impl<'a, P> State<'a, P> {
pub fn new() -> Self {
Self::from(StateRegistry::new())
}
pub fn requirements(&self) -> StateReq<'_, 'a, P> {
StateReq::new(self)
}
pub fn with_inner_state<F>(&mut self, f: F) -> ExecResult<Self>
where
F: FnOnce(&mut Self) -> ExecResult<()>,
{
let registry = std::mem::take(&mut self.registry);
let mut state = registry.into_child().into();
f(&mut state)?;
let (registry, child) = StateRegistry::from(state).into_parent();
self.registry = registry.unwrap();
Ok(child.into())
}
pub fn holding<T>(
&mut self,
f: impl FnOnce(&mut T, &mut Self) -> ExecResult<()>,
) -> ExecResult<()>
where
T: CustomState<'a> + TidAble<'a>,
{
#[derive(better_any::Tid)]
struct Marker<T>(PhantomData<fn() -> T>);
impl<'a, T: TidAble<'a>> CustomState<'a> for Marker<T> {}
let registry_with_t = self.find_mut::<T>()?;
registry_with_t.insert(Marker::<T>(PhantomData));
let mut t = registry_with_t.remove::<T>()?;
f(&mut t, self)?;
let state_with_t = self.find_mut::<Marker<T>>()?;
state_with_t.insert(t);
state_with_t.remove::<Marker<T>>()?;
Ok(())
}
}
impl<'a, P> From<StateRegistry<'a>> for State<'a, P> {
fn from(value: StateRegistry<'a>) -> Self {
Self {
registry: value,
marker: PhantomData,
}
}
}
impl<'a, P> From<State<'a, P>> for StateRegistry<'a> {
fn from(value: State<'a, P>) -> Self {
value.registry
}
}
impl<P> Default for State<'_, P> {
fn default() -> Self {
Self::new()
}
}
impl<P> State<'_, P>
where
P: Problem,
{
pub fn iterations(&self) -> u32 {
self.get_value::<common::Iterations>()
}
pub fn evaluations(&self) -> u32 {
self.get_value::<common::Evaluations>()
}
pub fn populations(&self) -> Ref<'_, common::Populations<P>> {
self.borrow::<common::Populations<P>>()
}
pub fn populations_mut(&self) -> RefMut<'_, common::Populations<P>> {
self.borrow_mut::<common::Populations<P>>()
}
pub fn random_mut(&self) -> RefMut<'_, Random> {
self.borrow_mut::<Random>()
}
pub fn log(&self) -> Ref<'_, Log> {
self.borrow::<Log>()
}
pub fn configure_log<F>(&mut self, f: F) -> ExecResult<()>
where
F: FnOnce(&mut logging::LogConfig<P>) -> ExecResult<()>,
{
let mut config = self.entry::<logging::LogConfig<P>>().or_default();
f(&mut *config)
}
}
impl<'a, P: Problem> State<'a, P> {
pub fn insert_evaluator(&mut self, evaluator: impl Evaluate<Problem = P> + 'a) {
self.insert(common::Evaluator::<P, identifier::Global>::new(evaluator));
}
pub fn insert_evaluator_as<I: Identifier>(
&mut self,
evaluator: impl Evaluate<Problem = P> + 'a,
) {
self.insert(common::Evaluator::<P, I>::new(evaluator));
}
}
impl<P> State<'_, P>
where
P: SingleObjectiveProblem,
{
pub fn best_individual(&self) -> Option<Ref<'_, Individual<P>>> {
let r = self.try_borrow::<common::BestIndividual<P>>().ok()?;
Ref::filter_map(r, |r| r.deref().as_ref()).ok()
}
pub fn best_objective_value(&self) -> Option<SingleObjective> {
self.best_individual().map(|i| *i.objective())
}
}
impl<P> State<'_, P>
where
P: MultiObjectiveProblem,
{
pub fn pareto_front(&self) -> Ref<'_, common::ParetoFront<P>> {
self.borrow::<common::ParetoFront<P>>()
}
}