Skip to main content

solverforge_cvrp/
problem_data.rs

1/// Matrix sentinel for a leg that cannot be traversed.
2///
3/// Stock CVRP helpers treat this as non-evaluable route-local travel and as a
4/// very large construction distance. It is intentionally the same sentinel used
5/// by `solverforge-maps` road-network matrices.
6pub const UNREACHABLE: i64 = i64::MAX;
7
8pub(crate) const MAX_SAFE_LEG_COST: i64 = i64::MAX / 4;
9
10/// Immutable problem data shared by all vehicles.
11///
12/// Stored via raw pointer in each vehicle so the framework can clone vehicles
13/// freely during local search without copying matrices.
14#[derive(Clone, Debug)]
15pub struct ProblemData {
16    pub capacity: i64,
17    pub depot: usize,
18    pub demands: Vec<i32>,
19    pub distance_matrix: Vec<Vec<i64>>,
20    pub time_windows: Vec<(i64, i64)>,
21    pub service_durations: Vec<i64>,
22    pub travel_times: Vec<Vec<i64>>,
23    pub vehicle_departure_time: i64,
24}
25
26impl ProblemData {
27    #[inline]
28    pub(crate) fn distance_cost(&self, from: usize, to: usize) -> i64 {
29        self.finite_matrix_value(&self.distance_matrix, from, to)
30            .unwrap_or(MAX_SAFE_LEG_COST)
31    }
32
33    #[inline]
34    pub(crate) fn finite_distance(&self, from: usize, to: usize) -> Option<i64> {
35        self.finite_matrix_value(&self.distance_matrix, from, to)
36    }
37
38    #[inline]
39    pub(crate) fn travel_time(&self, from: usize, to: usize) -> Option<i64> {
40        self.finite_matrix_value(&self.travel_times, from, to)
41    }
42
43    #[inline]
44    fn finite_matrix_value(&self, matrix: &[Vec<i64>], from: usize, to: usize) -> Option<i64> {
45        let value = matrix.get(from)?.get(to).copied()?;
46        (value >= 0 && value != UNREACHABLE).then_some(value)
47    }
48}