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
use crate::{Setting, ObjFunc, AlgorithmBase, Algorithm};
pub struct FASetting {
pub base: Setting,
pub alpha: f64,
pub beta_min: f64,
pub gamma: f64,
pub beta0: f64,
}
impl Default for FASetting {
fn default() -> Self {
Self {
base: Setting {
pop_num: 80,
..Default::default()
},
alpha: 0.01,
beta_min: 0.2,
gamma: 1.,
beta0: 1.,
}
}
}
fn distance(me: &Vec<f64>, she: &Vec<f64>) -> f64 {
let mut dist = 0.;
for i in 0..me.len() {
let diff = me[i] - she[i];
dist += diff * diff;
}
dist.sqrt()
}
pub struct FA<F: ObjFunc> {
alpha: f64,
beta_min: f64,
gamma: f64,
beta0: f64,
base: AlgorithmBase<F>,
}
impl<F: ObjFunc> FA<F> {
pub fn new(func: F, settings: FASetting) -> Self {
let base = AlgorithmBase::new(func, settings.base);
Self {
alpha: settings.alpha,
beta_min: settings.beta_min,
gamma: settings.gamma,
beta0: settings.beta_min,
base,
}
}
fn move_firefly(&mut self, me: usize, she: usize) {
let r = distance(&self.base.pool[me], &self.base.pool[she]);
let beta = (self.beta0 - self.beta_min) * (-self.gamma * r * r).exp() + self.beta_min;
for s in 0..self.base.dim {
self.base.pool[me][s] = self.check(s, self.base.pool[me][s]
+ beta * (self.base.pool[she][s] - self.base.pool[me][s])
+ self.alpha * (self.ub(s) - self.lb(s)) * rand!(-0.5, 0.5));
}
}
fn move_fireflies(&mut self) {
for i in 0..self.base.pop_num {
let mut moved = false;
for j in 0..self.base.pop_num {
if i == j || self.base.fitness[i] <= self.base.fitness[j] {
continue;
}
self.move_firefly(i, j);
moved = true;
}
if moved {
continue;
}
for s in 0..self.base.dim {
self.base.pool[i][s] = self.check(s, self.base.pool[i][s]
+ self.alpha * (self.ub(s) - self.lb(s)) * rand!(-0.5, 0.5));
}
}
}
}
impl<F: ObjFunc> Algorithm<F> for FA<F> {
fn base(&self) -> &AlgorithmBase<F> { &self.base }
fn base_mut(&mut self) -> &mut AlgorithmBase<F> { &mut self.base }
fn init(&mut self) {
self.init_pop();
self.set_best(0);
}
fn generation(&mut self) {
self.move_fireflies();
for i in 0..self.base.pop_num {
let b = &mut self.base;
b.fitness[i] = b.func.fitness(b.gen, &b.pool[i]);
}
self.find_best();
}
}
#[cfg(test)]
mod tests {
use crate::{
tests::{test, TestObj},
{FA, FASetting, Setting, Task},
};
#[test]
fn fa() {
test(FA::new(
TestObj::new(),
FASetting {
base: Setting {
task: Task::MinFit(1e-20),
..Default::default()
},
..Default::default()
},
));
}
}