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
use rand::{Rng};
use std;

use ea::*;

/// Represents baseline interface for the objective function.
///
/// By default solution is represented by a vector of real-numbers.
///
/// # Example: Custom optimization problem
/// ```
/// extern crate revonet;
/// extern crate rand;
///
/// use rand::{Rng, SeedableRng, StdRng};
///
/// use revonet::ea::*;
/// use revonet::problem::*;
///
/// // Dummy problem returning random fitness.
/// pub struct DummyProblem;
///
/// impl Problem for DummyProblem {
///     // Function to evaluate a specific individual.
///     fn compute<T: Individual>(&self, ind: &mut T) -> f32 {
///         // use `to_vec` to get real-coded representation of an individual.
///         let v = ind.to_vec().unwrap();
///
///         // Perform calculations as per optimization problem being implemened.
///         // Here just a random value is returned.
///         let mut rng: StdRng = StdRng::from_seed(&[0]);
///         rng.gen::<f32>()
///     }
/// }
///
/// fn main() {}
/// ```

pub trait Problem{
    /// Returns whether given fitness value is enough to be a solution.
    ///
    /// # Arguments:
    /// * `value` - fitness value to consider.
    fn is_solution(&self, value: f32) -> bool {
        value < 1e-3f32
    }
    /// Generate random individual for the problem. Default implementation creates a real-coded
    /// individual with the number of genes equal to `size`
    ///
    /// # Arguments:
    /// * `size` - number of genes.
    /// * `rng` - reference to pre-initialized RNG.
    fn get_random_individual<T: Individual, R: Rng>(&self, size: usize, mut rng: &mut R) -> T {
        let mut res_ind = T::new();
        res_ind.init(size, rng);
        res_ind
    }
    /// Computes fitness value for a given individual.
    ///
    /// # Arguments:
    /// * `ind` - individual to compute a fitness for.
    fn compute<T: Individual>(&self, ind: &mut T) -> f32;
}

//---------------------------------------------------------------
/*
Some other functions: https://en.wikipedia.org/wiki/Test_functions_for_optimization
*/

/// Sample problem representing [Sphere function](https://en.wikipedia.org/wiki/Test_functions_for_optimization).
#[allow(dead_code)]
pub struct SphereProblem;
impl Problem for SphereProblem {
    fn compute<T: Individual>(&self, ind: &mut T) -> f32 {
        let v = ind.to_vec().expect("Can not extract vector of genes");
        if v.len() > 0 {v.iter().fold(0f32, |s, x| s + x*x)} else {std::f32::NAN}
    }
}

//---------------------------------------------------------------
/// Sample problem representing [Rastrigin function](https://en.wikipedia.org/wiki/Rastrigin_function).
#[allow(dead_code)]
pub struct RastriginProblem;
impl Problem for RastriginProblem {
    fn compute<T: Individual>(&self, ind: &mut T) -> f32 {
        const PI2: f32 = 2f32 * std::f32::consts::PI;
        let v = ind.to_vec().expect("Can not extract vector of genes");
        if v.len() > 0 {v.iter().fold(10f32*(v.len() as f32), |s, x| s + x*x - 10f32 * (x * PI2).cos())}
        else {std::f32::NAN}
    }
}


//---------------------------------------------------------------
/// Sample problem representing [Rosenbrock function](https://en.wikipedia.org/wiki/Rosenbrock_function).
#[allow(dead_code)]
pub struct RosenbrockProblem;
impl Problem for RosenbrockProblem {
    fn compute<T: Individual>(&self, ind: &mut T) -> f32 {
        let v = ind.to_vec().expect("Can not extract vector of genes");
        if v.len() == 0 {return std::f32::NAN;}

        let mut res = 0f32;
        for k in 1..v.len() {
            let xk = v[k as usize];
            let xk1 = v[(k - 1) as usize];
            res += 100f32 * (xk - xk1).powf(2f32) + (xk1 - 1f32).powf(2f32)
        }
        res
    }
}