add traits for stable graph: gui graph conversion, residual graph, empty flow filter
This commit is contained in:
80
src/graph.rs
Normal file
80
src/graph.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use egui_graphs::{DefaultNodeShape, Graph, default_edge_transform, default_node_transform, to_graph_custom};
|
||||||
|
use petgraph::{stable_graph::{StableGraph, NodeIndex}, Directed};
|
||||||
|
use egui::Pos2;
|
||||||
|
use crate::layout::CustomEdgeShape;
|
||||||
|
use egui::Color32;
|
||||||
|
|
||||||
|
pub trait ResidualGraph {
|
||||||
|
fn residual(&self) -> StableGraph<(f32, f32), (u64, u64)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResidualGraph for StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
fn residual(&self) -> StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
let mut res_graph = self.clone();
|
||||||
|
|
||||||
|
for edge in res_graph.edge_indices().map(|e| e).collect::<Vec<_>>() {
|
||||||
|
let (source, target) = res_graph.edge_endpoints(edge).expect("edge not connected");
|
||||||
|
if let Some(reverse_edge) = res_graph.find_edge(target, source) {
|
||||||
|
let (flow, capacity) = *res_graph.edge_weight(edge).expect("forward edge not found");
|
||||||
|
let (reverse_flow, reverse_capacity) = *res_graph.edge_weight(reverse_edge).expect("reverse edge not found");
|
||||||
|
// update the forward edge
|
||||||
|
// TODO: this seems to overflow in certain cases
|
||||||
|
res_graph.update_edge(source, target, (flow, capacity + reverse_flow - flow));
|
||||||
|
// update the reverse edge
|
||||||
|
res_graph.update_edge(target, source, (reverse_flow, reverse_capacity + flow - reverse_flow));
|
||||||
|
} else {
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait GuiGraph {
|
||||||
|
fn to_gui_graph(&self, s: NodeIndex, t: NodeIndex, active_flows_only: bool) -> Graph<(f32, f32), (u64, u64), Directed, u32, DefaultNodeShape, CustomEdgeShape>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GuiGraph for StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
fn to_gui_graph(&self, s: NodeIndex, t: NodeIndex, active_flows_only: bool) -> Graph<(f32, f32), (u64, u64), Directed, u32, DefaultNodeShape, CustomEdgeShape> {
|
||||||
|
let mut graph = to_graph_custom(&self,
|
||||||
|
|n| {
|
||||||
|
let (x, y) = *n.payload();
|
||||||
|
default_node_transform(n);
|
||||||
|
n.set_location(Pos2::new(x, y));
|
||||||
|
n.set_label(String::from(""));
|
||||||
|
},
|
||||||
|
|e| {
|
||||||
|
let (flow, capacity): (u64, u64) = *e.payload();
|
||||||
|
default_edge_transform(e);
|
||||||
|
e.set_label(format!("{flow}:{capacity}"));
|
||||||
|
if flow > 0 {
|
||||||
|
e.set_selected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
graph.node_mut(s).expect("node index not found").set_label(String::from("s"));
|
||||||
|
graph.node_mut(t).expect("node index not found").set_label(String::from("t"));
|
||||||
|
graph.node_mut(s).expect("node index not found").set_color(Color32::RED);
|
||||||
|
graph.node_mut(t).expect("node index not found").set_color(Color32::GREEN);
|
||||||
|
graph
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FlowGraph {
|
||||||
|
fn filter_empty_flows(&self) -> StableGraph<(f32, f32), (u64, u64)>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowGraph for StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
fn filter_empty_flows(&self) -> StableGraph<(f32, f32), (u64, u64)> {
|
||||||
|
self.filter_map( |_, n| {
|
||||||
|
Some(*n)
|
||||||
|
},
|
||||||
|
|_, &e| {
|
||||||
|
match e.0 {
|
||||||
|
0 => None,
|
||||||
|
_ => Some(e),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user