checkpoint 2025-08-27

This commit is contained in:
2025-08-27 00:06:12 +02:00
parent 5e064c73ed
commit 5b67d74b31
11 changed files with 81 additions and 93 deletions

View File

@@ -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: thread '<unnamed>' panicked at src/algorithms/goldberg_tarjan.rs:109:238:
No distance label found No distance label found
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 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)

View File

@@ -82,7 +82,6 @@ impl Dinic {
visited.visit(neighbor); visited.visit(neighbor);
let mut new_path = path.clone(); let mut new_path = path.clone();
new_path.push(neighbor); new_path.push(neighbor);
// TODO: is this right?
if neighbor == self.sink { if neighbor == self.sink {
return Some(new_path); return Some(new_path);
} else { } else {
@@ -113,15 +112,7 @@ impl MaxflowAlgorithm for Dinic {
// increase flow with bottleneck capacity along the augmenting path // increase flow with bottleneck capacity along the augmenting path
for edge in edges { for edge in edges {
// get source and target of edge self.residual_graph.add_flow(edge, bottleneck_capacity);
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;
} }
false false
} else { } else {

View File

@@ -65,15 +65,7 @@ impl MaxflowAlgorithm for EdmondsKarp {
// increase flow with bottleneck capacity along the augmenting path // increase flow with bottleneck capacity along the augmenting path
for edge in edges { for edge in edges {
// get source and target of edge self.residual_graph.add_flow(edge, bottleneck_capacity);
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;
} }
false false
} else { } else {

View File

@@ -37,7 +37,6 @@ impl FordFulkerson {
visited.visit(neighbor); visited.visit(neighbor);
let mut new_path = path.clone(); let mut new_path = path.clone();
new_path.push(neighbor); new_path.push(neighbor);
// TODO: is this right?
if neighbor == self.sink { if neighbor == self.sink {
return Some(new_path); return Some(new_path);
} else { } else {
@@ -65,15 +64,7 @@ impl MaxflowAlgorithm for FordFulkerson {
// increase flow with bottleneck capacity along the augmenting path // increase flow with bottleneck capacity along the augmenting path
for edge in edges { for edge in edges {
// get source and target of edge self.residual_graph.add_flow(edge, bottleneck_capacity);
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;
} }
false false
} else { } else {

View File

@@ -80,8 +80,6 @@ pub trait FlowGraph {
fn valid_flow(&self, source: NodeIndex, sink: NodeIndex) -> bool; 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 total_flow(&self, source: NodeIndex, sink: NodeIndex) -> u64;
fn available_capacity(&self, edge: EdgeIndex) -> u64; fn available_capacity(&self, edge: EdgeIndex) -> u64;
@@ -198,22 +196,6 @@ impl FlowGraph for StableGraph<(f32, f32), (u64, u64)> {
true 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 { 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 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(); let incoming_flows_source: u64 = self.edges_directed(source, Direction::Incoming).map(|e| e.weight().0).sum();

View File

@@ -30,9 +30,9 @@ impl<E: Clone> From<EdgeProps<E>> for CustomEdgeShape {
label_text: props.label, label_text: props.label,
width: 1., width: 1.,
tip_size: 10., tip_size: 6.,
tip_angle: std::f32::consts::TAU / 30., tip_angle: std::f32::consts::TAU / 20.,
curve_size: 15., curve_size: 10.,
loop_size: 3., loop_size: 3.,
} }
} }

View File

@@ -167,7 +167,6 @@ impl App for MaxflowApp {
ui.add(egui::DragValue::new(&mut self.node_count).range(2..=50)); ui.add(egui::DragValue::new(&mut self.node_count).range(2..=50));
ui.label("maximum capacity"); ui.label("maximum capacity");
ui.add(egui::DragValue::new(&mut self.max_capacity).range(1..=100)); 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() { if ui.button("generate graph").clicked() {
self.problem = random_generator::MaxflowProblem::new_planar_graph(self.node_count, self.max_capacity); self.problem = random_generator::MaxflowProblem::new_planar_graph(self.node_count, self.max_capacity);
self.reset_state(); self.reset_state();

View File

@@ -26,7 +26,7 @@ impl MaxflowProblem {
// check if node is too close to another node (distance < 40) // check if node is too close to another node (distance < 40)
let mut too_close = true; let mut too_close = true;
let (mut x, mut y) = (0.0, 0.0); 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 { while too_close {
too_close = false; too_close = false;
x = rng.gen_range(0.0..=400.0); x = rng.gen_range(0.0..=400.0);
@@ -140,9 +140,4 @@ impl MaxflowProblem {
_ => false _ => 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!();
}
} }

View File

@@ -12,13 +12,7 @@ fn solve_problem_all_algos(problem: &MaxflowProblem) -> (f64, f64, f64, f64) {
let mut durations = vec![0.0; 4]; let mut durations = vec![0.0; 4];
for (i,a) in instances.iter_mut().enumerate() { for (i,a) in instances.iter_mut().enumerate() {
let now = Instant::now(); let now = Instant::now();
match a {
MaxflowAlgorithmEnum::GoldbergTarjan(_) => { a.run(); },
_ => {
a.run(); a.run();
}
}
//a.run();
durations[i] = now.elapsed().as_secs_f64(); durations[i] = now.elapsed().as_secs_f64();
// check if the flow is valid // 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(); let mut response = String::new();
for (problem_count, nodes, capacity) in test_tuples { 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(); response += format!("=== Testing with problem_count={}, nodes={}, capacity={}\n", problem_count, nodes, capacity).as_str();
let mut problems: Vec<_> = Vec::new(); let mut problems: Vec<_> = Vec::new();
for _ in 0..problem_count { for _ in 0..problem_count {
@@ -60,10 +55,11 @@ pub fn run_small_tests() -> String {
let test_tuples = [ let test_tuples = [
// (number of problems, number of nodes, max. capacity) // (number of problems, number of nodes, max. capacity)
(10, 10, 10), (10, 10, 10),
(10, 10, 100),
(10, 50, 10),
(10, 50, 100),
(10, 100, 10), (10, 100, 10),
(10, 100, 100), (10, 100, 100)
(10, 200, 10),
(10, 200, 100)
]; ];
return run_tests(test_tuples.into()); return run_tests(test_tuples.into());
} }
@@ -74,13 +70,12 @@ pub fn run_large_tests() -> String {
(10, 100, 10), (10, 100, 10),
(10, 100, 100), (10, 100, 100),
(10, 100, 1000), (10, 100, 1000),
(10, 500, 10), (10, 200, 10),
(10, 500, 100), (10, 200, 100),
(10, 500, 1000), (10, 200, 1000),
(10, 1000, 10), (10, 300, 10),
(10, 1000, 100), (10, 300, 100),
(10, 1000, 1000), (10, 300, 1000)
(10, 10000, 10)
]; ];
return run_tests(test_tuples.into()); return run_tests(test_tuples.into());
} }

54
tests.txt Normal file
View 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

View File

@@ -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, three, (0,5)); // changed capacity to 5 to enforce a single optimal solution
g.add_edge(four, t, (0,10)); 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(); let mut m = g.clone();
m.update_edge(s, one, (10, 10)); m.update_edge(s, one, (10, 10));
m.update_edge(s, two, (9, 10)); m.update_edge(s, two, (9, 10));