diff --git a/vrp-scientific/src/common/routing.rs b/vrp-scientific/src/common/routing.rs index d8d43cc22..836945766 100644 --- a/vrp-scientific/src/common/routing.rs +++ b/vrp-scientific/src/common/routing.rs @@ -4,11 +4,12 @@ mod routing_test; use std::sync::Arc; use vrp_core::custom_extra_property; -use vrp_core::models::common::Location; -use vrp_core::models::problem::{create_matrix_transport_cost, MatrixData, TransportCost}; +use vrp_core::models::common::{Distance, Duration, Location, Profile}; +use vrp_core::models::problem::{TransportCost, TravelTime}; +use vrp_core::models::solution::Route; use vrp_core::models::Extras; use vrp_core::prelude::{GenericError, InfoLogger}; -use vrp_core::utils::{Float, Timer}; +use vrp_core::utils::{Float, GenericResult, Timer}; custom_extra_property!(CoordIndex typeof CoordIndex); @@ -41,8 +42,8 @@ impl CoordIndex { || { // NOTE changing to calculating just an upper/lower triangle of the matrix won't improve // performance. I think it is related to the fact that we have to change a memory access - // pattern to less effective. - let matrix_values = self + // pattern to less effective one. + let mut matrix_values = self .locations .iter() .flat_map(|&(x1, y1)| { @@ -60,11 +61,49 @@ impl CoordIndex { }) .collect::>(); - let matrix_data = MatrixData::new(0, None, matrix_values.clone(), matrix_values); + matrix_values.shrink_to_fit(); - create_matrix_transport_cost(vec![matrix_data]) + let transport: Arc = Arc::new(SingleDataTransportCost::new(matrix_values)?); + + Ok(transport) }, |duration| (logger)(format!("fleet index created in {}ms", duration.as_millis()).as_str()), ) } } + +/// Represents a transport cost which has the same distances as durations and single profile. +struct SingleDataTransportCost { + size: usize, + values: Vec, +} + +impl SingleDataTransportCost { + pub fn new(values: Vec) -> GenericResult { + let size = (values.len() as Float).sqrt() as usize; + + if size * size != values.len() { + return Err(GenericError::from(format!("non-square flatten matrix: {} items", values.len()))); + } + + Ok(Self { size, values }) + } +} + +impl TransportCost for SingleDataTransportCost { + fn duration_approx(&self, _: &Profile, from: Location, to: Location) -> Duration { + self.values[from * self.size + to] + } + + fn distance_approx(&self, _: &Profile, from: Location, to: Location) -> Distance { + self.values[from * self.size + to] + } + + fn duration(&self, _: &Route, from: Location, to: Location, _: TravelTime) -> Duration { + self.values[from * self.size + to] + } + + fn distance(&self, _: &Route, from: Location, to: Location, _: TravelTime) -> Distance { + self.values[from * self.size + to] + } +}