@@ -6,17 +6,20 @@ use model::config::Config;
6
6
use model:: network:: Network ;
7
7
use model:: vehicle_types:: VehicleTypes ;
8
8
use objective_framework:: Objective ;
9
+ use solution:: path:: Path ;
10
+ use solution:: Schedule ;
11
+
9
12
use rs_graph:: linkedlistgraph:: Node as RsNode ;
10
- use rs_graph:: maxflow:: pushrelabel ;
13
+ use rs_graph:: maxflow:: dinic ;
11
14
use rs_graph:: traits:: Directed ;
12
15
use rs_graph:: Buildable ;
13
16
use rs_graph:: Builder ;
14
17
use rs_graph:: IndexGraph ;
15
18
use rs_graph:: LinkedListGraph ;
16
- use solution:: path:: Path ;
17
- use solution:: Schedule ;
19
+
18
20
use std:: collections:: HashMap ;
19
21
use std:: sync:: Arc ;
22
+ use std:: time;
20
23
21
24
/// Solving the problem by finding a maximum-cardinally matching in a unweighted bipartit graph.
22
25
/// For each service trip, we create two nodes, one on the left and one on the right.
@@ -48,22 +51,24 @@ impl Solver for MaxMatchingSolver {
48
51
}
49
52
50
53
fn solve ( & self ) -> Solution {
54
+ let start_time = time:: Instant :: now ( ) ;
51
55
// TODO decide on which vehicle type (biggest or best fitting)
52
56
// for now: take biggest vehicles (good for a small count, as it might be reused for
53
57
// later trips)
54
58
let vehicle_type = self . vehicles . iter ( ) . last ( ) . unwrap ( ) ;
55
59
let seat_count = self . vehicles . get ( vehicle_type) . unwrap ( ) . seats ( ) ;
56
60
61
+ // tested on bc_201:
62
+ // Dinic on VecGraph: 101 sec
63
+ // Dinic on LinkedListGraph: 23 sec
57
64
let mut builder = LinkedListGraph :: < u32 > :: new_builder ( ) ;
58
- // let mut builder = VecGraph::<u32>::new_builder();
59
65
60
66
let mut left_node_to_trip: HashMap < RsNode , ( NodeId , u8 ) > = HashMap :: new ( ) ;
61
67
let mut trip_to_node: HashMap < ( NodeId , u8 ) , ( RsNode , RsNode ) > = HashMap :: new ( ) ;
62
68
let source = builder. add_node ( ) ;
63
69
let sink = builder. add_node ( ) ;
64
70
let num_service_trips = self . network . service_nodes ( ) . count ( ) ;
65
71
for ( counter, service_trip) in self . network . service_nodes ( ) . enumerate ( ) {
66
- println ! ( "Adding service trip {}/{}" , counter + 1 , num_service_trips) ;
67
72
let demand = self . network . node ( service_trip) . as_service_trip ( ) . demand ( ) ;
68
73
for i in 0 ..demand. div_ceil ( seat_count) as u8 {
69
74
let left_node = builder. add_node ( ) ;
@@ -83,11 +88,32 @@ impl Solver for MaxMatchingSolver {
83
88
}
84
89
} ) ;
85
90
}
91
+ if counter % 100 == 99 {
92
+ println ! (
93
+ " service trips added to matching graph: {}/{}" ,
94
+ counter + 1 ,
95
+ num_service_trips
96
+ ) ;
97
+ }
86
98
}
87
99
88
100
let graph = builder. into_graph ( ) ;
89
101
90
- let ( _, flow, _) = pushrelabel ( & graph, source, sink, |_| 1 ) ;
102
+ println ! (
103
+ "Matching graph loaded (elapsed time for max matching: {:0.2}sec)" ,
104
+ start_time. elapsed( ) . as_secs_f32( )
105
+ ) ;
106
+
107
+ // tested on bc_201:
108
+ // dinic: 23 sec
109
+ // edmondskarp: 2682 sec
110
+ // pushrelabel: 38 sec
111
+ let ( _, flow, _) = dinic ( & graph, source, sink, |_| 1 ) ;
112
+
113
+ println ! (
114
+ "Matching computed (elapsed time for max matching: {:0.2}sec)" ,
115
+ start_time. elapsed( ) . as_secs_f32( )
116
+ ) ;
91
117
92
118
let mut schedule = Schedule :: empty (
93
119
self . vehicles . clone ( ) ,
@@ -146,6 +172,10 @@ impl Solver for MaxMatchingSolver {
146
172
}
147
173
148
174
schedule = schedule. reassign_end_depots_greedily ( ) . unwrap ( ) ;
175
+ println ! (
176
+ "Maximum matching turned into schedule. (max matching running time: {:0.2}sec)" ,
177
+ start_time. elapsed( ) . as_secs_f32( )
178
+ ) ;
149
179
150
180
self . objective . evaluate ( schedule)
151
181
}
0 commit comments