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
use crate::{common::TspRecord, TspDistance, TspError, TspResult, TspSolver};
use ndarray::{Array1, ArrayView1};
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use serde::{
de::{DeserializeOwned, MapAccess, Visitor},
Deserialize, Deserializer,
};
use std::{fmt::Formatter, fs::read_to_string, path::Path};
impl<T> TspSolver<T>
where
T: TspDistance,
{
pub fn load_or_create<P: AsRef<Path>>(dir: P, objects: ArrayView1<T>) -> Self
where
T: DeserializeOwned + Clone,
{
let path = dir.as_ref();
match Self::load(path) {
Ok(o) => o,
Err(_) => Self::new(path, objects.to_owned()),
}
}
pub fn load<P: AsRef<Path>>(dir: P) -> TspResult<Self>
where
T: DeserializeOwned,
{
let path = dir.as_ref().canonicalize()?;
if !path.exists() || !path.is_dir() {
Err(TspError::io_error(&path, "Directory not found"))?
}
let content = read_to_string(path.join("main.json"))?;
let mut this = serde_json::from_str::<Self>(&content)?;
this.check_points = path.to_path_buf();
this.load_record(this.improves)?;
Ok(this)
}
pub fn load_record(&mut self, improves: usize) -> TspResult<()> {
let record = TspRecord::load(self.check_points.clone(), improves)?;
self.steps = record.steps;
self.best_distance = record.best_distance;
self.best_path = record.best_path;
Ok(())
}
}
impl TspRecord {
pub fn load<P: AsRef<Path>>(dir: P, improves: usize) -> TspResult<Self> {
let file = dir.as_ref().join(format!("step_{}.json", improves));
let content = read_to_string(file)?;
Ok(serde_json::from_str(&content)?)
}
}
impl<'de, T> Deserialize<'de> for TspSolver<T>
where
T: Deserialize<'de> + TspDistance,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let mut this = TspSolver {
problem_id: "".to_string(),
objects: Array1::from_shape_vec((0,), vec![]).unwrap(),
best_path: Default::default(),
best_distance: 0.0,
rng: SmallRng::from_rng(thread_rng()).unwrap(),
steps: 0,
improves: 0,
check_points: Default::default(),
};
TspSolver::deserialize_in_place(deserializer, &mut this)?;
Ok(this)
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(TspDeserializer { ptr: place })
}
}
pub struct TspDeserializer<'i, T: TspDistance> {
ptr: &'i mut TspSolver<T>,
}
impl<'i, 'de, T> Visitor<'de> for TspDeserializer<'i, T>
where
T: Deserialize<'de> + TspDistance,
{
type Value = ();
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("expect `TspSolver` object")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'de>,
{
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"problem_id" => self.ptr.problem_id = map.next_value()?,
"objects" => self.ptr.objects = map.next_value()?,
"improves" => self.ptr.improves = map.next_value()?,
_ => {}
}
}
Ok(())
}
}