@@ -203,3 +203,127 @@ impl<S: VrpSolution> CrossEntityDistanceMeter<S> for MatrixIntraDistanceMeter {
203203 data. distance_matrix [ visits[ src_pos] ] [ visits[ dst_pos] ] as f64
204204 }
205205}
206+
207+ #[ cfg( test) ]
208+ mod tests {
209+ use super :: * ;
210+
211+ struct TestSolution {
212+ data : Box < ProblemData > ,
213+ routes : Vec < Vec < usize > > ,
214+ }
215+
216+ impl TestSolution {
217+ fn new ( routes : Vec < Vec < usize > > ) -> Self {
218+ Self {
219+ data : Box :: new ( ProblemData {
220+ capacity : 10 ,
221+ depot : 0 ,
222+ demands : vec ! [ 0 , 2 , 3 , 4 ] ,
223+ distance_matrix : vec ! [
224+ vec![ 0 , 5 , 7 , 9 ] ,
225+ vec![ 5 , 0 , 4 , 6 ] ,
226+ vec![ 7 , 4 , 0 , 3 ] ,
227+ vec![ 9 , 6 , 3 , 0 ] ,
228+ ] ,
229+ time_windows : vec ! [ ( 0 , 100 ) , ( 0 , 10 ) , ( 7 , 14 ) , ( 0 , 12 ) ] ,
230+ service_durations : vec ! [ 0 , 2 , 2 , 3 ] ,
231+ travel_times : vec ! [
232+ vec![ 0 , 5 , 7 , 9 ] ,
233+ vec![ 5 , 0 , 4 , 6 ] ,
234+ vec![ 7 , 4 , 0 , 3 ] ,
235+ vec![ 9 , 6 , 3 , 0 ] ,
236+ ] ,
237+ vehicle_departure_time : 0 ,
238+ } ) ,
239+ routes,
240+ }
241+ }
242+ }
243+
244+ impl VrpSolution for TestSolution {
245+ fn vehicle_data_ptr ( & self , _entity_idx : usize ) -> * const ProblemData {
246+ self . data . as_ref ( ) as * const ProblemData
247+ }
248+
249+ fn vehicle_visits ( & self , entity_idx : usize ) -> & [ usize ] {
250+ & self . routes [ entity_idx]
251+ }
252+
253+ fn vehicle_visits_mut ( & mut self , entity_idx : usize ) -> & mut Vec < usize > {
254+ & mut self . routes [ entity_idx]
255+ }
256+
257+ fn vehicle_count ( & self ) -> usize {
258+ self . routes . len ( )
259+ }
260+ }
261+
262+ #[ test]
263+ fn helpers_use_problem_data_from_first_vehicle ( ) {
264+ let solution = TestSolution :: new ( vec ! [ vec![ 1 , 2 ] , vec![ 3 ] ] ) ;
265+
266+ assert_eq ! ( distance( & solution, 1 , 3 ) , 6 ) ;
267+ assert_eq ! ( depot_for_entity( & solution, 1 ) , 0 ) ;
268+ assert_eq ! ( depot_for_cw( & solution) , 0 ) ;
269+ assert_eq ! ( element_load( & solution, 2 ) , 3 ) ;
270+ assert_eq ! ( capacity( & solution) , 10 ) ;
271+ }
272+
273+ #[ test]
274+ fn helpers_handle_empty_fleets ( ) {
275+ let solution = TestSolution :: new ( vec ! [ ] ) ;
276+
277+ assert_eq ! ( distance( & solution, 1 , 2 ) , 0 ) ;
278+ assert_eq ! ( depot_for_entity( & solution, 0 ) , 0 ) ;
279+ assert_eq ! ( depot_for_cw( & solution) , 0 ) ;
280+ assert_eq ! ( element_load( & solution, 1 ) , 0 ) ;
281+ assert_eq ! ( capacity( & solution) , i64 :: MAX ) ;
282+ assert ! ( is_time_feasible( & solution, & [ 1 , 2 ] ) ) ;
283+ assert ! ( is_kopt_feasible( & solution, 0 , & [ 1 , 2 ] ) ) ;
284+ }
285+
286+ #[ test]
287+ fn route_helpers_replace_and_clone_routes ( ) {
288+ let mut solution = TestSolution :: new ( vec ! [ vec![ 1 , 2 ] , vec![ 3 ] ] ) ;
289+
290+ assign_route ( & mut solution, 0 , vec ! [ 2 , 3 ] ) ;
291+ assert_eq ! ( solution. routes[ 0 ] , vec![ 2 , 3 ] ) ;
292+ assert_eq ! ( get_route( & solution, 0 ) , vec![ 2 , 3 ] ) ;
293+
294+ set_route ( & mut solution, 1 , vec ! [ 1 ] ) ;
295+ assert_eq ! ( solution. routes[ 1 ] , vec![ 1 ] ) ;
296+ }
297+
298+ #[ test]
299+ fn time_feasibility_checks_waiting_and_deadlines ( ) {
300+ let solution = TestSolution :: new ( vec ! [ vec![ 1 , 2 ] , vec![ 3 ] ] ) ;
301+
302+ assert ! (
303+ is_time_feasible( & solution, & [ 1 , 2 ] ) ,
304+ "route should wait for customer 2 and still finish in time"
305+ ) ;
306+ assert ! (
307+ !is_time_feasible( & solution, & [ 2 , 3 ] ) ,
308+ "route should miss customer 3's latest end"
309+ ) ;
310+ assert ! ( is_kopt_feasible( & solution, 1 , & [ 1 , 2 ] ) ) ;
311+ }
312+
313+ #[ test]
314+ fn distance_meters_cover_invalid_positions ( ) {
315+ let solution = TestSolution :: new ( vec ! [ vec![ 1 , 2 ] , vec![ 3 ] ] ) ;
316+
317+ assert_eq ! ( MatrixDistanceMeter . distance( & solution, 0 , 0 , 1 , 0 ) , 6.0 ) ;
318+ assert_eq ! (
319+ MatrixIntraDistanceMeter . distance( & solution, 0 , 0 , 0 , 1 ) ,
320+ 4.0
321+ ) ;
322+ assert ! ( MatrixDistanceMeter
323+ . distance( & solution, 0 , 4 , 1 , 0 )
324+ . is_infinite( ) ) ;
325+ assert ! ( MatrixIntraDistanceMeter
326+ . distance( & solution, 0 , 0 , 0 , 4 )
327+ . is_infinite( ) ) ;
328+ }
329+ }
0 commit comments