Fix residual graph generation, minor algorithm refactorings
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
// Dinic
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
// Edmonds-Karp (also Ford-Fulkerson mit BFS statt DFS),
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use petgraph::{stable_graph::{NodeIndex, StableGraph, EdgeReference}, visit::{EdgeRef, VisitMap, Visitable}, Direction};
|
use petgraph::{stable_graph::{NodeIndex, StableGraph, EdgeReference}, visit::{EdgeRef, VisitMap, Visitable}, Direction};
|
||||||
|
|
||||||
fn available_capacity(edge: EdgeReference<'_, (u64, u64)>) -> u64 {
|
fn available_capacity(edge: (u64, u64)) -> u64 {
|
||||||
edge.weight().1 - edge.weight().0
|
edge.1 - edge.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs a depth Breadth First Search (BFS) and returns an augmenting path from source to destination if possible
|
// Runs a depth Breadth First Search (BFS) and returns an augmenting path from source to destination if possible
|
||||||
@@ -21,7 +20,7 @@ fn bfs(graph: &StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, destinati
|
|||||||
|
|
||||||
for edge in outgoing_edges {
|
for edge in outgoing_edges {
|
||||||
let neighbor = edge.target();
|
let neighbor = edge.target();
|
||||||
if !visited.is_visited(&neighbor) && available_capacity(edge) > 0 {
|
if !visited.is_visited(&neighbor) && available_capacity(*edge.weight()) > 0 {
|
||||||
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);
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
// Ford-Fulkerson mit DFS zur Berechnung des flusserhöhenden Pfades,
|
|
||||||
// Edmonds-Karp (also Ford-Fulkerson mit BFS statt DFS),
|
|
||||||
// Dinic
|
|
||||||
// Goldberg-Tarjan (auch Preflow-Push oder Push-Relabel genannt).
|
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use petgraph::{stable_graph::{EdgeReference, NodeIndex, StableGraph}, visit::{EdgeRef, VisitMap, Visitable}, Direction};
|
use petgraph::{stable_graph::{EdgeReference, NodeIndex, StableGraph}, visit::{EdgeRef, VisitMap, Visitable}, Direction};
|
||||||
|
|
||||||
//use crate::random_generator::MaxflowProblem;
|
|
||||||
//mod random_generator;
|
|
||||||
|
|
||||||
fn available_capacity(edge: EdgeReference<'_, (u64, u64)>) -> u64 {
|
fn available_capacity(edge: (u64, u64)) -> u64 {
|
||||||
edge.weight().1 - edge.weight().0
|
edge.1 - edge.0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs a depth Depth First Search (DFS) and returns an augmenting path from source to destination if possible
|
// Runs a depth Depth First Search (DFS) which returns an augmenting path from source to destination if possible
|
||||||
fn dfs(graph: &StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, destination: NodeIndex) -> Option<Vec<NodeIndex>> {
|
fn dfs(graph: &StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, destination: NodeIndex) -> Option<Vec<NodeIndex>> {
|
||||||
let mut visited = graph.visit_map();
|
let mut visited = graph.visit_map();
|
||||||
let mut stack = VecDeque::from([(source, vec![source])]);
|
let mut stack = VecDeque::from([(source, vec![source])]);
|
||||||
@@ -24,10 +18,10 @@ fn dfs(graph: &StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, destinati
|
|||||||
let outgoing_edges = graph.edges_directed(node, Direction::Outgoing);
|
let outgoing_edges = graph.edges_directed(node, Direction::Outgoing);
|
||||||
visited.visit(node);
|
visited.visit(node);
|
||||||
|
|
||||||
// iterate over all outgoing edges
|
// iterate over all outgoing edges & add neighboring nodes to the stack
|
||||||
for edge in outgoing_edges {
|
for edge in outgoing_edges {
|
||||||
let neighbor = edge.target();
|
let neighbor = edge.target();
|
||||||
if !visited.is_visited(&neighbor) && available_capacity(edge) > 0 {
|
if !visited.is_visited(&neighbor) && available_capacity(*edge.weight()) > 0 {
|
||||||
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);
|
||||||
@@ -67,52 +61,3 @@ pub fn ford_fulkerson(mut graph: StableGraph<(f32, f32), (u64, u64)>, source: No
|
|||||||
// return graph with augmented flows
|
// return graph with augmented flows
|
||||||
graph
|
graph
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub struct FordFulkerson {
|
|
||||||
// problem: MaxflowProblem,
|
|
||||||
// flows: Graph<(), u64, Directed, u32, DefaultNodeShape, DefaultEdgeShape>,
|
|
||||||
// alertnatively, use a map from EdgeIndex to flow value
|
|
||||||
//dfs: Dfs<N, VM>,
|
|
||||||
//}
|
|
||||||
|
|
||||||
/* impl FordFulkerson {
|
|
||||||
fn new(problem: MaxflowProblem) -> S/elf {
|
|
||||||
Self { problem: problem, flows: Graph::new(StableGraph::default()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn graph(&mut self) -> &Graph<bool, (u64, u64)> {
|
|
||||||
&self.problem.g
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flows(&mut self) -> &Graph<(), u64> {
|
|
||||||
&self.flows
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dfs(&mut self, ni: NodeIndex) -> Vec<Vec<EdgeIndex>>{
|
|
||||||
// set own node to visited
|
|
||||||
self.problem.g.node_mut(ni).expect("node index not found").set_visited(true);
|
|
||||||
//self.graph().node_mut(ni).expect("node index not found").set_visited(true);
|
|
||||||
|
|
||||||
let augmenting_paths: Vec<Vec<EdgeIndex>> = Vec::new();
|
|
||||||
let neighboring_edges = self.graph().edges_directed(ni, Direction::Outgoing);
|
|
||||||
|
|
||||||
for edge in neighboring_edges {
|
|
||||||
//let neighbor = self.problem.g.node_mut(edge.target()).expect("node index not found");
|
|
||||||
//if neighbor.visited() == false {
|
|
||||||
// println!("{:?}", edge.weight());
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
// iterate over all unvisited! neighbors. for each:
|
|
||||||
// - check if there is capacity left
|
|
||||||
// - if neighbor = target, return path
|
|
||||||
// - else, do dfs starting from neighbor
|
|
||||||
// - if neighbor returns augmenting path add it to own list & prepend own edge
|
|
||||||
// return list of augmenting paths
|
|
||||||
augmenting_paths
|
|
||||||
}
|
|
||||||
|
|
||||||
fn step(&self) {
|
|
||||||
//self.dfs(self.problem.s);
|
|
||||||
}
|
|
||||||
|
|
||||||
} */
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use egui_graphs::{DefaultNodeShape, Graph, default_edge_transform, default_node_transform, to_graph_custom};
|
use egui_graphs::{DefaultNodeShape, Graph, default_edge_transform, default_node_transform, to_graph_custom};
|
||||||
use petgraph::{stable_graph::{StableGraph, NodeIndex}, Directed};
|
use petgraph::{stable_graph::{NodeIndex, StableGraph}, visit::{VisitMap, Visitable}, Directed};
|
||||||
use egui::Pos2;
|
use egui::Pos2;
|
||||||
use crate::layout::CustomEdgeShape;
|
use crate::layout::CustomEdgeShape;
|
||||||
use egui::Color32;
|
use egui::Color32;
|
||||||
@@ -19,9 +19,10 @@ impl ResidualGraph for StableGraph<(f32, f32), (u64, u64)> {
|
|||||||
let (reverse_flow, reverse_capacity) = *res_graph.edge_weight(reverse_edge).expect("reverse edge not found");
|
let (reverse_flow, reverse_capacity) = *res_graph.edge_weight(reverse_edge).expect("reverse edge not found");
|
||||||
// update the forward edge
|
// update the forward edge
|
||||||
// TODO: this seems to overflow in certain cases
|
// TODO: this seems to overflow in certain cases
|
||||||
res_graph.update_edge(source, target, (flow, capacity + reverse_flow - flow));
|
|
||||||
|
res_graph.update_edge(source, target, (flow, capacity + reverse_flow));
|
||||||
// update the reverse edge
|
// update the reverse edge
|
||||||
res_graph.update_edge(target, source, (reverse_flow, reverse_capacity + flow - reverse_flow));
|
//res_graph.update_edge(target, source, (reverse_flow, reverse_capacity + flow));
|
||||||
} else {
|
} else {
|
||||||
// add a residual edge with a flow of 0 if the reverse edge doesn't exist
|
// add a residual edge with a flow of 0 if the reverse edge doesn't exist
|
||||||
res_graph.add_edge(target, source, (0, 0));
|
res_graph.add_edge(target, source, (0, 0));
|
||||||
|
|||||||
Reference in New Issue
Block a user