-
Notifications
You must be signed in to change notification settings - Fork 1
/
aco.rs
123 lines (107 loc) · 3.27 KB
/
aco.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
112
113
114
115
116
117
118
119
120
121
122
123
//! Implementation of Ant based algorithms
//!
//! # Ant Colony Optimization
//! Implementation is based on those sources:
//! * <https://ieeexplore.ieee.org/document/4129846> DOI: 10.1109/MCI.2006.329691
//! * <http://www.scholarpedia.org/article/Ant_colony_optimization>
//!
//! Look at [Builder](Builder) for parameters overview and
//! at [AntColonyOptimization] for interface details
//!
//! Logging system details can be found [here](probe)
//!
//! ```
pub mod builder;
pub mod colony;
pub mod grader;
pub mod pheromone;
pub mod probe;
mod solution;
pub mod termination_condition;
#[cfg(feature = "aco_tsp")]
pub mod tsp;
pub use builder::Builder;
use itertools::Itertools;
pub use solution::Solution;
use crate::aco::colony::Colony;
use crate::aco::grader::Grader;
use crate::aco::pheromone::{Pheromone, PheromoneUpdate};
use crate::aco::probe::Probe;
use crate::aco::termination_condition::TerminationCondition;
use nalgebra::{Dyn, OMatrix};
pub type FMatrix = OMatrix<f64, Dyn, Dyn>;
pub trait AdditionalArgs {}
impl AdditionalArgs for () {}
/// # Ant Colony Optimization
///
/// Encapsulates common ACO algorithm patterns.
///
/// To extract data use a [probe](probe)
pub struct AntColonyOptimization<P, C, G, T, Pr, Ph, Args = ()>
where
P: PheromoneUpdate<Ph, Args>,
C: Colony<Ph, Args>,
G: Grader<Args>,
T: TerminationCondition<Ph, Args>,
Pr: Probe<Ph, Args>,
Ph: Pheromone,
Args: AdditionalArgs,
{
colony: C,
pheromone_update: P,
pheromone: Ph,
grader: G,
termination_cond: T,
probe: Pr,
additional_args: Args,
}
impl<P, C, G, T, Pr, Ph, Args> AntColonyOptimization<P, C, G, T, Pr, Ph, Args>
where
P: PheromoneUpdate<Ph, Args>,
C: Colony<Ph, Args>,
G: Grader<Args>,
T: TerminationCondition<Ph, Args>,
Pr: Probe<Ph, Args>,
Ph: Pheromone,
Args: AdditionalArgs,
{
/// Executes the algorithm
pub fn run(mut self) {
self.termination_cond.init(&self.pheromone, &self.additional_args);
while !self
.termination_cond
.update_and_check(&self.pheromone, &self.additional_args)
{
self.probe.on_iteration_start(&self.additional_args);
self.iterate();
self.probe.on_iteration_end(&self.additional_args);
}
self.end()
}
fn iterate(&mut self) {
let paths = self
.colony
.build_solutions(&mut self.pheromone, &self.additional_args);
let sols = self.grade(paths);
let best = self.find_best(&sols);
self.probe.on_current_best(best, &self.additional_args);
self.pheromone_update
.apply(&mut self.pheromone, &sols, &self.additional_args);
self.probe
.on_pheromone_update(&self.pheromone, &self.additional_args);
}
fn find_best<'a>(&mut self, sols: &'a [Solution]) -> &'a Solution {
let best = sols
.iter()
.reduce(|a, b| if a.fitness > b.fitness { a } else { b });
best.unwrap()
}
fn grade(&mut self, paths: Vec<Vec<usize>>) -> Vec<Solution> {
let mut sols = paths.into_iter().map(Solution::from_path).collect_vec();
self.grader.apply(&mut sols, &self.additional_args);
sols
}
fn end(mut self) {
self.probe.on_end(&self.additional_args);
}
}