use super::*;
pub trait Undirected: ConstrainedGraph
where
<Self::VertexIter as IntoIterator>::IntoIter: ExactSizeIterator,
<Self::EdgeIter as IntoIterator>::IntoIter: ExactSizeIterator,
{}
graph_wrapper! {
struct UndirectedGraph
}
impl_constraints_for_wrapper!{UndirectedGraph : Undirected}
impl<G> BaseGraph for UndirectedGraph<G>
where
G: ConstrainedGraph,
<G as BaseGraph>::Vertex: Vertex,
<G as BaseGraph>::Weight: Weight,
<<G as BaseGraph>::VertexIter as IntoIterator>::IntoIter: ExactSizeIterator,
<<G as BaseGraph>::EdgeIter as IntoIterator>::IntoIter: ExactSizeIterator,
{
type Vertex = <G as BaseGraph>::Vertex;
type Weight = <G as BaseGraph>::Weight;
type VertexIter = <G as BaseGraph>::VertexIter;
type EdgeIter = <G as BaseGraph>::EdgeIter;
fn empty_graph() -> Self {
UndirectedGraph::wrap(G::empty_graph())
}
wrapped_method!{all_vertices(&self) -> Self::VertexIter}
wrapped_method!{all_edges(&self) -> Self::EdgeIter}
wrapped_method!{add_vertex(&mut self, v: Self::Vertex) -> Result<(), ()>}
wrapped_method!{remove_vertex(&mut self, v: Self::Vertex) -> Result<(), ()>}
fn add_edge(&mut self, e: BaseEdge<Self::Vertex, Self::Weight>) -> Result<(), ()> {
let mut c = self.unconstrained().add_edge(e);
if e.source != e.sink {
c = c.add_edge(BaseEdge::new(e.sink, e.source, e.weight));
}
c.constrain()
}
fn remove_edge(&mut self, e: BaseEdge<Self::Vertex, Self::Weight>) -> Result<(), ()> {
let mut c = self.unconstrained().remove_edge(e);
if e.source != e.sink {
c = c.remove_edge(BaseEdge::new(e.sink, e.source, e.weight));
}
c.constrain()
}
}
impl<G> ConstrainedGraph for UndirectedGraph<G>
where
G: ConstrainedGraph,
<G as BaseGraph>::Vertex: Vertex,
<G as BaseGraph>::Weight: Weight,
<<G as BaseGraph>::VertexIter as IntoIterator>::IntoIter: ExactSizeIterator,
<<G as BaseGraph>::EdgeIter as IntoIterator>::IntoIter: ExactSizeIterator,
{
fn invariant_holds(&self) -> bool {
let edges = self.all_edges().into_iter();
let mut unmatched_edges: Vec<BaseEdge<Self::Vertex,Self::Weight>> = Vec::new();
for e in edges{
if e.source == e.sink {
continue;
}
if let Some(i) = unmatched_edges.iter().position(|temp| {
temp.source == e.sink &&
temp.sink == e.source &&
temp.weight == e.weight
} ){
unmatched_edges.swap_remove(i);
}else{
unmatched_edges.push(e);
}
}
unmatched_edges.is_empty() &&
self.wrapped().invariant_holds()
}
wrapped_uncon_methods!{}
}