Skip to content

Commit 180f714

Browse files
committed
some tests for the matching algorithm. LinkedListGraph with Dinic is the winner.
1 parent f342096 commit 180f714

File tree

1 file changed

+36
-6
lines changed

1 file changed

+36
-6
lines changed

solver/src/max_matching_solver.rs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@ use model::config::Config;
66
use model::network::Network;
77
use model::vehicle_types::VehicleTypes;
88
use objective_framework::Objective;
9+
use solution::path::Path;
10+
use solution::Schedule;
11+
912
use rs_graph::linkedlistgraph::Node as RsNode;
10-
use rs_graph::maxflow::pushrelabel;
13+
use rs_graph::maxflow::dinic;
1114
use rs_graph::traits::Directed;
1215
use rs_graph::Buildable;
1316
use rs_graph::Builder;
1417
use rs_graph::IndexGraph;
1518
use rs_graph::LinkedListGraph;
16-
use solution::path::Path;
17-
use solution::Schedule;
19+
1820
use std::collections::HashMap;
1921
use std::sync::Arc;
22+
use std::time;
2023

2124
/// Solving the problem by finding a maximum-cardinally matching in a unweighted bipartit graph.
2225
/// 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 {
4851
}
4952

5053
fn solve(&self) -> Solution {
54+
let start_time = time::Instant::now();
5155
// TODO decide on which vehicle type (biggest or best fitting)
5256
// for now: take biggest vehicles (good for a small count, as it might be reused for
5357
// later trips)
5458
let vehicle_type = self.vehicles.iter().last().unwrap();
5559
let seat_count = self.vehicles.get(vehicle_type).unwrap().seats();
5660

61+
// tested on bc_201:
62+
// Dinic on VecGraph: 101 sec
63+
// Dinic on LinkedListGraph: 23 sec
5764
let mut builder = LinkedListGraph::<u32>::new_builder();
58-
// let mut builder = VecGraph::<u32>::new_builder();
5965

6066
let mut left_node_to_trip: HashMap<RsNode, (NodeId, u8)> = HashMap::new();
6167
let mut trip_to_node: HashMap<(NodeId, u8), (RsNode, RsNode)> = HashMap::new();
6268
let source = builder.add_node();
6369
let sink = builder.add_node();
6470
let num_service_trips = self.network.service_nodes().count();
6571
for (counter, service_trip) in self.network.service_nodes().enumerate() {
66-
println!("Adding service trip {}/{}", counter + 1, num_service_trips);
6772
let demand = self.network.node(service_trip).as_service_trip().demand();
6873
for i in 0..demand.div_ceil(seat_count) as u8 {
6974
let left_node = builder.add_node();
@@ -83,11 +88,32 @@ impl Solver for MaxMatchingSolver {
8388
}
8489
});
8590
}
91+
if counter % 100 == 99 {
92+
println!(
93+
" service trips added to matching graph: {}/{}",
94+
counter + 1,
95+
num_service_trips
96+
);
97+
}
8698
}
8799

88100
let graph = builder.into_graph();
89101

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+
);
91117

92118
let mut schedule = Schedule::empty(
93119
self.vehicles.clone(),
@@ -146,6 +172,10 @@ impl Solver for MaxMatchingSolver {
146172
}
147173

148174
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+
);
149179

150180
self.objective.evaluate(schedule)
151181
}

0 commit comments

Comments
 (0)