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
use crate::{Setting, ObjFunc, AlgorithmBase, Algorithm};
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 bounding(&mut self, s: usize) {
if self.tmp[s] < self.lb(s) {
self.tmp[s] = self.lb(s);
} else if self.tmp[s] > self.ub(s) {
self.tmp[s] = self.ub(s);
}
}
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.base.pool[i][s] + rand!(1., self.base.dim as f64)
* (self.base.best[s] - tf * mean);
self.bounding(s);
}
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.base.pool[i][s] + diff * rand!(1., self.base.dim as f64);
self.bounding(s);
}
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 init(&mut self) {
self.init_pop();
self.find_best();
}
fn generation(&mut self) {
for i in 0..self.base.pop_num {
self.teaching(i);
self.learning(i);
}
}
}
#[cfg(test)]
mod tests {
use crate::{
tests::{test, TestObj},
{TLBO, TLBOSetting, Task},
};
#[test]
fn tlbo() {
test(TLBO::new(
TestObj::new(),
TLBOSetting {
task: Task::MinFit(1e-20),
..Default::default()
},
));
}
}