use petgraph::graph::{Graph, NodeIndex};
use petgraph::visit::EdgeRef;
use petgraph::Directed;
use std::marker::PhantomData;
use super::traits::{FlowGraph, OriginalGraphView};
#[derive(Debug, Clone)]
pub struct AdjacencyListFlowGraph<N = ()>
where
N: Clone + std::fmt::Debug,
{
graph: Graph<N, f64, Directed, u32>,
_phantom_n: PhantomData<N>,
}
impl<N> AdjacencyListFlowGraph<N>
where
N: Clone + std::fmt::Debug,
{
pub fn new() -> Self {
Self {
graph: Graph::default(), _phantom_n: PhantomData,
}
}
pub fn add_node(&mut self, weight: N) -> usize {
self.graph.add_node(weight).index()
}
pub fn add_edge(&mut self, u_idx: usize, v_idx: usize, capacity: f64) {
let node_count = self.graph.node_count();
if u_idx >= node_count || v_idx >= node_count {
panic!("Attempted to add edge with out-of-bounds vertex index. u_idx: {u_idx}, v_idx: {v_idx}, node_count: {node_count}");
}
let u_node = NodeIndex::new(u_idx);
let v_node = NodeIndex::new(v_idx);
self.graph.add_edge(u_node, v_node, capacity);
}
}
impl<N> FlowGraph for AdjacencyListFlowGraph<N>
where
N: Clone + std::fmt::Debug,
{
fn vertex_count(&self) -> usize {
self.graph.node_count()
}
}
impl<N> OriginalGraphView for AdjacencyListFlowGraph<N>
where
N: Clone + std::fmt::Debug,
{
fn all_edges(&self) -> Box<dyn Iterator<Item = (usize, usize, f64)> + '_> {
Box::new(self.graph.edge_references().map(|edge_ref| {
(
edge_ref.source().index(), edge_ref.target().index(), *edge_ref.weight(), )
}))
}
}
impl<N> Default for AdjacencyListFlowGraph<N>
where
N: Default + Clone + std::fmt::Debug,
{
fn default() -> Self {
Self {
graph: Graph::default(),
_phantom_n: PhantomData,
}
}
}