M env/src/fitness/mod.rs => env/src/fitness/mod.rs +1 -0
@@ 6,6 6,7 @@ pub mod labs;
pub mod one_max;
pub mod rosenbrock;
pub mod sphere;
+pub mod real;
pub trait FitnessFunction {
type In;
A env/src/fitness/real.rs => env/src/fitness/real.rs +278 -0
@@ 0,0 1,278 @@
+use std::{convert::Infallible, f64::consts::PI, marker::PhantomData};
+
+use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector, SVector};
+
+use super::FitnessFunction;
+
+pub struct Linear<const LEN: usize> {
+ a0: f64,
+ a: SVector<f64, LEN>,
+}
+
+impl<const LEN: usize> Linear<LEN> {
+ pub fn new(a0: f64, a: SVector<f64, LEN>) -> Self {
+ Self {
+ a0,
+ a
+ }
+ }
+}
+
+impl<const LEN: usize> FitnessFunction for Linear<LEN> {
+ type In = SVector<f64, LEN>;
+ type Out = f64;
+ type Err = Infallible;
+
+ fn fit(self: &Self, inp: &Self::In) -> Result<Self::Out, Self::Err> {
+ Ok(self.a0 + (self.a.transpose() * inp).x)
+ }
+}
+
+pub struct Step<const LEN: usize> {
+ a0: f64,
+ a: SVector<f64, LEN>,
+}
+
+impl<const LEN: usize> Step<LEN> {
+ pub fn new(a0: f64, a: SVector<f64, LEN>) -> Self {
+ Self {
+ a0,
+ a
+ }
+ }
+}
+
+impl<const LEN: usize> FitnessFunction for Step<LEN> {
+ type In = SVector<f64, LEN>;
+ type Out = f64;
+ type Err = Infallible;
+
+ fn fit(self: &Self, inp: &Self::In) -> Result<Self::Out, Self::Err> {
+ Ok(self.a0 + inp.component_mul(&self.a).map(|x| x.floor()).sum())
+ }
+}
+
+pub struct Rastrigin<TDim: Dim> {
+ _phantom: PhantomData<TDim>
+}
+
+impl<TDim: Dim> Rastrigin<TDim> {
+ pub fn new() -> Self {
+ Self {
+ _phantom: PhantomData
+ }
+ }
+}
+
+impl<TDim: Dim> FitnessFunction for Rastrigin<TDim>
+where
+ DefaultAllocator: Allocator<TDim>
+{
+ type In = OVector<f64, TDim>;
+ type Out = f64;
+ type Err = Infallible;
+
+ fn fit(self: &Self, inp: &Self::In) -> Result<Self::Out, Self::Err> {
+ let dim = inp.len() as f64;
+ Ok(10.0 * dim + inp.iter()
+ .map(|x| x.powi(2) - 10.0 * (2.0 * PI * x).cos())
+ .sum::<f64>())
+ }
+}
+
+pub struct Griewank<TDim: Dim> {
+ _phantom: PhantomData<TDim>
+}
+
+impl<TDim: Dim> Griewank<TDim> {
+ pub fn new() -> Self {
+ Self {
+ _phantom: PhantomData
+ }
+ }
+}
+
+impl<TDim: Dim> FitnessFunction for Griewank<TDim>
+where
+ DefaultAllocator: Allocator<TDim>
+{
+ type In = OVector<f64, TDim>;
+ type Out = f64;
+ type Err = Infallible;
+
+ fn fit(self: &Self, inp: &Self::In) -> Result<Self::Out, Self::Err> {
+ Ok(1.0 + inp.map(|x| x.powi(2)).sum() / 4000.0 - inp
+ .iter()
+ .enumerate()
+ .map(|(i, x)| (x / ((i + 1) as f64).sqrt()).cos())
+ .product::<f64>())
+ }
+}
+
+pub struct Schwefel<const LEN: usize>;
+
+impl<const LEN: usize> Schwefel<LEN> {
+ pub fn new() -> Self {
+ Self
+ }
+}
+
+impl<const LEN: usize> FitnessFunction for Schwefel<LEN> {
+ type In = SVector<f64, LEN>;
+ type Out = f64;
+ type Err = Infallible;
+
+ fn fit(self: &Self, inp: &Self::In) -> Result<Self::Out, Self::Err> {
+ Ok(-inp
+ .map(|x| x * x.abs().sqrt().sin())
+ .sum())
+ }
+}
+
+#[cfg(test)]
+pub mod tests {
+ use nalgebra::{Dyn, OVector, SVector};
+
+ use crate::{fitness::{real::{Linear, Rastrigin, Schwefel, Step}, FitnessFunction}, test_infra::load_test_file};
+
+ use super::Griewank;
+
+ #[test]
+ fn test_linear_1() {
+ const MAX_LEN: usize = 10;
+
+ let data = load_test_file::<f64, f64>("tests/linear_1.txt");
+ let offset = SVector::repeat(1.0);
+ let linear = Linear::new(1.0, offset);
+
+ for test in data {
+ let filled = test.inp.iter()
+ .chain(vec![0f64; MAX_LEN - test.inp.len()].iter())
+ .map(|x| *x)
+ .collect::<Vec<_>>();
+ let inp = SVector::<f64, MAX_LEN>::from_vec(filled);
+
+ assert_eq!(
+ linear.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_linear_2() {
+ const MAX_LEN: usize = 10;
+
+ let data = load_test_file::<f64, f64>("tests/linear_2.txt");
+ let offset = SVector::from_vec((2..=11).map(|x| x as f64).collect());
+ let linear = Linear::new(1.0, offset);
+
+ for test in data {
+ let filled = test.inp.iter()
+ .chain(vec![0f64; MAX_LEN - test.inp.len()].iter())
+ .map(|x| *x)
+ .collect::<Vec<_>>();
+ let inp = SVector::<f64, MAX_LEN>::from_vec(filled);
+
+ assert_eq!(
+ linear.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_step_1() {
+ const MAX_LEN: usize = 10;
+
+ let data = load_test_file::<f64, f64>("tests/step_1.txt");
+ let offset = SVector::repeat(1.0);
+ let linear = Step::new(1.0, offset);
+
+ for test in data {
+ let filled = test.inp.iter()
+ .chain(vec![0f64; MAX_LEN - test.inp.len()].iter())
+ .map(|x| *x)
+ .collect::<Vec<_>>();
+ let inp = SVector::<f64, MAX_LEN>::from_vec(filled);
+
+ assert_eq!(
+ linear.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_step_2() {
+ const MAX_LEN: usize = 10;
+
+ let data = load_test_file::<f64, f64>("tests/step_2.txt");
+ let offset = SVector::from_vec((2..=11).map(|x| x as f64).collect());
+ let linear = Step::new(1.0, offset);
+
+ for test in data {
+ let filled = test.inp.iter()
+ .chain(vec![0f64; MAX_LEN - test.inp.len()].iter())
+ .map(|x| *x)
+ .collect::<Vec<_>>();
+ let inp = SVector::<f64, MAX_LEN>::from_vec(filled);
+
+ assert_eq!(
+ linear.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_rastrigin() {
+ let data = load_test_file::<f64, f64>("tests/rastrigin.txt");
+ let linear = Rastrigin::<Dyn>::new();
+
+ for test in data {
+ let inp = OVector::<f64, Dyn>::from_vec(test.inp);
+
+ assert_eq!(
+ linear.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_griewank() {
+ let data = load_test_file::<f64, f64>("tests/griewank.txt");
+ let griewank = Griewank::<Dyn>::new();
+
+ for test in data {
+ let inp = OVector::<f64, Dyn>::from_vec(test.inp);
+
+ assert_eq!(
+ griewank.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+
+ #[test]
+ fn test_schwefel() {
+ const MAX_LEN: usize = 10;
+
+ let data = load_test_file::<f64, f64>("tests/schwefel.txt");
+ let schwefel = Schwefel::new();
+
+ for test in data {
+ let filled = test.inp.iter()
+ .chain(vec![0f64; MAX_LEN - test.inp.len()].iter())
+ .map(|x| *x)
+ .collect::<Vec<_>>();
+ let inp = SVector::<f64, MAX_LEN>::from_vec(filled);
+
+ assert_eq!(
+ schwefel.fit(&inp).unwrap(),
+ test.out
+ );
+ }
+ }
+}
A env/tests/griewank.txt => env/tests/griewank.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Griewank function.
+0 : 0.0
+0.5 : 0.12247993810962732
+1 : 0.4599476941318603
+-0.5 : 0.12247993810962732
+-5 : 0.7225878145367739
+5 : 0.7225878145367739
+0 0 : 0.0
+-1 -1 : 0.5897380911762422
+-1 1 : 0.5897380911762422
+1 -1 : 0.5897380911762422
+1 1 : 0.5897380911762422
+-0.1 -0.2 : 0.014941804023654082
+0.1 0.2 : 0.014941804023654082
+-5 -5 : 1.2744346440216008
+-5 5 : 1.2744346440216008
+5 -5 : 1.2744346440216008
+5 5 : 1.2744346440216008
+0 0 0 : 0.0
+1 1 1 : 0.656567738230001
+-5 -5 -5 : 0.765274977211063
+-5 -5 5 : 0.765274977211063
+-5 5 -5 : 0.765274977211063
+-5 5 5 : 0.765274977211063
+5 -5 -5 : 0.765274977211063
+5 -5 5 : 0.765274977211063
+5 5 -5 : 0.765274977211063
+5 5 5 : 0.765274977211063
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : 1.088546150836955
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 1.088546150836955
+0 0 0 0 0 0 0 0 0 0 : 0.0
+1 1 1 1 1 1 1 1 1 1 : 0.8067591547236139
A env/tests/linear_1.txt => env/tests/linear_1.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Linear function, with coeffs a_i= (1,1,...,1) and bias a_0 = 1
+0 : 1
+0.5 : 1.5
+1 : 2
+-0.5 : 0.5
+-5 : -4
+5 : 6
+0 0 : 1
+-1 -1 : -1
+-1 1 : 1
+1 -1 : 1
+1 1 : 3
+-0.1 -0.2 : 0.7
+0.1 0.2 : 1.3
+-5 -5 : -9
+-5 5 : 1
+5 -5 : 1
+5 5 : 11
+0 0 0 : 1
+1 1 1 : 4
+-5 -5 -5 : -14
+-5 -5 5 : -4
+-5 5 -5 : -4
+-5 5 5 : 6
+5 -5 -5 : -4
+5 -5 5 : 6
+5 5 -5 : 6
+5 5 5 : 16
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : -48.6
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 50.6
+0 0 0 0 0 0 0 0 0 0 : 1
+1 1 1 1 1 1 1 1 1 1 : 11
A env/tests/linear_2.txt => env/tests/linear_2.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Linear function, with coeffs a_i = (2,3,...,D+1) and bias a_0 = 1
+0 : 1
+0.5 : 2.0
+1 : 3
+-0.5 : 0.0
+-5 : -9
+5 : 11
+0 0 : 1
+-1 -1 : -4
+-1 1 : 2
+1 -1 : 0
+1 1 : 6
+-0.1 -0.2 : 0.19999999999999996
+0.1 0.2 : 1.8
+-5 -5 : -24
+-5 5 : 6
+5 -5 : -4
+5 5 : 26
+0 0 0 : 1
+1 1 1 : 10
+-5 -5 -5 : -44
+-5 -5 5 : -4
+-5 5 -5 : -14
+-5 5 5 : 26
+5 -5 -5 : -24
+5 -5 5 : 16
+5 5 -5 : 6
+5 5 5 : 46
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : -408.1
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 410.1
+0 0 0 0 0 0 0 0 0 0 : 1
+1 1 1 1 1 1 1 1 1 1 : 66
A env/tests/rastrigin.txt => env/tests/rastrigin.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Rastringin function.
+0 : 0.0
+0.5 : 20.25
+1 : 1.0
+-0.5 : 20.25
+-5 : 25.0
+5 : 25.0
+0 0 : 0.0
+-1 -1 : 2.0
+-1 1 : 2.0
+1 -1 : 2.0
+1 1 : 2.0
+-0.1 -0.2 : 8.869660112501052
+0.1 0.2 : 8.869660112501052
+-5 -5 : 50.0
+-5 5 : 50.0
+5 -5 : 50.0
+5 5 : 50.0
+0 0 0 : 0.0
+1 1 1 : 3.0
+-5 -5 -5 : 75.0
+-5 -5 5 : 75.0
+-5 5 -5 : 75.0
+-5 5 5 : 75.0
+5 -5 -5 : 75.0
+5 -5 5 : 75.0
+5 5 -5 : 75.0
+5 5 5 : 75.0
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : 439.5698300562505
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 439.5698300562505
+0 0 0 0 0 0 0 0 0 0 : 0.0
+1 1 1 1 1 1 1 1 1 1 : 10.0
A env/tests/schwefel.txt => env/tests/schwefel.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Schwefel function.
+0 : -0.0
+0.5 : -0.32481846954003124
+1 : -0.8414709848078965
+-0.5 : 0.32481846954003124
+-5 : 3.93374565773607
+5 : -3.93374565773607
+0 0 : -0.0
+-1 -1 : 1.682941969615793
+-1 1 : -0.0
+1 -1 : -0.0
+1 1 : -1.682941969615793
+-0.1 -0.2 : 0.11758932708149258
+0.1 0.2 : -0.11758932708149258
+-5 -5 : 7.86749131547214
+-5 5 : -0.0
+5 -5 : -0.0
+5 5 : -7.86749131547214
+0 0 0 : -0.0
+1 1 1 : -2.5244129544236893
+-5 -5 -5 : 11.80123697320821
+-5 -5 5 : 3.93374565773607
+-5 5 -5 : 3.93374565773607
+-5 5 5 : -3.93374565773607
+5 -5 -5 : 3.93374565773607
+5 -5 5 : -3.93374565773607
+5 5 -5 : -3.93374565773607
+5 5 5 : -11.80123697320821
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : 23.145593064008178
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : -23.145593064008178
+0 0 0 0 0 0 0 0 0 0 : -0.0
+1 1 1 1 1 1 1 1 1 1 : -8.414709848078965
A env/tests/step_1.txt => env/tests/step_1.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Step function, with coeffs a_i= (1,1,...,1) and bias a_0 = 1
+0 : 1
+0.5 : 1
+1 : 2
+-0.5 : 0
+-5 : -4
+5 : 6
+0 0 : 1
+-1 -1 : -1
+-1 1 : 1
+1 -1 : 1
+1 1 : 3
+-0.1 -0.2 : -1
+0.1 0.2 : 1
+-5 -5 : -9
+-5 5 : 1
+5 -5 : 1
+5 5 : 11
+0 0 0 : 1
+1 1 1 : 4
+-5 -5 -5 : -14
+-5 -5 5 : -4
+-5 5 -5 : -4
+-5 5 5 : 6
+5 -5 -5 : -4
+5 -5 5 : 6
+5 5 -5 : 6
+5 5 5 : 16
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : -54
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 46
+0 0 0 0 0 0 0 0 0 0 : 1
+1 1 1 1 1 1 1 1 1 1 : 11
A env/tests/step_2.txt => env/tests/step_2.txt +32 -0
@@ 0,0 1,32 @@
+# Test data for Step function, with coeffs a_i = (2,3,...,D+1) and bias a_0 = 1
+0 : 1
+0.5 : 2
+1 : 3
+-0.5 : 0
+-5 : -9
+5 : 11
+0 0 : 1
+-1 -1 : -4
+-1 1 : 2
+1 -1 : 0
+1 1 : 6
+-0.1 -0.2 : -1
+0.1 0.2 : 1
+-5 -5 : -24
+-5 5 : 6
+5 -5 : -4
+5 5 : 26
+0 0 0 : 1
+1 1 1 : 10
+-5 -5 -5 : -44
+-5 -5 5 : -4
+-5 5 -5 : -14
+-5 5 5 : 26
+5 -5 -5 : -24
+5 -5 5 : 16
+5 5 -5 : 6
+5 5 5 : 46
+-0.1 -1.2 -2.3 -3.4 -4.5 -5.6 -6.7 -7.8 -8.9 -9.1 : -413
+0.1 1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9 9.1 : 408
+0 0 0 0 0 0 0 0 0 0 : 1
+1 1 1 1 1 1 1 1 1 1 : 66