Skip to main content

vrp_pragmatic/format/problem/
mod.rs

1//! Specifies logic to read problem and routing matrix from json input.
2
3use super::*;
4use crate::parse_time;
5use std::io::{BufReader, Read};
6use std::sync::Arc;
7use vrp_core::models::common::TimeWindow;
8use vrp_core::models::Lock;
9use vrp_core::prelude::{ActivityCost, Fleet as CoreFleet, Jobs as CoreJobs, TransportCost};
10use vrp_core::utils::*;
11
12pub(crate) type ApiProblem = Problem;
13
14mod model;
15pub use self::model::*;
16
17#[cfg(test)]
18#[path = "../../../tests/unit/format/problem/reader_test.rs"]
19mod reader_test;
20
21mod clustering_reader;
22
23mod fleet_reader;
24pub use self::fleet_reader::create_approx_matrices;
25
26mod goal_reader;
27mod job_reader;
28
29mod problem_reader;
30use self::problem_reader::{map_to_problem_with_approx, map_to_problem_with_matrices};
31
32/// Reads specific problem definition from various sources.
33pub trait PragmaticProblem {
34    /// Reads problem defined in pragmatic format.
35    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError>;
36}
37
38impl<R: Read> PragmaticProblem for (BufReader<R>, Vec<BufReader<R>>) {
39    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
40        let problem = deserialize_problem(self.0)?;
41
42        let mut matrices = vec![];
43        for matrix in self.1 {
44            matrices.push(deserialize_matrix(matrix)?);
45        }
46
47        map_to_problem_with_matrices(problem, matrices)
48    }
49}
50
51impl<R: Read> PragmaticProblem for BufReader<R> {
52    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
53        let problem = deserialize_problem(self)?;
54
55        map_to_problem_with_approx(problem)
56    }
57}
58
59impl PragmaticProblem for (String, Vec<String>) {
60    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
61        let problem = deserialize_problem(BufReader::new(self.0.as_bytes()))?;
62
63        let mut matrices = vec![];
64        for matrix in self.1 {
65            matrices.push(deserialize_matrix(BufReader::new(matrix.as_bytes()))?);
66        }
67
68        map_to_problem_with_matrices(problem, matrices)
69    }
70}
71
72impl PragmaticProblem for String {
73    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
74        let problem = deserialize_problem(BufReader::new(self.as_bytes()))?;
75
76        map_to_problem_with_approx(problem)
77    }
78}
79
80impl PragmaticProblem for (ApiProblem, Vec<Matrix>) {
81    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
82        map_to_problem_with_matrices(self.0, self.1)
83    }
84}
85
86impl PragmaticProblem for ApiProblem {
87    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
88        map_to_problem_with_approx(self)
89    }
90}
91
92impl PragmaticProblem for (ApiProblem, Option<Vec<Matrix>>) {
93    fn read_pragmatic(self) -> Result<CoreProblem, MultiFormatError> {
94        if let Some(matrices) = self.1 {
95            (self.0, matrices).read_pragmatic()
96        } else {
97            self.0.read_pragmatic()
98        }
99    }
100}
101
102/// Keeps track of problem properties (e.g. features).
103struct ProblemProperties {
104    has_multi_dimen_capacity: bool,
105    has_breaks: bool,
106    has_skills: bool,
107    has_unreachable_locations: bool,
108    has_reloads: bool,
109    has_recharges: bool,
110    has_order: bool,
111    has_group: bool,
112    has_value: bool,
113    has_compatibility: bool,
114    has_tour_size_limits: bool,
115    has_tour_travel_limits: bool,
116}
117
118/// Keeps track of materialized problem building blocks.
119struct ProblemBlocks {
120    jobs: Arc<CoreJobs>,
121    fleet: Arc<CoreFleet>,
122    job_index: Option<Arc<JobIndex>>,
123    transport: Arc<dyn TransportCost>,
124    activity: Arc<dyn ActivityCost>,
125    locks: Vec<Arc<Lock>>,
126    reserved_times_index: ReservedTimesIndex,
127}
128
129fn parse_time_window(tw: &[String]) -> TimeWindow {
130    assert_eq!(tw.len(), 2);
131    TimeWindow::new(parse_time(tw.first().unwrap()), parse_time(tw.last().unwrap()))
132}