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
use crate::format::problem::*;
use crate::format::{CoordIndex, FormatError};
pub struct ValidationContext<'a> {
pub problem: &'a Problem,
pub matrices: Option<&'a Vec<Matrix>>,
coord_index: CoordIndex,
job_index: HashMap<String, Job>,
}
mod common;
use self::common::*;
mod jobs;
use self::jobs::validate_jobs;
mod objectives;
use self::objectives::validate_objectives;
mod vehicles;
use self::vehicles::validate_vehicles;
mod relations;
use self::relations::validate_relations;
mod routing;
use self::routing::validate_routing;
use hashbrown::HashMap;
impl<'a> ValidationContext<'a> {
pub fn new(problem: &'a Problem, matrices: Option<&'a Vec<Matrix>>) -> Self {
Self {
problem,
matrices,
coord_index: CoordIndex::new(problem),
job_index: problem.plan.jobs.iter().map(|job| (job.id.clone(), job.clone())).collect(),
}
}
pub fn validate(&self) -> Result<(), Vec<FormatError>> {
let errors = validate_jobs(&self)
.err()
.into_iter()
.chain(validate_vehicles(&self).err().into_iter())
.chain(validate_objectives(&self).err().into_iter())
.chain(validate_routing(&self).err().into_iter())
.chain(validate_relations(&self).err().into_iter())
.flatten()
.collect::<Vec<_>>();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
fn jobs(&self) -> impl Iterator<Item = &Job> {
self.problem.plan.jobs.iter()
}
fn vehicles(&self) -> impl Iterator<Item = &VehicleType> {
self.problem.fleet.vehicles.iter()
}
fn tasks(&self, job: &'a Job) -> Vec<&'a JobTask> {
job.pickups
.as_ref()
.iter()
.flat_map(|tasks| tasks.iter())
.chain(job.deliveries.as_ref().iter().flat_map(|tasks| tasks.iter()))
.chain(job.replacements.as_ref().iter().flat_map(|tasks| tasks.iter()))
.chain(job.services.as_ref().iter().flat_map(|tasks| tasks.iter()))
.collect()
}
}
fn combine_error_results(results: &[Result<(), FormatError>]) -> Result<(), Vec<FormatError>> {
let errors = results.iter().cloned().flat_map(|result| result.err().into_iter()).collect::<Vec<FormatError>>();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
fn is_reserved_job_id(job_id: &str) -> bool {
job_id == "departure" || job_id == "arrival" || job_id == "break" || job_id == "reload" || job_id == "dispatch"
}