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
use super::*;
use gen_iter::GenIter;

impl<T> TspSolver<T>
where
    T: TspDistance,
{
    pub fn ant_colony_optimization(&mut self, ants: usize) -> impl Iterator<Item = TspRecord> + '_
    where
        T: Serialize,
    {
        let mut path = (0..self.objects.len()).collect::<Vec<usize>>();
        path.shuffle(&mut self.rng);
        GenIter(move || {
            yield self.get_record();
            loop {
                let mut ant_paths = Array2::zeros((ants, path.len()));
                for i in 0..ants {
                    for (j, value) in self.build_path(&path).iter().enumerate() {
                        ant_paths[[i, j]] = *value;
                    }
                }
                let (new_path, new_distance) = self.collect_best_path(ant_paths);
                if new_distance < self.best_distance {
                    self.best_path = new_path;
                    self.best_distance = new_distance;
                    self.improves += 1;
                    self.save_best();
                    yield self.get_record()
                }
                self.steps += 1;
            }
        })
    }
    fn save_best(&self)
    where
        T: Serialize,
    {
        match self.save(&self.check_points) {
            Ok(_) => {}
            Err(e) => {
                println!("{e:?} {}", self.check_points.display());
                tracing::error!("{}", e)
            }
        }
    }

    fn build_path(&mut self, path: &[usize]) -> Array1<usize> {
        let mut visited = vec![false; self.objects.len()];
        let mut ant_path = Array1::zeros((path.len(),));
        ant_path[0] = path[0];
        visited[path[0]] = true;
        for i in 1..path.len() {
            let next = self.select_next(ant_path[i - 1], &visited);
            ant_path[i] = next;
            visited[next] = true;
        }
        ant_path
    }

    fn select_next(&mut self, current: usize, visited: &[bool]) -> usize {
        let pheromones = self.compute_pheromones(current, visited);
        let total_pheromones = pheromones.iter().sum::<f64>();
        let probabilities = pheromones.iter().map(|&p| p / total_pheromones).collect::<Vec<_>>();
        let mut cum_prob = 0.0;
        let random_value = self.rng.gen::<f64>();
        for (i, &prob) in probabilities.iter().enumerate() {
            cum_prob += prob;
            if random_value <= cum_prob {
                return i;
            }
        }
        probabilities.iter().enumerate().max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap()).unwrap().0
    }

    fn compute_pheromones(&self, current: usize, visited: &[bool]) -> Vec<f64> {
        let mut pheromones = vec![0.0; self.objects.len()];
        for (i, obj) in self.objects.iter().enumerate() {
            if visited[i] {
                continue;
            }
            let distance = T::distance(obj, &self.objects[current]);
            pheromones[i] = self.compute_pheromone(distance);
        }
        pheromones
    }

    fn compute_pheromone(&self, distance: f64) -> f64 {
        1.0 / distance
    }

    fn collect_best_path(&self, ant_paths: Array2<usize>) -> (Array1<usize>, f64) {
        let mut best_path = Array1::zeros((ant_paths.shape()[1],));
        let mut best_distance = f64::max_value();
        for i in 0..ant_paths.shape()[0] {
            let path = ant_paths.row(i);
            let distance = T::total(self.objects.view(), path);
            if distance < best_distance {
                best_path = path.to_owned();
                best_distance = distance;
            }
        }
        (best_path, best_distance)
    }
}