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
use ndarray::{Array1, Array2, ArrayView1};
use num::Bounded;
use rand::{rngs::SmallRng, seq::SliceRandom, thread_rng, Rng, SeedableRng};
use serde::{Deserialize, Serialize};
use std::{
fs::create_dir_all,
path::{Path, PathBuf},
};
use crate::TspDistance;
use std::hash::{Hash, Hasher};
mod ant_colony_optimization;
mod der;
mod opt2;
mod ser;
pub struct TspSolver<T: TspDistance> {
problem_id: String,
objects: Array1<T>,
best_path: Array1<usize>,
best_distance: f64,
rng: SmallRng,
steps: usize,
improves: usize,
check_points: PathBuf,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TspRecord {
pub problem: String,
pub improves: usize,
pub steps: usize,
pub best_distance: f64,
pub best_path: Array1<usize>,
}
impl Eq for TspRecord {}
impl PartialEq<Self> for TspRecord {
fn eq(&self, other: &Self) -> bool {
self.problem == other.problem && self.improves == other.improves
}
}
impl Hash for TspRecord {
fn hash<H: Hasher>(&self, state: &mut H) {
self.problem.hash(state);
self.improves.hash(state);
}
}
impl<T> TspSolver<T>
where
T: TspDistance,
{
pub fn new<P: AsRef<Path>>(dir: P, objects: Array1<T>) -> Self {
let rng = SmallRng::from_rng(thread_rng()).unwrap();
let best_path = initialize_path(objects.len());
TspSolver {
problem_id: String::new(),
objects,
best_path,
best_distance: f64::max_value(),
rng,
steps: 0,
improves: 0,
check_points: dir.as_ref().to_path_buf(),
}
}
pub fn with_save_points<P: AsRef<Path>>(mut self, dir: P) -> Self {
self.check_points = dir.as_ref().to_path_buf();
match create_dir_all(&self.check_points) {
Ok(_) => {}
Err(e) => {
tracing::error!("{e}")
}
}
self
}
}
fn initialize_path(num: usize) -> Array1<usize> {
let mut path = Array1::zeros((num,));
for i in 0..num {
path[i] = i;
}
path
}