use std::{convert::Infallible, error::Error, marker::PhantomData};
use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector};
use crate::{binary_string::{BinaryString, BinaryStringConversionError}, population::EvaluatedChromosome};
pub mod labs;
pub mod one_max;
pub mod rosenbrock;
pub mod sphere;
pub mod real;
pub trait FitnessFunction {
type In;
type Out;
type Err: Error + 'static;
fn fit(&self, inp: &Self::In) -> Result<Self::Out, Self::Err>;
fn fit_population(&self, inp: Vec<Self::In>) -> Result<Vec<EvaluatedChromosome<Self::In, Self::Out>>, Self::Err> {
inp
.into_iter()
.map(|chromosome|
Ok(EvaluatedChromosome {
evaluation: self.fit(&chromosome)?,
chromosome,
}))
.collect::<Result<Vec<_>, _>>()
}
}
pub struct BinaryFitnessWrapper<D, DString, TFitness>
where
D: Dim,
DefaultAllocator: Allocator<D>
{
min: OVector<f64, D>,
max: OVector<f64, D>,
fitting_function: TFitness,
_phantom: PhantomData<DString>
}
impl<D, DString, TFitness> BinaryFitnessWrapper<D, DString, TFitness>
where
DString: Dim,
DefaultAllocator: Allocator<DString>,
D: Dim,
DefaultAllocator: Allocator<D>
{
pub fn new(fitting_function: TFitness, min: OVector<f64, D>, max: OVector<f64, D>) -> Self {
Self {
fitting_function,
min,
max,
_phantom: PhantomData
}
}
}
impl<D, DString, TFitness> FitnessFunction for BinaryFitnessWrapper<D, DString, TFitness>
where
DString: Dim,
DefaultAllocator: Allocator<DString>,
D: Dim,
DefaultAllocator: Allocator<D>,
TFitness: FitnessFunction<In = OVector<f64, D>, Out = f64, Err = Infallible>
{
type In = BinaryString<DString>;
type Out = f64;
type Err = BinaryStringConversionError;
fn fit(self: &Self, inp: &BinaryString<DString>) -> Result<f64, BinaryStringConversionError> {
Ok(self.fitting_function.fit(&inp.to_real(&self.min, &self.max)?).unwrap())
}
}