balanced_vrp_clustering 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/rust/Cargo.lock +2 -2
- data/rust/balanced_vrp_clustering_core/Cargo.toml +1 -1
- data/rust/balanced_vrp_clustering_core/src/clusterer.rs +21 -9
- data/rust/balanced_vrp_clustering_core/src/main.rs +1 -1
- data/rust/balanced_vrp_clustering_core/tests/integration.rs +1 -1
- data/rust/balanced_vrp_clustering_native/Cargo.toml +1 -1
- data/rust/balanced_vrp_clustering_native/src/lib.rs +2 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d40ecf7603eecf4a910d260b048a0995ef083693d86ca1505a8917e307b77f48
|
|
4
|
+
data.tar.gz: 2c341e23ec935338655142e1c91f2af52946c4e0e73b496c114bf3a512dc081a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e77d2b9e506296f6bbda1018fb539d1e63a3b9a4e6b5fab51435fc9bbe875babbc6a22e4ea690c73e9915d15e4285e51f9f4b2e592dfd1544ab2c9cd9231eb0f
|
|
7
|
+
data.tar.gz: fb314cc636d27e43963960fd61fc768a91078b9bf6611bec47c9feaf51bd684a67a6e557a8e268ab2e3ccab50e54dc3a5d86d2ff11c42700ef735004d8fd8e98
|
data/rust/Cargo.lock
CHANGED
|
@@ -78,7 +78,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|
|
78
78
|
|
|
79
79
|
[[package]]
|
|
80
80
|
name = "balanced_vrp_clustering_core"
|
|
81
|
-
version = "0.4.
|
|
81
|
+
version = "0.4.1"
|
|
82
82
|
dependencies = [
|
|
83
83
|
"approx",
|
|
84
84
|
"clap",
|
|
@@ -90,7 +90,7 @@ dependencies = [
|
|
|
90
90
|
|
|
91
91
|
[[package]]
|
|
92
92
|
name = "balanced_vrp_clustering_native"
|
|
93
|
-
version = "0.4.
|
|
93
|
+
version = "0.4.1"
|
|
94
94
|
dependencies = [
|
|
95
95
|
"balanced_vrp_clustering_core",
|
|
96
96
|
"magnus",
|
|
@@ -184,7 +184,7 @@ impl Clusterer {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
pub fn build(mut self) -> BuildOutput {
|
|
187
|
+
pub fn build(mut self) -> Result<BuildOutput, String> {
|
|
188
188
|
let started = Instant::now();
|
|
189
189
|
connect_linked_items(&mut self.items, &self.related_item_indices);
|
|
190
190
|
|
|
@@ -200,7 +200,7 @@ impl Clusterer {
|
|
|
200
200
|
self.strict_limitations = strict;
|
|
201
201
|
self.cut_limit = cut_lim;
|
|
202
202
|
|
|
203
|
-
self.calc_initial_centroids()
|
|
203
|
+
self.calc_initial_centroids()?;
|
|
204
204
|
self.prepare_balancing();
|
|
205
205
|
|
|
206
206
|
self.mark_items_at_top();
|
|
@@ -217,11 +217,11 @@ impl Clusterer {
|
|
|
217
217
|
.map(|c| c.iter().map(|&i| self.items[i].id.clone()).collect())
|
|
218
218
|
.collect();
|
|
219
219
|
|
|
220
|
-
BuildOutput {
|
|
220
|
+
Ok(BuildOutput {
|
|
221
221
|
iterations: self.iteration,
|
|
222
222
|
clusters,
|
|
223
223
|
elapsed_ms: started.elapsed().as_millis() as u64,
|
|
224
|
-
}
|
|
224
|
+
})
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
fn init_unit_symbols(&mut self) {
|
|
@@ -560,7 +560,7 @@ impl Clusterer {
|
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
fn calc_initial_centroids(&mut self) {
|
|
563
|
+
fn calc_initial_centroids(&mut self) -> Result<(), String> {
|
|
564
564
|
self.centroids.clear();
|
|
565
565
|
self.old_centroids_lat_lon.clear();
|
|
566
566
|
let mut remaining_skills: Vec<Vehicle> = self.vehicles.clone();
|
|
@@ -616,14 +616,25 @@ impl Clusterer {
|
|
|
616
616
|
for (ind, &index) in self.centroid_indices.iter().enumerate() {
|
|
617
617
|
let skills = remaining_skills.remove(0);
|
|
618
618
|
let item = &self.items[index];
|
|
619
|
+
let mut linked_conflict: Option<usize> = None;
|
|
619
620
|
do_forall_linked(&self.items, index, |li| {
|
|
620
|
-
if
|
|
621
|
-
|
|
621
|
+
if linked_conflict.is_none() {
|
|
622
|
+
if let Some(used_at) = insert_at_beginning.iter().position(|&x| x == li) {
|
|
623
|
+
linked_conflict = Some(used_at);
|
|
624
|
+
}
|
|
622
625
|
}
|
|
623
626
|
});
|
|
627
|
+
if let Some(used_at) = linked_conflict {
|
|
628
|
+
return Err(format!(
|
|
629
|
+
"Centroid {ind} is initialised with a service which has a linked service that is used to initialise centroid {used_at}"
|
|
630
|
+
));
|
|
631
|
+
}
|
|
624
632
|
let vehicle_centroid = vehicle_as_centroid_props(&skills);
|
|
625
633
|
if !compatible_item_centroid(item, &vehicle_centroid) {
|
|
626
|
-
|
|
634
|
+
// Mirror Ruby populate_centroids ArgumentError message.
|
|
635
|
+
return Err(format!(
|
|
636
|
+
"Centroid {ind} is initialised with an incompatible service -- {index}"
|
|
637
|
+
));
|
|
627
638
|
}
|
|
628
639
|
let mut centroid = vehicle_centroid;
|
|
629
640
|
centroid.lat = item.lat;
|
|
@@ -643,6 +654,7 @@ impl Clusterer {
|
|
|
643
654
|
c.capacity_offence_coeff = 0.0;
|
|
644
655
|
c.route_time = 0.0;
|
|
645
656
|
}
|
|
657
|
+
Ok(())
|
|
646
658
|
}
|
|
647
659
|
|
|
648
660
|
fn move_item_to_front(&mut self, item_idx: usize) {
|
|
@@ -1275,6 +1287,6 @@ fn default_day_skills() -> Vec<String> {
|
|
|
1275
1287
|
.collect()
|
|
1276
1288
|
}
|
|
1277
1289
|
|
|
1278
|
-
pub fn build_from_input(input: &InputConfig) -> BuildOutput {
|
|
1290
|
+
pub fn build_from_input(input: &InputConfig) -> Result<BuildOutput, String> {
|
|
1279
1291
|
Clusterer::from_input(input).build()
|
|
1280
1292
|
}
|
|
@@ -36,7 +36,7 @@ fn main() {
|
|
|
36
36
|
let cli = Cli::parse();
|
|
37
37
|
let json = fs::read_to_string(&cli.input).expect("read input");
|
|
38
38
|
let input: InputConfig = serde_json::from_str(&json).expect("parse input");
|
|
39
|
-
let result = build_from_input(&input);
|
|
39
|
+
let result = build_from_input(&input).unwrap_or_else(|e| panic!("{e}"));
|
|
40
40
|
let out_json = serde_json::to_string_pretty(&result).expect("serialize output");
|
|
41
41
|
if let Some(path) = cli.output {
|
|
42
42
|
fs::write(path, out_json).expect("write output");
|
|
@@ -30,7 +30,7 @@ fn golden_tiny_builds() {
|
|
|
30
30
|
}
|
|
31
31
|
let json = fs::read_to_string(path).expect("read tiny.json");
|
|
32
32
|
let input: InputConfig = serde_json::from_str(&json).expect("parse");
|
|
33
|
-
let output = build_from_input(&input);
|
|
33
|
+
let output = build_from_input(&input).expect("build");
|
|
34
34
|
assert_eq!(output.clusters.len(), 2);
|
|
35
35
|
assert_eq!(
|
|
36
36
|
output.clusters.iter().map(|c| c.len()).sum::<usize>(),
|
|
@@ -32,7 +32,8 @@ fn build_from_json(input: RString) -> Result<RString, Error> {
|
|
|
32
32
|
)
|
|
33
33
|
})?;
|
|
34
34
|
|
|
35
|
-
let output = build_from_input(&config)
|
|
35
|
+
let output = build_from_input(&config)
|
|
36
|
+
.map_err(|e| Error::new(ruby.exception_arg_error(), e))?;
|
|
36
37
|
let out_json = serde_json::to_string(&output).map_err(|e| {
|
|
37
38
|
Error::new(
|
|
38
39
|
ruby.exception_runtime_error(),
|