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
use crate::{Algorithm, AlgorithmBase, ObjFunc, Setting};
pub type TLBOSetting = Setting;
pub struct TLBO<F: ObjFunc> {
tmp: Vec<f64>,
base: AlgorithmBase<F>,
}
impl<F: ObjFunc> TLBO<F> {
pub fn new(func: F, settings: TLBOSetting) -> Self {
let base = AlgorithmBase::new(func, settings);
Self {
tmp: zeros!(base.dim),
base,
}
}
fn register(&mut self, i: usize) {
let f_new = self.base.func.fitness(self.base.gen, &self.tmp);
if f_new < self.base.fitness[i] {
self.base.pool[i] = self.tmp.clone();
self.base.fitness[i] = f_new;
}
if f_new < self.base.best_f {
self.set_best(i);
}
}
fn teaching(&mut self, i: usize) {
let tf = f64::round(rand!() + 1.);
for s in 0..self.base.dim {
let mut mean = 0.;
for j in 0..self.base.pop_num {
mean += self.base.pool[j][s];
}
mean /= self.base.dim as f64;
self.tmp[s] = self.check(s, self.base.pool[i][s]
+ rand!(1., self.base.dim as f64) * (self.base.best[s] - tf * mean));
}
self.register(i);
}
fn learning(&mut self, i: usize) {
let j = {
let j = rand!(0, self.base.pop_num - 1);
if j >= i { j + 1 } else { j }
};
for s in 0..self.base.dim {
let diff = if self.base.fitness[j] < self.base.fitness[i] {
self.base.pool[i][s] - self.base.pool[j][s]
} else {
self.base.pool[j][s] - self.base.pool[i][s]
};
self.tmp[s] = self.check(s, self.base.pool[i][s]
+ rand!(1., self.base.dim as f64) * diff);
}
self.register(i);
}
}
impl<F: ObjFunc> Algorithm<F> for TLBO<F> {
fn base(&self) -> &AlgorithmBase<F> { &self.base }
fn base_mut(&mut self) -> &mut AlgorithmBase<F> { &mut self.base }
fn generation(&mut self) {
for i in 0..self.base.pop_num {
self.teaching(i);
self.learning(i);
}
}
}
#[cfg(test)]
mod tests {
use crate::{
{Task, TLBO, TLBOSetting},
tests::{test, TestObj},
};
#[test]
fn tlbo() {
test(TLBO::new(
TestObj::new(),
TLBOSetting {
task: Task::MinFit(1e-20),
..Default::default()
},
));
}
}