checkpoint 2025-08-27
This commit is contained in:
@@ -92,3 +92,10 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
thread '<unnamed>' panicked at src/algorithms/goldberg_tarjan.rs:109:238:
|
||||
No distance label found
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
||||
# Code erklären
|
||||
|
||||
- Graph generieren (random_generator.rs)
|
||||
- GUI, Custom Layout (main.rs, layout.rs)
|
||||
- Graph Hilfsfunktionen (graph.rs)
|
||||
- Algorithmen (ford_fulkerson.rs, edmonds_karp.rs, dinic.rs, goldberg_tarjan.rs)
|
||||
@@ -82,7 +82,6 @@ impl Dinic {
|
||||
visited.visit(neighbor);
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(neighbor);
|
||||
// TODO: is this right?
|
||||
if neighbor == self.sink {
|
||||
return Some(new_path);
|
||||
} else {
|
||||
@@ -113,15 +112,7 @@ impl MaxflowAlgorithm for Dinic {
|
||||
|
||||
// increase flow with bottleneck capacity along the augmenting path
|
||||
for edge in edges {
|
||||
// get source and target of edge
|
||||
let (source, target) = self.residual_graph.edge_endpoints(edge).expect("edge not connected");
|
||||
// increase flow of the forward edge with the calculated bottleneck value
|
||||
let weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(edge).expect("edge not found");
|
||||
(*weight).0 += bottleneck_capacity;
|
||||
// increase capacity of the residual edge of the with the calculated bottleneck value
|
||||
let residual_edge = self.residual_graph.find_edge(target, source).expect("residual edge not found");
|
||||
let residual_weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(residual_edge).expect("edge not found");
|
||||
(*residual_weight).1 += bottleneck_capacity;
|
||||
self.residual_graph.add_flow(edge, bottleneck_capacity);
|
||||
}
|
||||
false
|
||||
} else {
|
||||
|
||||
@@ -65,15 +65,7 @@ impl MaxflowAlgorithm for EdmondsKarp {
|
||||
|
||||
// increase flow with bottleneck capacity along the augmenting path
|
||||
for edge in edges {
|
||||
// get source and target of edge
|
||||
let (source, target) = self.residual_graph.edge_endpoints(edge).expect("edge not connected");
|
||||
// increase flow of the forward edge with the calculated bottleneck value
|
||||
let weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(edge).expect("edge not found");
|
||||
(*weight).0 += bottleneck_capacity;
|
||||
// increase capacity of the residual edge of the with the calculated bottleneck value
|
||||
let residual_edge = self.residual_graph.find_edge(target, source).expect("residual edge not found");
|
||||
let residual_weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(residual_edge).expect("edge not found");
|
||||
(*residual_weight).1 += bottleneck_capacity;
|
||||
self.residual_graph.add_flow(edge, bottleneck_capacity);
|
||||
}
|
||||
false
|
||||
} else {
|
||||
|
||||
@@ -37,7 +37,6 @@ impl FordFulkerson {
|
||||
visited.visit(neighbor);
|
||||
let mut new_path = path.clone();
|
||||
new_path.push(neighbor);
|
||||
// TODO: is this right?
|
||||
if neighbor == self.sink {
|
||||
return Some(new_path);
|
||||
} else {
|
||||
@@ -65,15 +64,7 @@ impl MaxflowAlgorithm for FordFulkerson {
|
||||
|
||||
// increase flow with bottleneck capacity along the augmenting path
|
||||
for edge in edges {
|
||||
// get source and target of edge
|
||||
let (source, target) = self.residual_graph.edge_endpoints(edge).expect("edge not connected");
|
||||
// increase flow of the forward edge with the calculated bottleneck value
|
||||
let weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(edge).expect("edge not found");
|
||||
(*weight).0 += bottleneck_capacity;
|
||||
// increase capacity of the residual edge of the with the calculated bottleneck value
|
||||
let residual_edge = self.residual_graph.find_edge(target, source).expect("residual edge not found");
|
||||
let residual_weight: &mut (u64, u64) = self.residual_graph.edge_weight_mut(residual_edge).expect("edge not found");
|
||||
(*residual_weight).1 += bottleneck_capacity;
|
||||
self.residual_graph.add_flow(edge, bottleneck_capacity);
|
||||
}
|
||||
false
|
||||
} else {
|
||||
|
||||
18
src/graph.rs
18
src/graph.rs
@@ -80,8 +80,6 @@ pub trait FlowGraph {
|
||||
|
||||
fn valid_flow(&self, source: NodeIndex, sink: NodeIndex) -> bool;
|
||||
|
||||
fn saturated_cut(&self, source: NodeIndex, sink: NodeIndex) -> bool;
|
||||
|
||||
fn total_flow(&self, source: NodeIndex, sink: NodeIndex) -> u64;
|
||||
|
||||
fn available_capacity(&self, edge: EdgeIndex) -> u64;
|
||||
@@ -198,22 +196,6 @@ impl FlowGraph for StableGraph<(f32, f32), (u64, u64)> {
|
||||
true
|
||||
}
|
||||
|
||||
// checks if there exists a saturated cut in the graph (a bip)
|
||||
fn saturated_cut(&self, source: NodeIndex, sink: NodeIndex) -> bool {
|
||||
let mut s = HashSet::new();
|
||||
let mut t = HashSet::new();
|
||||
|
||||
for node in self.node_indices().into_iter().collect::<Vec<_>>() {
|
||||
if has_path_connecting(self, source, node, None) {
|
||||
s.insert(node);
|
||||
} else {
|
||||
t.insert(node);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn total_flow(&self, source: NodeIndex, sink: NodeIndex) -> u64 {
|
||||
let outgoing_flows_source: u64 = self.edges_directed(source, Direction::Outgoing).map(|e| e.weight().0).sum();
|
||||
let incoming_flows_source: u64 = self.edges_directed(source, Direction::Incoming).map(|e| e.weight().0).sum();
|
||||
|
||||
@@ -30,9 +30,9 @@ impl<E: Clone> From<EdgeProps<E>> for CustomEdgeShape {
|
||||
label_text: props.label,
|
||||
|
||||
width: 1.,
|
||||
tip_size: 10.,
|
||||
tip_angle: std::f32::consts::TAU / 30.,
|
||||
curve_size: 15.,
|
||||
tip_size: 6.,
|
||||
tip_angle: std::f32::consts::TAU / 20.,
|
||||
curve_size: 10.,
|
||||
loop_size: 3.,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,6 @@ impl App for MaxflowApp {
|
||||
ui.add(egui::DragValue::new(&mut self.node_count).range(2..=50));
|
||||
ui.label("maximum capacity");
|
||||
ui.add(egui::DragValue::new(&mut self.max_capacity).range(1..=100));
|
||||
// TODO: add generation strategy (random, pseudo-random)
|
||||
if ui.button("generate graph").clicked() {
|
||||
self.problem = random_generator::MaxflowProblem::new_planar_graph(self.node_count, self.max_capacity);
|
||||
self.reset_state();
|
||||
|
||||
@@ -26,7 +26,7 @@ impl MaxflowProblem {
|
||||
// check if node is too close to another node (distance < 40)
|
||||
let mut too_close = true;
|
||||
let (mut x, mut y) = (0.0, 0.0);
|
||||
// this is a poor attempt at modeling a do..while look in Rust
|
||||
// this is a poor attempt at modeling a do..while loop in Rust
|
||||
while too_close {
|
||||
too_close = false;
|
||||
x = rng.gen_range(0.0..=400.0);
|
||||
@@ -140,9 +140,4 @@ impl MaxflowProblem {
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn intersects_poly(a: (f32, f32), b: (f32, f32), c: (f32, f32), d: (f32, f32)) -> bool {
|
||||
let mut intersects = Self::intersects(a, b, c, d);
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,7 @@ fn solve_problem_all_algos(problem: &MaxflowProblem) -> (f64, f64, f64, f64) {
|
||||
let mut durations = vec![0.0; 4];
|
||||
for (i,a) in instances.iter_mut().enumerate() {
|
||||
let now = Instant::now();
|
||||
match a {
|
||||
MaxflowAlgorithmEnum::GoldbergTarjan(_) => { a.run(); },
|
||||
_ => {
|
||||
a.run();
|
||||
}
|
||||
}
|
||||
//a.run();
|
||||
durations[i] = now.elapsed().as_secs_f64();
|
||||
|
||||
// check if the flow is valid
|
||||
@@ -36,6 +30,7 @@ fn run_tests(test_tuples: Vec<(u64, u64, u64)>) -> String {
|
||||
let mut response = String::new();
|
||||
|
||||
for (problem_count, nodes, capacity) in test_tuples {
|
||||
println!("Running test: {} times, {} nodes, {} capacity", problem_count, nodes, capacity);
|
||||
response += format!("=== Testing with problem_count={}, nodes={}, capacity={}\n", problem_count, nodes, capacity).as_str();
|
||||
let mut problems: Vec<_> = Vec::new();
|
||||
for _ in 0..problem_count {
|
||||
@@ -60,10 +55,11 @@ pub fn run_small_tests() -> String {
|
||||
let test_tuples = [
|
||||
// (number of problems, number of nodes, max. capacity)
|
||||
(10, 10, 10),
|
||||
(10, 10, 100),
|
||||
(10, 50, 10),
|
||||
(10, 50, 100),
|
||||
(10, 100, 10),
|
||||
(10, 100, 100),
|
||||
(10, 200, 10),
|
||||
(10, 200, 100)
|
||||
(10, 100, 100)
|
||||
];
|
||||
return run_tests(test_tuples.into());
|
||||
}
|
||||
@@ -74,13 +70,12 @@ pub fn run_large_tests() -> String {
|
||||
(10, 100, 10),
|
||||
(10, 100, 100),
|
||||
(10, 100, 1000),
|
||||
(10, 500, 10),
|
||||
(10, 500, 100),
|
||||
(10, 500, 1000),
|
||||
(10, 1000, 10),
|
||||
(10, 1000, 100),
|
||||
(10, 1000, 1000),
|
||||
(10, 10000, 10)
|
||||
(10, 200, 10),
|
||||
(10, 200, 100),
|
||||
(10, 200, 1000),
|
||||
(10, 300, 10),
|
||||
(10, 300, 100),
|
||||
(10, 300, 1000)
|
||||
];
|
||||
return run_tests(test_tuples.into());
|
||||
}
|
||||
54
tests.txt
Normal file
54
tests.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
=== Testing with problem_count=10, nodes=100, capacity=10
|
||||
Ford-Fulkerson: 0.00019723s
|
||||
Edmonds-Karp: 0.00017104s
|
||||
Dinic: 0.00114540s
|
||||
Goldberg-Tarjan: 0.11118784s
|
||||
|
||||
=== Testing with problem_count=10, nodes=100, capacity=100
|
||||
Ford-Fulkerson: 0.00044646s
|
||||
Edmonds-Karp: 0.00030087s
|
||||
Dinic: 0.00212037s
|
||||
Goldberg-Tarjan: 0.15394399s
|
||||
|
||||
=== Testing with problem_count=10, nodes=100, capacity=1000
|
||||
Ford-Fulkerson: 0.00028169s
|
||||
Edmonds-Karp: 0.00017956s
|
||||
Dinic: 0.00128019s
|
||||
Goldberg-Tarjan: 0.11455003s
|
||||
|
||||
=== Testing with problem_count=10, nodes=200, capacity=10
|
||||
Ford-Fulkerson: 0.00057035s
|
||||
Edmonds-Karp: 0.00042638s
|
||||
Dinic: 0.00270890s
|
||||
Goldberg-Tarjan: 1.70483265s
|
||||
|
||||
=== Testing with problem_count=10, nodes=200, capacity=100
|
||||
Ford-Fulkerson: 0.00121046s
|
||||
Edmonds-Karp: 0.00045426s
|
||||
Dinic: 0.00301752s
|
||||
Goldberg-Tarjan: 1.48397911s
|
||||
|
||||
=== Testing with problem_count=10, nodes=200, capacity=1000
|
||||
Ford-Fulkerson: 0.00183244s
|
||||
Edmonds-Karp: 0.00062984s
|
||||
Dinic: 0.00411386s
|
||||
Goldberg-Tarjan: 1.49089764s
|
||||
|
||||
=== Testing with problem_count=10, nodes=300, capacity=10
|
||||
Ford-Fulkerson: 0.00086230s
|
||||
Edmonds-Karp: 0.00071712s
|
||||
Dinic: 0.00423448s
|
||||
Goldberg-Tarjan: 5.84010118s
|
||||
|
||||
=== Testing with problem_count=10, nodes=300, capacity=100
|
||||
Ford-Fulkerson: 0.00164213s
|
||||
Edmonds-Karp: 0.00040957s
|
||||
Dinic: 0.00322493s
|
||||
Goldberg-Tarjan: 1.97116912s
|
||||
|
||||
=== Testing with problem_count=10, nodes=300, capacity=1000
|
||||
Ford-Fulkerson: 0.00362413s
|
||||
Edmonds-Karp: 0.00094858s
|
||||
Dinic: 0.00600265s
|
||||
Goldberg-Tarjan: 5.16341617s
|
||||
|
||||
@@ -23,24 +23,6 @@ fn generate_small_maxflow_example() -> (StableGraph<(f32, f32), (u64, u64)>, Sta
|
||||
g.add_edge(four, three, (0,5)); // changed capacity to 5 to enforce a single optimal solution
|
||||
g.add_edge(four, t, (0,10));
|
||||
|
||||
// TODO:
|
||||
// let mut m: StableGraph<(f32, f32), (u64, u64)> = StableGraph::new();
|
||||
// let s = m.add_node((0., 5.));
|
||||
// let one = m.add_node((10., 0.));
|
||||
// let two = m.add_node((10., 10.));
|
||||
// let three = m.add_node((20., 0.));
|
||||
// let four = m.add_node((20., 10.));
|
||||
// let t = m.add_node((30., 5.));
|
||||
// m.add_edge(s, one, (10, 10));
|
||||
// m.add_edge(s, two, (9, 10));
|
||||
// m.add_edge(one, three, (4, 4));
|
||||
// m.add_edge(one, four, (6, 8));
|
||||
// m.add_edge(one, two, (0,2));
|
||||
// m.add_edge(two, four, (9,9));
|
||||
// m.add_edge(three, t, (9,10));
|
||||
// m.add_edge(four, three, (5,6));
|
||||
// m.add_edge(four, t, (10,10));
|
||||
|
||||
let mut m = g.clone();
|
||||
m.update_edge(s, one, (10, 10));
|
||||
m.update_edge(s, two, (9, 10));
|
||||
|
||||
Reference in New Issue
Block a user