Implement Ford-Fulkerson
This commit is contained in:
@@ -1,13 +1,126 @@
|
|||||||
|
use std::cmp::min;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
|
use eframe::glow::FALSE;
|
||||||
// Ford-Fulkerson mit DFS zur Berechnung des flusserhöhenden Pfades,
|
// Ford-Fulkerson mit DFS zur Berechnung des flusserhöhenden Pfades,
|
||||||
// Edmonds-Karp (also Ford-Fulkerson mit BFS statt DFS),
|
// Edmonds-Karp (also Ford-Fulkerson mit BFS statt DFS),
|
||||||
// Dinic
|
// Dinic
|
||||||
// Goldberg-Tarjan (auch Preflow-Push oder Push-Relabel genannt).
|
// Goldberg-Tarjan (auch Preflow-Push oder Push-Relabel genannt).
|
||||||
use random_generator::MaxflowProblem;
|
use egui_graphs::{Graph, DefaultNodeShape, DefaultEdgeShape};
|
||||||
|
use petgraph::adj::EdgeIndex;
|
||||||
|
use petgraph::data::Build;
|
||||||
|
use petgraph::{Directed, Direction};
|
||||||
|
use petgraph::stable_graph::EdgeReference;
|
||||||
|
use petgraph::visit::{Dfs, EdgeRef, NodeRef, VisitMap, Visitable};
|
||||||
|
use petgraph::stable_graph::{StableGraph, NodeIndex};
|
||||||
|
|
||||||
mod random_generator;
|
use crate::random_generator::MaxflowProblem;
|
||||||
|
use crate::graph::{MaxflowNode, MaxflowEdge};
|
||||||
|
//mod random_generator;
|
||||||
|
|
||||||
impl FordFulkerson {
|
fn available_capacity(edge: EdgeReference<'_, (u64, u64)>) -> u64 {
|
||||||
fn solve(problem: MaxflowProblem) -> ???solution??? {
|
edge.weight().1 - edge.weight().0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the first augmenting path
|
||||||
|
fn dfs(graph: &StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, destination: NodeIndex) -> Option<Vec<NodeIndex>> {
|
||||||
|
let mut visited = graph.visit_map();
|
||||||
|
let mut queue = VecDeque::new();
|
||||||
|
queue.push_back((source, vec![source]));
|
||||||
|
|
||||||
|
// main priority queue
|
||||||
|
while let Some((node, path)) = queue.pop_front() {
|
||||||
|
let outgoing_edges = graph.edges_directed(node, Direction::Outgoing);
|
||||||
|
|
||||||
|
// iterate over all outgoing edges
|
||||||
|
for edge in outgoing_edges {
|
||||||
|
let neighbor = edge.target();
|
||||||
|
if !visited.is_visited(&neighbor) && available_capacity(edge) > 0 {
|
||||||
|
visited.visit(neighbor);
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.push(neighbor);
|
||||||
|
// TODO: is this right?
|
||||||
|
if neighbor == destination {
|
||||||
|
return Some(new_path);
|
||||||
|
} else {
|
||||||
|
queue.push_back((neighbor, new_path));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ford_fulkerson(mut graph: StableGraph<(f32, f32), (u64, u64)>, source: NodeIndex, sink: NodeIndex) -> StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
//let augmenting_path = dfs(graph, source, sink);
|
||||||
|
|
||||||
|
// continue while there are augmenting paths
|
||||||
|
while let Some(path) = dfs(&graph, source, sink) {
|
||||||
|
// find all edges along the path
|
||||||
|
let edges: Vec<petgraph::prelude::EdgeIndex> = path.windows(2).map(|w| graph.find_edge(w[0], w[1]).expect("edge not found")).collect();
|
||||||
|
// find bottleneck capacity along path
|
||||||
|
let increase_value = edges.iter().fold(u64::MAX, |m, x| {
|
||||||
|
let edge = graph.edge_weight(*x).expect("edge index not found");
|
||||||
|
min(m, edge.1 - edge.0)
|
||||||
|
});
|
||||||
|
|
||||||
|
// increase flow with bottleneck capacity along the augmenting path
|
||||||
|
for edge in edges {
|
||||||
|
let weight = graph.edge_weight_mut(edge).expect("edge not found");
|
||||||
|
(*weight).0 += increase_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return graph with augmented flows
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} */
|
||||||
|
|||||||
33
src/graph.rs
Normal file
33
src/graph.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//use egui_graphs::{Node, Edge};
|
||||||
|
use petgraph::graph::{Node, Edge};
|
||||||
|
|
||||||
|
pub trait MaxflowNode {
|
||||||
|
fn visited(&self) -> bool;
|
||||||
|
fn set_visited(&mut self, b: bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait MaxflowEdge {
|
||||||
|
fn remaining_capacity(&self) -> u64;
|
||||||
|
fn set_capacity(&mut self, c: u64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* impl MaxflowNode for Node<bool, (u64, u64)> {
|
||||||
|
fn visited(&self) -> bool {
|
||||||
|
*self.()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_visited(&mut self, b: bool) {
|
||||||
|
let payload = self.payload_mut();
|
||||||
|
*payload = b;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
impl MaxflowEdge for Edge<(u64, u64)> {
|
||||||
|
fn remaining_capacity(&self) -> u64 {
|
||||||
|
self.weight.1 - self.weight.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_capacity(&mut self, c: u64) {
|
||||||
|
self.weight.0 = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/main.rs
21
src/main.rs
@@ -2,15 +2,14 @@ use eframe::{run_native, App, CreationContext, NativeOptions, Frame};
|
|||||||
use egui::{CentralPanel, SidePanel, Context};
|
use egui::{CentralPanel, SidePanel, Context};
|
||||||
use egui_graphs::{GraphView, Graph, SettingsStyle, LayoutRandom, LayoutStateRandom};
|
use egui_graphs::{GraphView, Graph, SettingsStyle, LayoutRandom, LayoutStateRandom};
|
||||||
|
|
||||||
|
use algorithms::ford_fulkerson;
|
||||||
use random_generator::MaxflowProblem;
|
use random_generator::MaxflowProblem;
|
||||||
use algorithms::{ford_fulk
|
|
||||||
//use petgraph::stable_graph::StableGraph;
|
|
||||||
|
|
||||||
mod random_generator;
|
mod random_generator;
|
||||||
mod algorithms;
|
mod algorithms;
|
||||||
|
mod graph;
|
||||||
|
|
||||||
pub struct MaxflowApp {
|
pub struct MaxflowApp {
|
||||||
g: Graph<(), u64>,
|
g: Graph<(f32, f32), (u64, u64)>,
|
||||||
p: MaxflowProblem,
|
p: MaxflowProblem,
|
||||||
node_count: u64,
|
node_count: u64,
|
||||||
max_capacity: u64,
|
max_capacity: u64,
|
||||||
@@ -19,12 +18,13 @@ pub struct MaxflowApp {
|
|||||||
impl MaxflowApp {
|
impl MaxflowApp {
|
||||||
fn new(_: &CreationContext<'_>) -> Self {
|
fn new(_: &CreationContext<'_>) -> Self {
|
||||||
let problem = MaxflowProblem::new(10, 10);
|
let problem = MaxflowProblem::new(10, 10);
|
||||||
Self { g: problem.g.clone(), p: problem, node_count: 10, max_capacity: 5 }
|
Self { g: problem.to_gui_graph(), p: problem, node_count: 10, max_capacity: 5 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App for MaxflowApp {
|
impl App for MaxflowApp {
|
||||||
fn update(&mut self, ctx: &Context, _: &mut Frame) {
|
fn update(&mut self, ctx: &Context, _: &mut Frame) {
|
||||||
|
ctx.set_theme(egui::Theme::Light);
|
||||||
CentralPanel::default().show(ctx, |ui| {
|
CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.add(&mut GraphView::<_, _, _, _, _, _, LayoutStateRandom, LayoutRandom>::new(&mut self.g).with_styles(&SettingsStyle::default().with_labels_always(true)));
|
ui.add(&mut GraphView::<_, _, _, _, _, _, LayoutStateRandom, LayoutRandom>::new(&mut self.g).with_styles(&SettingsStyle::default().with_labels_always(true)));
|
||||||
});
|
});
|
||||||
@@ -32,14 +32,17 @@ impl App for MaxflowApp {
|
|||||||
.min_width(200.)
|
.min_width(200.)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.label("node count");
|
ui.label("node count");
|
||||||
ui.add(egui::DragValue::new(&mut self.node_count).range(1..=1000));
|
ui.add(egui::DragValue::new(&mut self.node_count).range(2..=1000));
|
||||||
ui.label("maximum capacity");
|
ui.label("maximum capacity");
|
||||||
ui.add(egui::DragValue::new(&mut self.max_capacity).range(1..=10));
|
ui.add(egui::DragValue::new(&mut self.max_capacity).range(1..=100));
|
||||||
if ui.button("generate graph").clicked() {
|
if ui.button("generate graph").clicked() {
|
||||||
let problem = random_generator::MaxflowProblem::new(self.node_count, self.max_capacity);
|
self.p = random_generator::MaxflowProblem::new(self.node_count, self.max_capacity);
|
||||||
self.g = problem.g;
|
self.g = self.p.to_gui_graph();
|
||||||
}
|
}
|
||||||
if ui.button("run algorithm").clicked() {
|
if ui.button("run algorithm").clicked() {
|
||||||
|
let max_flow_graph = ford_fulkerson(self.p.g.clone(), self.p.s, self.p.t);
|
||||||
|
self.p = MaxflowProblem::from(max_flow_graph, self.p.s, self.p.t);
|
||||||
|
self.g = self.p.to_gui_graph();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user