vrp_core/models/common/
domain.rs

1#[cfg(test)]
2#[path = "../../../tests/unit/models/common/domain_test.rs"]
3mod domain_test;
4
5use crate::models::common::{Duration, Timestamp};
6use rosomaxa::prelude::Float;
7use std::hash::{Hash, Hasher};
8
9/// Specifies location type.
10pub type Location = usize;
11
12/// Represents a routing profile.
13#[derive(Clone, Debug)]
14pub struct Profile {
15    /// An unique index.
16    pub index: usize,
17    /// A duration scale factor.
18    pub scale: Float,
19}
20
21impl Profile {
22    /// Creates a new instance of `Profile`.
23    pub fn new(index: usize, scale: Option<Float>) -> Profile {
24        Self { index, scale: scale.unwrap_or(1.) }
25    }
26}
27
28impl Default for Profile {
29    fn default() -> Self {
30        Self { index: 0, scale: 1. }
31    }
32}
33
34/// Specifies cost value.
35pub type Cost = Float;
36
37/// Represents a time window.
38#[derive(Clone, Debug, PartialEq)]
39pub struct TimeWindow {
40    /// Start of time window.
41    pub start: Timestamp,
42    /// End of time window.
43    pub end: Timestamp,
44}
45
46/// Represents a time offset.
47#[derive(Clone, Debug, PartialEq)]
48pub struct TimeOffset {
49    /// Offset value to start time.
50    pub start: Timestamp,
51    /// Offset value to end time.
52    pub end: Timestamp,
53}
54
55/// A enum for various time definitions.
56#[derive(Clone, Debug)]
57pub enum TimeSpan {
58    /// A time window variant.
59    Window(TimeWindow),
60    /// A time offset variant.
61    Offset(TimeOffset),
62}
63
64/// Specifies a flexible time interval.
65#[derive(Clone, Debug, Default, PartialEq)]
66pub struct TimeInterval {
67    /// Earliest possible time to start.
68    pub earliest: Option<Timestamp>,
69    /// Latest possible time to stop.
70    pub latest: Option<Timestamp>,
71}
72
73impl TimeWindow {
74    /// Creates a new [`TimeWindow`].
75    pub fn new(start: Timestamp, end: Timestamp) -> Self {
76        Self { start, end }
77    }
78
79    /// Returns unlimited time window.
80    pub fn max() -> Self {
81        Self { start: 0., end: Float::MAX }
82    }
83
84    /// Checks whether time window has intersection with another one (inclusive).
85    pub fn intersects(&self, other: &Self) -> bool {
86        self.start <= other.end && other.start <= self.end
87    }
88
89    /// Checks whether time window has intersection with another one (exclusive).
90    pub fn intersects_exclusive(&self, other: &Self) -> bool {
91        self.start < other.end && other.start < self.end
92    }
93
94    /// Checks whether time window contains given time.
95    pub fn contains(&self, time: Timestamp) -> bool {
96        time >= self.start && time <= self.end
97    }
98
99    /// Returns distance between two time windows.
100    pub fn distance(&self, other: &Self) -> Timestamp {
101        if self.intersects(other) {
102            0.
103        } else {
104            // [other.s other.e] [self.s self.e]
105            if self.start > other.start {
106                self.start - other.end
107            } else {
108                // [self.s self.e] [other.s other.e]
109                other.start - self.end
110            }
111        }
112    }
113
114    /// Returns a new overlapping time window.
115    pub fn overlapping(&self, other: &Self) -> Option<TimeWindow> {
116        if self.intersects(other) {
117            let start = self.start.max(other.start);
118            let end = self.end.min(other.end);
119
120            Some(TimeWindow::new(start, end))
121        } else {
122            None
123        }
124    }
125
126    /// Returns duration of time window.
127    pub fn duration(&self) -> Duration {
128        self.end - self.start
129    }
130}
131
132impl Eq for TimeWindow {}
133
134impl Hash for TimeWindow {
135    fn hash<H: Hasher>(&self, state: &mut H) {
136        let start = self.start.to_bits() as i64;
137        let end = self.end.to_bits() as i64;
138
139        start.hash(state);
140        end.hash(state);
141    }
142}
143
144impl TimeOffset {
145    /// Creates a new [`TimeOffset`].
146    pub fn new(start: Timestamp, end: Timestamp) -> Self {
147        Self { start, end }
148    }
149}
150
151impl TimeSpan {
152    /// Converts given time span into time window.
153    pub fn to_time_window(&self, date: Timestamp) -> TimeWindow {
154        match &self {
155            TimeSpan::Window(window) => window.clone(),
156            TimeSpan::Offset(offset) => TimeWindow::new(date + offset.start, date + offset.end),
157        }
158    }
159
160    /// Checks that this time span intersects with given time windows.
161    pub fn intersects(&self, date: Timestamp, other: &TimeWindow) -> bool {
162        self.to_time_window(date).intersects(other)
163    }
164
165    /// If time span is time window, then return it. Otherwise, return None.
166    pub fn as_time_window(&self) -> Option<TimeWindow> {
167        match &self {
168            TimeSpan::Window(window) => Some(window.clone()),
169            _ => None,
170        }
171    }
172}
173
174impl TimeInterval {
175    /// Converts time interval to time window.
176    pub fn to_time_window(&self) -> TimeWindow {
177        TimeWindow { start: self.earliest.unwrap_or(0.), end: self.latest.unwrap_or(Float::MAX) }
178    }
179}
180
181/// Represents a schedule.
182#[derive(Clone, Debug, PartialEq)]
183pub struct Schedule {
184    /// Arrival time.
185    pub arrival: Timestamp,
186    /// Departure time.
187    pub departure: Timestamp,
188}
189
190impl Schedule {
191    /// Creates a new instance of `Schedule`.
192    pub fn new(arrival: Timestamp, departure: Timestamp) -> Self {
193        Self { arrival, departure }
194    }
195}
196
197impl Eq for Schedule {}
198
199impl Hash for TimeInterval {
200    fn hash<H: Hasher>(&self, state: &mut H) {
201        let earliest = self.earliest.unwrap_or(0.).to_bits() as i64;
202        let latest = self.latest.unwrap_or(Float::MAX).to_bits() as i64;
203
204        earliest.hash(state);
205        latest.hash(state);
206    }
207}
208
209impl Eq for TimeInterval {}