1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//! This module contains multi-objective functions

use crate::{FixedDimensional, NDimensional, UnConstrained, Constrained, MultiObjective, Bounded};

/// This is the Chankong-Haimes function.
///
/// The function is borrowed from [here](https://en.wikipedia.org/wiki/Test_functions_for_optimization).
/// This function is specificaly 2 dimensional, and has a Pareto fron that looks like this:
///
/// ![](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Chakong_and_Haimes_function.pdf/page1-796px-Chakong_and_Haimes_function.pdf.jpg)
pub struct ChankongHaimes {}

impl FixedDimensional for ChankongHaimes {
    const D: usize = 2;
}

impl Bounded for ChankongHaimes {
    const BOUNDS: (f64, f64) = (-20.0, 20.0);
}

impl Constrained for ChankongHaimes {
    const NH: usize = 0;
    const NG: usize = 2;

    fn equality_constraints(_x: Vec<f64>) -> Vec<f64> {
        vec![0.0; Self::NH]
    }

    fn inequality_constraints(x: Vec<f64>) -> Vec<f64> {
        let mut fx: Vec<f64> = vec![0.0; Self::NG];
        fx[0] = x[0].powi(2) + x[1].powi(2) - 225.0;
        fx[1] = x[0] - 3.0*x[1] + 10.0;
        fx
    }
}

impl MultiObjective for ChankongHaimes {
    const NF: usize = 2;

    fn f(x: Vec<f64>) -> Vec<f64> {
        Self::check_input(x.clone());
        let mut fx: Vec<f64> = vec![0.0; Self::NF];
        fx[0] = 2.0 + (x[0] - 2.0).powi(2) - (x[1] - 1.0).powi(2);
        fx[1] = 9.0*x[0] - (x[1] - 1.0).powi(2);
        fx
    }
}

#[cfg(test)]
mod chankong_haimes_tests {
    use super::{ChankongHaimes as F, MultiObjective, Constrained, FixedDimensional};

    #[test]
    fn check_zero() {
        let x = vec![0.0; F::D];
        F::f(x.clone());
        F::equality_constraints(x.clone());
        F::inequality_constraints(x);
        assert!(true);
    }

    #[test]
    fn check_one() {
        let x = vec![0.0; F::D];
        F::f(x.clone());
        F::equality_constraints(x.clone());
        F::inequality_constraints(x);
        assert!(true);
    }
}


/// This is the Fonseca-Fleming function.
///
/// The function is borrowed from [here](https://en.wikipedia.org/wiki/Test_functions_for_optimization).
/// Although the function accepts a vector with an arbitrary number of inputs, this is what the
/// Pareto front looks like in 2D:
///
/// ![](https://upload.wikimedia.org/wikipedia/commons/thumb/5/59/Fonseca_and_Fleming_function.pdf/page1-796px-Fonseca_and_Fleming_function.pdf.jpg)
pub struct FonsecaFlemming {}

impl NDimensional for FonsecaFlemming {}
impl UnConstrained for FonsecaFlemming {}

impl Bounded for FonsecaFlemming {
    const BOUNDS: (f64, f64) = (-4.0, 4.0);
}

impl MultiObjective for FonsecaFlemming {
    const NF: usize = 2;

    fn f(x: Vec<f64>) -> Vec<f64> {
        let mut fx: Vec<f64> = vec![0.0; Self::NF];
        let n = x.len();
        let mut sumxminus: f64 = 0.0;
        let mut sumxplus: f64 = 0.0;
        let nsqrt = (n as f64).sqrt();
        for xi in x {
            sumxminus += (xi - 1.0/nsqrt).powi(2);
            sumxplus += (xi + 1.0/nsqrt).powi(2);
        }
        fx[0] = 1.0 - (-sumxminus).exp();
        fx[1] = 1.0 - (-sumxplus).exp();
        fx
    }
}

#[cfg(test)]
mod flemingfonseca_tests {
    use super::{FonsecaFlemming as F, NDimensional, MultiObjective};

    #[test]
    fn check_zero() {
        F::f(vec![0.0; F::LOW_D]);
        F::f(vec![0.0; F::HIGH_D]);
        assert!(true);
    }

    #[test]
    fn check_one() {
        F::f(vec![1.0; F::LOW_D]);
        F::f(vec![1.0; F::HIGH_D]);
        assert!(true);
    }
}

/// This is the Viennet function.
///
/// The function is borrowed from [here](https://en.wikipedia.org/wiki/Test_functions_for_optimization).
/// This function is specifically 2 dimensional, and has a Pareto fron that looks like this:
///
/// ![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f2/Viennet_function.pdf/page1-796px-Viennet_function.pdf.jpg)

pub struct Viennet {}

impl UnConstrained for Viennet {}

impl FixedDimensional for Viennet {
    const D: usize = 2;
}

impl Bounded for Viennet {
    const BOUNDS: (f64, f64) = (-3.0, 3.0);
}

impl MultiObjective for Viennet {
    const NF: usize = 3;

    fn f(x: Vec<f64>) -> Vec<f64> {
        Self::check_input(x.clone());
        let mut fx: Vec<f64> = vec![0.0; Self::NF];
        let x2y2 = x[0].powi(2) + x[1].powi(2);
        fx[0] = 0.5*x2y2 + x2y2.sin();
        fx[1] = (3.0*x[0] - 2.0*x[1] + 4.0).powi(2)/8.0 + (x[0] - x[1] + 1.0).powi(2)/27.0 + 15.0;
        fx[2] = 1.0/(x2y2 + 1.0) - 1.1*(-x2y2).exp();
        fx
    }
}


#[cfg(test)]
mod viennet_tests {
    use super::{Viennet as F, MultiObjective, FixedDimensional};

    #[test]
    fn check_zero() {
        let x = vec![0.0; F::D];
        F::f(x.clone());
        assert!(true);
    }

    #[test]
    fn check_one() {
        let x = vec![0.0; F::D];
        F::f(x.clone());
        assert!(true);
    }
}