-
Notifications
You must be signed in to change notification settings - Fork 3
/
problem.rs
111 lines (102 loc) · 3.67 KB
/
problem.rs
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
}
}