use std::convert::Infallible;
use nalgebra::{allocator::Allocator, DefaultAllocator, Dim};
use crate::binary_string::BinaryString;
use super::FitnessFunction;
use std::marker::PhantomData;
pub struct LABS<D> {
_phantom: PhantomData<D>
}
impl<D> LABS<D> {
pub fn new() -> Self {
Self {
_phantom: PhantomData
}
}
}
impl<D> FitnessFunction for LABS<D>
where
D: Dim,
DefaultAllocator: Allocator<D>
{
type In = BinaryString<D>;
type Out = i32;
type Err = Infallible;
fn fit(self: &Self, chromosome: &BinaryString<D>) -> Result<i32, Infallible> {
fn ck(k: usize, s: &Vec<i32>) -> i32 {
let d = s.len();
s.iter()
.take(d - k)
.zip(s.iter().skip(k))
.map(|(x, y)| x * y)
.sum()
}
let s: Vec<i32> = chromosome
.into_iter()
.map(|c| (*c as i32) * 2 - 1)
.collect();
let d = s.len();
Ok((1..=d-1)
.map(|k| ck(k, &s).pow(2))
.sum())
}
}
#[cfg(test)]
pub mod tests {
use nalgebra::Dyn;
use crate::{binary_string::BinaryString, fitness::{labs::LABS, FitnessFunction}, test_infra::load_test_file};
#[test]
fn test_labs() {
let data = load_test_file::<i8, i32>("tests/labs.txt");
for test in data {
println!("Test vector {}", test.inp.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join(", "));
assert_eq!(
LABS::<Dyn>::new().fit(&BinaryString::new_dyn(test.inp)).unwrap(),
test.out
)
}
}
}