use std::ops::{Deref, DerefMut};
use thiserror::Error;
use crate::{problems::SingleObjectiveProblem, Individual, Problem};
pub trait AsSolutions<'a, P: Problem> {
fn as_solutions(&'a self) -> Vec<&'a P::Encoding>;
}
impl<'a, P, T> AsSolutions<'a, P> for T
where
P: Problem,
T: Deref + ?Sized + 'a,
&'a T::Target: IntoIterator<Item = &'a Individual<P>>,
{
fn as_solutions(&'a self) -> Vec<&'a P::Encoding> {
self.deref().into_iter().map(Individual::solution).collect()
}
}
pub trait AsSolutionsMut<'a, P: Problem> {
fn as_solutions_mut(&'a mut self) -> Vec<&'a mut P::Encoding>;
}
impl<'a, P, T> AsSolutionsMut<'a, P> for T
where
P: Problem,
T: DerefMut + ?Sized + 'a,
&'a mut T::Target: IntoIterator<Item = &'a mut Individual<P>>,
{
fn as_solutions_mut(&'a mut self) -> Vec<&'a mut P::Encoding> {
self.deref_mut()
.into_iter()
.map(Individual::solution_mut)
.collect()
}
}
pub trait IntoSolutions<P: Problem> {
fn into_solutions(self) -> Vec<P::Encoding>
where
Self: Sized;
}
impl<P, T> IntoSolutions<P> for T
where
P: Problem,
T: IntoIterator<Item = Individual<P>>,
{
fn into_solutions(self) -> Vec<P::Encoding>
where
Self: Sized,
{
self.into_iter().map(Individual::into_solution).collect()
}
}
pub trait IntoIndividuals<T> {
fn into_individuals<P: Problem<Encoding = T>>(self) -> Vec<Individual<P>>
where
Self: Sized;
}
impl<T> IntoIndividuals<T::Item> for T
where
T: IntoIterator,
{
fn into_individuals<P: Problem<Encoding = T::Item>>(self) -> Vec<Individual<P>>
where
Self: Sized,
{
self.into_iter().map(Individual::new_unevaluated).collect()
}
}
#[derive(Debug, PartialEq, Error)]
pub enum SingleIndividualError {
#[error("expected a single individual, but found none")]
EmptyPopulation,
#[error("`expected a single individual, but found {0}")]
TooManyIndividuals(usize),
}
pub trait IntoSingle<P: Problem> {
fn into_single(self) -> Result<Individual<P>, SingleIndividualError>;
}
impl<P, T> IntoSingle<P> for T
where
P: Problem,
T: IntoIterator<Item = Individual<P>>,
T::IntoIter: ExactSizeIterator,
{
fn into_single(self) -> Result<Individual<P>, SingleIndividualError> {
let mut iter = self.into_iter();
let n = iter.len();
match n {
0 => Err(SingleIndividualError::EmptyPopulation),
1 => iter.next().ok_or_else(|| unreachable!()),
_ => Err(SingleIndividualError::TooManyIndividuals(n)),
}
}
}
pub trait IntoSingleRef<'a, P: Problem> {
fn into_single_ref(self) -> Result<&'a Individual<P>, SingleIndividualError>;
}
impl<'a, P, T> IntoSingleRef<'a, P> for T
where
P: Problem,
T: IntoIterator<Item = &'a Individual<P>> + 'a,
T::IntoIter: ExactSizeIterator,
{
fn into_single_ref(self) -> Result<&'a Individual<P>, SingleIndividualError> {
let mut iter = self.into_iter();
let n = iter.len();
match n {
0 => Err(SingleIndividualError::EmptyPopulation),
1 => iter.next().ok_or_else(|| unreachable!()),
_ => Err(SingleIndividualError::TooManyIndividuals(n)),
}
}
}
pub trait BestIndividual<'a, P: SingleObjectiveProblem> {
fn best_individual(&'a self) -> Option<&'a Individual<P>>;
}
impl<'a, P, T> BestIndividual<'a, P> for T
where
P: SingleObjectiveProblem,
T: Deref + ?Sized + 'a,
&'a T::Target: IntoIterator<Item = &'a Individual<P>>,
{
fn best_individual(&'a self) -> Option<&'a Individual<P>> {
self.deref().into_iter().min_by_key(|i| i.objective())
}
}