use crate::aco::pheromone::Pheromone;
use crate::aco::FMatrix;
pub trait Goodness<P: Pheromone> {
fn apply(&mut self, pheromone: &P) -> P;
}
pub struct CanonicalGoodness {
pub(in crate::aco) alpha: f64,
pub(in crate::aco) beta: f64,
pub(in crate::aco) heuristic: FMatrix,
}
impl CanonicalGoodness {
pub fn new(alpha: f64, beta: f64, heuristic: FMatrix) -> Self {
Self {
alpha,
beta,
heuristic,
}
}
pub fn default(solution_size: usize) -> Self {
let h = FMatrix::repeat(solution_size, solution_size, 1.0);
Self::new(1.0, 1.0, h)
}
}
impl Goodness<FMatrix> for CanonicalGoodness {
fn apply(&mut self, pheromone: &FMatrix) -> FMatrix {
let solution_size = pheromone.nrows();
let iter = pheromone
.iter()
.zip(self.heuristic.iter())
.map(|(p, h)| p.powf(self.alpha) * h.powf(self.beta));
FMatrix::from_iterator(solution_size, solution_size, iter)
}
}
#[cfg(test)]
mod tests {
use crate::aco::goodness::{CanonicalGoodness, Goodness};
use crate::aco::FMatrix;
#[test]
fn canonical_goodness_calculations_are_right() {
let heuristic = FMatrix::from_vec(2, 2, vec![1.0, 2.0, 4.0, 8.0]);
let alpha = 2.0;
let beta = 3.0;
let pheromone = FMatrix::from_vec(2, 2, vec![4.0, 2.0, 8.0, 0.5]);
let goodness = vec![16.0, 32.0, 4096.0, 128.0];
let mut g_op = CanonicalGoodness::new(alpha, beta, heuristic);
for (a, b) in goodness.iter().zip(g_op.apply(&pheromone).iter()) {
assert_eq!(a, b);
}
}
}