use std::cmp;
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem::replace;
use std::mem::size_of;
use std::ops::{Index, IndexMut};
use std::slice;
use crate::{Directed, Direction, EdgeType, Graph, Incoming, Outgoing, Undirected};
use crate::iter_format::{DebugMap, IterFormatExt, NoPretty};
use crate::iter_utils::IterUtilsExt;
use super::{index_twice, Edge, Frozen, Node, Pair, DIRECTIONS};
use crate::visit::{
EdgeRef, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNodeReferences, NodeIndexable,
};
use crate::IntoWeightedEdge;
#[doc(no_inline)]
pub use crate::graph::{
edge_index, node_index, DefaultIx, EdgeIndex, GraphIndex, IndexType, NodeIndex,
};
use crate::util::enumerate;
#[cfg(feature = "serde-1")]
mod serialization;
pub struct StableGraph<N, E, Ty = Directed, Ix = DefaultIx> {
g: Graph<Option<N>, Option<E>, Ty, Ix>,
node_count: usize,
edge_count: usize,
free_node: NodeIndex<Ix>,
free_edge: EdgeIndex<Ix>,
}
pub type StableDiGraph<N, E, Ix = DefaultIx> = StableGraph<N, E, Directed, Ix>;
pub type StableUnGraph<N, E, Ix = DefaultIx> = StableGraph<N, E, Undirected, Ix>;
impl<N, E, Ty, Ix> fmt::Debug for StableGraph<N, E, Ty, Ix>
where
N: fmt::Debug,
E: fmt::Debug,
Ty: EdgeType,
Ix: IndexType,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let etype = if self.is_directed() {
"Directed"
} else {
"Undirected"
};
let mut fmt_struct = f.debug_struct("StableGraph");
fmt_struct.field("Ty", &etype);
fmt_struct.field("node_count", &self.node_count);
fmt_struct.field("edge_count", &self.edge_count);
if self.g.edges.iter().any(|e| e.weight.is_some()) {
fmt_struct.field(
"edges",
&self
.g
.edges
.iter()
.filter(|e| e.weight.is_some())
.map(|e| NoPretty((e.source().index(), e.target().index())))
.format(", "),
);
}
if size_of::<N>() != 0 {
fmt_struct.field(
"node weights",
&DebugMap(|| {
self.g
.nodes
.iter()
.map(|n| n.weight.as_ref())
.enumerate()
.filter_map(|(i, wo)| wo.map(move |w| (i, w)))
}),
);
}
if size_of::<E>() != 0 {
fmt_struct.field(
"edge weights",
&DebugMap(|| {
self.g
.edges
.iter()
.map(|n| n.weight.as_ref())
.enumerate()
.filter_map(|(i, wo)| wo.map(move |w| (i, w)))
}),
);
}
fmt_struct.field("free_node", &self.free_node);
fmt_struct.field("free_edge", &self.free_edge);
fmt_struct.finish()
}
}
impl<N, E> StableGraph<N, E, Directed> {
pub fn new() -> Self {
Self::with_capacity(0, 0)
}
}
impl<N, E, Ty, Ix> StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
StableGraph {
g: Graph::with_capacity(nodes, edges),
node_count: 0,
edge_count: 0,
free_node: NodeIndex::end(),
free_edge: EdgeIndex::end(),
}
}
pub fn capacity(&self) -> (usize, usize) {
self.g.capacity()
}
pub fn clear(&mut self) {
self.node_count = 0;
self.edge_count = 0;
self.free_node = NodeIndex::end();
self.free_edge = EdgeIndex::end();
self.g.clear();
}
pub fn clear_edges(&mut self) {
self.edge_count = 0;
self.free_edge = EdgeIndex::end();
self.g.edges.clear();
for node in &mut self.g.nodes {
if node.weight.is_some() {
node.next = [EdgeIndex::end(), EdgeIndex::end()];
}
}
}
pub fn node_count(&self) -> usize {
self.node_count
}
pub fn edge_count(&self) -> usize {
self.edge_count
}
#[inline]
pub fn is_directed(&self) -> bool {
Ty::is_directed()
}
pub fn add_node(&mut self, weight: N) -> NodeIndex<Ix> {
let index = if self.free_node != NodeIndex::end() {
let node_idx = self.free_node;
let node_slot = &mut self.g.nodes[node_idx.index()];
let _old = replace(&mut node_slot.weight, Some(weight));
debug_assert!(_old.is_none());
self.free_node = node_slot.next[0]._into_node();
node_slot.next[0] = EdgeIndex::end();
node_idx
} else {
self.g.add_node(Some(weight))
};
self.node_count += 1;
index
}
fn add_vacant_node(&mut self, free_node: &mut NodeIndex<Ix>) {
let node_idx = self.g.add_node(None);
let node_slot = &mut self.g.nodes[node_idx.index()];
node_slot.next[0] = free_node._into_edge();
*free_node = node_idx;
}
pub fn remove_node(&mut self, a: NodeIndex<Ix>) -> Option<N> {
let node_weight = self.g.nodes.get_mut(a.index())?.weight.take()?;
for d in &DIRECTIONS {
let k = d.index();
loop {
let next = self.g.nodes[a.index()].next[k];
if next == EdgeIndex::end() {
break;
}
let ret = self.remove_edge(next);
debug_assert!(ret.is_some());
let _ = ret;
}
}
let node_slot = &mut self.g.nodes[a.index()];
node_slot.next = [self.free_node._into_edge(), EdgeIndex::end()];
self.free_node = a;
self.node_count -= 1;
Some(node_weight)
}
pub fn contains_node(&self, a: NodeIndex<Ix>) -> bool {
self.get_node(a).is_some()
}
fn get_node(&self, a: NodeIndex<Ix>) -> Option<&Node<Option<N>, Ix>> {
self.g
.nodes
.get(a.index())
.and_then(|node| node.weight.as_ref().map(move |_| node))
}
pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
let edge_idx;
let mut new_edge = None::<Edge<_, _>>;
{
let edge: &mut Edge<_, _>;
if self.free_edge != EdgeIndex::end() {
edge_idx = self.free_edge;
edge = &mut self.g.edges[edge_idx.index()];
let _old = replace(&mut edge.weight, Some(weight));
debug_assert!(_old.is_none());
self.free_edge = edge.next[0];
edge.node = [a, b];
} else {
edge_idx = EdgeIndex::new(self.g.edges.len());
assert!(<Ix as IndexType>::max().index() == !0 || EdgeIndex::end() != edge_idx);
new_edge = Some(Edge {
weight: Some(weight),
node: [a, b],
next: [EdgeIndex::end(); 2],
});
edge = new_edge.as_mut().unwrap();
}
let wrong_index = match index_twice(&mut self.g.nodes, a.index(), b.index()) {
Pair::None => Some(cmp::max(a.index(), b.index())),
Pair::One(an) => {
if an.weight.is_none() {
Some(a.index())
} else {
edge.next = an.next;
an.next[0] = edge_idx;
an.next[1] = edge_idx;
None
}
}
Pair::Both(an, bn) => {
if an.weight.is_none() {
Some(a.index())
} else if bn.weight.is_none() {
Some(b.index())
} else {
edge.next = [an.next[0], bn.next[1]];
an.next[0] = edge_idx;
bn.next[1] = edge_idx;
None
}
}
};
if let Some(i) = wrong_index {
panic!(
"StableGraph::add_edge: node index {} is not a node in the graph",
i
);
}
self.edge_count += 1;
}
if let Some(edge) = new_edge {
self.g.edges.push(edge);
}
edge_idx
}
fn add_vacant_edge(&mut self, free_edge: &mut EdgeIndex<Ix>) {
let edge_idx = EdgeIndex::new(self.g.edges.len());
debug_assert!(edge_idx != EdgeIndex::end());
let mut edge = Edge {
weight: None,
node: [NodeIndex::end(); 2],
next: [EdgeIndex::end(); 2],
};
edge.next[0] = *free_edge;
*free_edge = edge_idx;
self.g.edges.push(edge);
}
pub fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, weight: E) -> EdgeIndex<Ix> {
if let Some(ix) = self.find_edge(a, b) {
self[ix] = weight;
return ix;
}
self.add_edge(a, b, weight)
}
pub fn remove_edge(&mut self, e: EdgeIndex<Ix>) -> Option<E> {
let (is_edge, edge_node, edge_next) = match self.g.edges.get(e.index()) {
None => return None,
Some(x) => (x.weight.is_some(), x.node, x.next),
};
if !is_edge {
return None;
}
self.g.change_edge_links(edge_node, e, edge_next);
let edge = &mut self.g.edges[e.index()];
edge.next = [self.free_edge, EdgeIndex::end()];
edge.node = [NodeIndex::end(), NodeIndex::end()];
self.free_edge = e;
self.edge_count -= 1;
edge.weight.take()
}
pub fn node_weight(&self, a: NodeIndex<Ix>) -> Option<&N> {
match self.g.nodes.get(a.index()) {
Some(no) => no.weight.as_ref(),
None => None,
}
}
pub fn node_weight_mut(&mut self, a: NodeIndex<Ix>) -> Option<&mut N> {
match self.g.nodes.get_mut(a.index()) {
Some(no) => no.weight.as_mut(),
None => None,
}
}
pub fn node_weights_mut(&mut self) -> impl Iterator<Item = &mut N> {
self.g
.node_weights_mut()
.flat_map(|maybe_node| maybe_node.iter_mut())
}
pub fn node_indices(&self) -> NodeIndices<N, Ix> {
NodeIndices {
iter: enumerate(self.raw_nodes()),
}
}
pub fn edge_weight(&self, e: EdgeIndex<Ix>) -> Option<&E> {
match self.g.edges.get(e.index()) {
Some(ed) => ed.weight.as_ref(),
None => None,
}
}
pub fn edge_weight_mut(&mut self, e: EdgeIndex<Ix>) -> Option<&mut E> {
match self.g.edges.get_mut(e.index()) {
Some(ed) => ed.weight.as_mut(),
None => None,
}
}
pub fn edge_weights_mut(&mut self) -> impl Iterator<Item = &mut E> {
self.g
.edge_weights_mut()
.flat_map(|maybe_edge| maybe_edge.iter_mut())
}
pub fn edge_endpoints(&self, e: EdgeIndex<Ix>) -> Option<(NodeIndex<Ix>, NodeIndex<Ix>)> {
match self.g.edges.get(e.index()) {
Some(ed) if ed.weight.is_some() => Some((ed.source(), ed.target())),
_otherwise => None,
}
}
pub fn edge_indices(&self) -> EdgeIndices<E, Ix> {
EdgeIndices {
iter: enumerate(self.raw_edges()),
}
}
pub fn contains_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> bool {
self.find_edge(a, b).is_some()
}
pub fn find_edge(&self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> Option<EdgeIndex<Ix>> {
if !self.is_directed() {
self.find_edge_undirected(a, b).map(|(ix, _)| ix)
} else {
match self.get_node(a) {
None => None,
Some(node) => self.g.find_edge_directed_from_node(node, b),
}
}
}
pub fn find_edge_undirected(
&self,
a: NodeIndex<Ix>,
b: NodeIndex<Ix>,
) -> Option<(EdgeIndex<Ix>, Direction)> {
match self.get_node(a) {
None => None,
Some(node) => self.g.find_edge_undirected_from_node(node, b),
}
}
pub fn neighbors(&self, a: NodeIndex<Ix>) -> Neighbors<E, Ix> {
self.neighbors_directed(a, Outgoing)
}
pub fn neighbors_directed(&self, a: NodeIndex<Ix>, dir: Direction) -> Neighbors<E, Ix> {
let mut iter = self.neighbors_undirected(a);
if self.is_directed() {
let k = dir.index();
iter.next[1 - k] = EdgeIndex::end();
iter.skip_start = NodeIndex::end();
}
iter
}
pub fn neighbors_undirected(&self, a: NodeIndex<Ix>) -> Neighbors<E, Ix> {
Neighbors {
skip_start: a,
edges: &self.g.edges,
next: match self.get_node(a) {
None => [EdgeIndex::end(), EdgeIndex::end()],
Some(n) => n.next,
},
}
}
pub fn edges(&self, a: NodeIndex<Ix>) -> Edges<E, Ty, Ix> {
self.edges_directed(a, Outgoing)
}
pub fn edges_directed(&self, a: NodeIndex<Ix>, dir: Direction) -> Edges<E, Ty, Ix> {
Edges {
skip_start: a,
edges: &self.g.edges,
direction: dir,
next: match self.get_node(a) {
None => [EdgeIndex::end(), EdgeIndex::end()],
Some(n) => n.next,
},
ty: PhantomData,
}
}
pub fn externals(&self, dir: Direction) -> Externals<N, Ty, Ix> {
Externals {
iter: self.raw_nodes().iter().enumerate(),
dir,
ty: PhantomData,
}
}
pub fn index_twice_mut<T, U>(
&mut self,
i: T,
j: U,
) -> (
&mut <Self as Index<T>>::Output,
&mut <Self as Index<U>>::Output,
)
where
Self: IndexMut<T> + IndexMut<U>,
T: GraphIndex,
U: GraphIndex,
{
assert!(T::is_node_index() != U::is_node_index() || i.index() != j.index());
unsafe {
let self_mut = self as *mut _;
(
<Self as IndexMut<T>>::index_mut(&mut *self_mut, i),
<Self as IndexMut<U>>::index_mut(&mut *self_mut, j),
)
}
}
pub fn retain_nodes<F>(&mut self, mut visit: F)
where
F: FnMut(Frozen<Self>, NodeIndex<Ix>) -> bool,
{
for i in 0..self.node_bound() {
let ix = node_index(i);
if self.contains_node(ix) && !visit(Frozen(self), ix) {
self.remove_node(ix);
}
}
self.check_free_lists();
}
pub fn retain_edges<F>(&mut self, mut visit: F)
where
F: FnMut(Frozen<Self>, EdgeIndex<Ix>) -> bool,
{
for i in 0..self.edge_bound() {
let ix = edge_index(i);
if self.edge_weight(ix).is_some() && !visit(Frozen(self), ix) {
self.remove_edge(ix);
}
}
self.check_free_lists();
}
pub fn from_edges<I>(iterable: I) -> Self
where
I: IntoIterator,
I::Item: IntoWeightedEdge<E>,
<I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
N: Default,
{
let mut g = Self::with_capacity(0, 0);
g.extend_with_edges(iterable);
g
}
pub fn map<'a, F, G, N2, E2>(
&'a self,
mut node_map: F,
mut edge_map: G,
) -> StableGraph<N2, E2, Ty, Ix>
where
F: FnMut(NodeIndex<Ix>, &'a N) -> N2,
G: FnMut(EdgeIndex<Ix>, &'a E) -> E2,
{
let g = self.g.map(
move |i, w| w.as_ref().map(|w| node_map(i, w)),
move |i, w| w.as_ref().map(|w| edge_map(i, w)),
);
StableGraph {
g,
node_count: self.node_count,
edge_count: self.edge_count,
free_node: self.free_node,
free_edge: self.free_edge,
}
}
pub fn filter_map<'a, F, G, N2, E2>(
&'a self,
mut node_map: F,
mut edge_map: G,
) -> StableGraph<N2, E2, Ty, Ix>
where
F: FnMut(NodeIndex<Ix>, &'a N) -> Option<N2>,
G: FnMut(EdgeIndex<Ix>, &'a E) -> Option<E2>,
{
let node_bound = self.node_bound();
let edge_bound = self.edge_bound();
let mut result_g = StableGraph::with_capacity(node_bound, edge_bound);
let mut free_node = NodeIndex::end();
let mut free_edge = EdgeIndex::end();
for (i, node) in enumerate(self.raw_nodes()) {
if i >= node_bound {
break;
}
if let Some(node_weight) = node.weight.as_ref() {
if let Some(new_weight) = node_map(NodeIndex::new(i), node_weight) {
result_g.add_node(new_weight);
continue;
}
}
result_g.add_vacant_node(&mut free_node);
}
for (i, edge) in enumerate(self.raw_edges()) {
if i >= edge_bound {
break;
}
let source = edge.source();
let target = edge.target();
if let Some(edge_weight) = edge.weight.as_ref() {
if result_g.contains_node(source) && result_g.contains_node(target) {
if let Some(new_weight) = edge_map(EdgeIndex::new(i), edge_weight) {
result_g.add_edge(source, target, new_weight);
continue;
}
}
}
result_g.add_vacant_edge(&mut free_edge);
}
result_g.free_node = free_node;
result_g.free_edge = free_edge;
result_g.check_free_lists();
result_g
}
pub fn extend_with_edges<I>(&mut self, iterable: I)
where
I: IntoIterator,
I::Item: IntoWeightedEdge<E>,
<I::Item as IntoWeightedEdge<E>>::NodeId: Into<NodeIndex<Ix>>,
N: Default,
{
let iter = iterable.into_iter();
for elt in iter {
let (source, target, weight) = elt.into_weighted_edge();
let (source, target) = (source.into(), target.into());
let nx = cmp::max(source, target);
while nx.index() >= self.node_count() {
self.add_node(N::default());
}
self.add_edge(source, target, weight);
}
}
fn raw_nodes(&self) -> &[Node<Option<N>, Ix>] {
self.g.raw_nodes()
}
fn raw_edges(&self) -> &[Edge<Option<E>, Ix>] {
self.g.raw_edges()
}
fn edge_bound(&self) -> usize {
self.edge_references()
.next_back()
.map_or(0, |edge| edge.id().index() + 1)
}
#[cfg(feature = "serde-1")]
fn link_edges(&mut self) -> Result<(), NodeIndex<Ix>> {
self.node_count = 0;
self.edge_count = 0;
let mut free_node = NodeIndex::end();
for (node_index, node) in enumerate(&mut self.g.nodes) {
if node.weight.is_some() {
self.node_count += 1;
} else {
node.next = [free_node._into_edge(), EdgeIndex::end()];
free_node = NodeIndex::new(node_index);
}
}
self.free_node = free_node;
let mut free_edge = EdgeIndex::end();
for (edge_index, edge) in enumerate(&mut self.g.edges) {
if edge.weight.is_none() {
edge.next = [free_edge, EdgeIndex::end()];
free_edge = EdgeIndex::new(edge_index);
continue;
}
let a = edge.source();
let b = edge.target();
let edge_idx = EdgeIndex::new(edge_index);
match index_twice(&mut self.g.nodes, a.index(), b.index()) {
Pair::None => return Err(if a > b { a } else { b }),
Pair::One(an) => {
edge.next = an.next;
an.next[0] = edge_idx;
an.next[1] = edge_idx;
}
Pair::Both(an, bn) => {
edge.next = [an.next[0], bn.next[1]];
an.next[0] = edge_idx;
bn.next[1] = edge_idx;
}
}
self.edge_count += 1;
}
self.free_edge = free_edge;
Ok(())
}
#[cfg(not(debug_assertions))]
fn check_free_lists(&self) {}
#[cfg(debug_assertions)]
fn check_free_lists(&self) {
let mut free_node = self.free_node;
let mut free_node_len = 0;
while free_node != NodeIndex::end() {
if let Some(n) = self.g.nodes.get(free_node.index()) {
if n.weight.is_none() {
free_node = n.next[0]._into_node();
free_node_len += 1;
continue;
}
debug_assert!(
false,
"Corrupt free list: pointing to existing {:?}",
free_node.index()
);
}
debug_assert!(false, "Corrupt free list: missing {:?}", free_node.index());
}
debug_assert_eq!(self.node_count(), self.raw_nodes().len() - free_node_len);
let mut free_edge_len = 0;
let mut free_edge = self.free_edge;
while free_edge != EdgeIndex::end() {
if let Some(n) = self.g.edges.get(free_edge.index()) {
if n.weight.is_none() {
free_edge = n.next[0];
free_edge_len += 1;
continue;
}
debug_assert!(
false,
"Corrupt free list: pointing to existing {:?}",
free_node.index()
);
}
debug_assert!(false, "Corrupt free list: missing {:?}", free_edge.index());
}
debug_assert_eq!(self.edge_count(), self.raw_edges().len() - free_edge_len);
}
}
impl<N, E, Ty, Ix: IndexType> Clone for StableGraph<N, E, Ty, Ix>
where
N: Clone,
E: Clone,
{
fn clone(&self) -> Self {
StableGraph {
g: self.g.clone(),
node_count: self.node_count,
edge_count: self.edge_count,
free_node: self.free_node,
free_edge: self.free_edge,
}
}
fn clone_from(&mut self, rhs: &Self) {
self.g.clone_from(&rhs.g);
self.node_count = rhs.node_count;
self.edge_count = rhs.edge_count;
self.free_node = rhs.free_node;
self.free_edge = rhs.free_edge;
}
}
impl<N, E, Ty, Ix> Index<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type Output = N;
fn index(&self, index: NodeIndex<Ix>) -> &N {
self.node_weight(index).unwrap()
}
}
impl<N, E, Ty, Ix> IndexMut<NodeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn index_mut(&mut self, index: NodeIndex<Ix>) -> &mut N {
self.node_weight_mut(index).unwrap()
}
}
impl<N, E, Ty, Ix> Index<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type Output = E;
fn index(&self, index: EdgeIndex<Ix>) -> &E {
self.edge_weight(index).unwrap()
}
}
impl<N, E, Ty, Ix> IndexMut<EdgeIndex<Ix>> for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn index_mut(&mut self, index: EdgeIndex<Ix>) -> &mut E {
self.edge_weight_mut(index).unwrap()
}
}
impl<N, E, Ty, Ix> Default for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn default() -> Self {
Self::with_capacity(0, 0)
}
}
impl<N, E, Ty, Ix> From<Graph<N, E, Ty, Ix>> for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn from(g: Graph<N, E, Ty, Ix>) -> Self {
let nodes = g.nodes.into_iter().map(|e| Node {
weight: Some(e.weight),
next: e.next,
});
let edges = g.edges.into_iter().map(|e| Edge {
weight: Some(e.weight),
node: e.node,
next: e.next,
});
StableGraph {
node_count: nodes.len(),
edge_count: edges.len(),
g: Graph {
edges: edges.collect(),
nodes: nodes.collect(),
ty: g.ty,
},
free_node: NodeIndex::end(),
free_edge: EdgeIndex::end(),
}
}
}
impl<N, E, Ty, Ix> From<StableGraph<N, E, Ty, Ix>> for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn from(graph: StableGraph<N, E, Ty, Ix>) -> Self {
let mut result_g = Graph::with_capacity(graph.node_count(), graph.edge_count());
let mut node_index_map = vec![NodeIndex::end(); graph.node_bound()];
for (i, node) in enumerate(graph.g.nodes) {
if let Some(nw) = node.weight {
node_index_map[i] = result_g.add_node(nw);
}
}
for edge in graph.g.edges {
let source_index = edge.source().index();
let target_index = edge.target().index();
if let Some(ew) = edge.weight {
let source = node_index_map[source_index];
let target = node_index_map[target_index];
debug_assert!(source != NodeIndex::end());
debug_assert!(target != NodeIndex::end());
result_g.add_edge(source, target, ew);
}
}
result_g
}
}
impl<'a, N, E, Ty, Ix> IntoNodeReferences for &'a StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type NodeRef = (NodeIndex<Ix>, &'a N);
type NodeReferences = NodeReferences<'a, N, Ix>;
fn node_references(self) -> Self::NodeReferences {
NodeReferences {
iter: enumerate(self.raw_nodes()),
}
}
}
pub struct NodeReferences<'a, N: 'a, Ix: IndexType = DefaultIx> {
iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
}
impl<'a, N, Ix> Iterator for NodeReferences<'a, N, Ix>
where
Ix: IndexType,
{
type Item = (NodeIndex<Ix>, &'a N);
fn next(&mut self) -> Option<Self::Item> {
self.iter
.ex_find_map(|(i, node)| node.weight.as_ref().map(move |w| (node_index(i), w)))
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
(0, hi)
}
}
impl<'a, N, Ix> DoubleEndedIterator for NodeReferences<'a, N, Ix>
where
Ix: IndexType,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.ex_rfind_map(|(i, node)| node.weight.as_ref().map(move |w| (node_index(i), w)))
}
}
#[derive(Debug)]
pub struct EdgeReference<'a, E: 'a, Ix = DefaultIx> {
index: EdgeIndex<Ix>,
node: [NodeIndex<Ix>; 2],
weight: &'a E,
}
impl<'a, E, Ix: IndexType> Clone for EdgeReference<'a, E, Ix> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, E, Ix: IndexType> Copy for EdgeReference<'a, E, Ix> {}
impl<'a, E, Ix: IndexType> PartialEq for EdgeReference<'a, E, Ix>
where
E: PartialEq,
{
fn eq(&self, rhs: &Self) -> bool {
self.index == rhs.index && self.weight == rhs.weight
}
}
impl<'a, Ix, E> EdgeReference<'a, E, Ix>
where
Ix: IndexType,
{
pub fn weight(&self) -> &'a E {
self.weight
}
}
impl<'a, Ix, E> EdgeRef for EdgeReference<'a, E, Ix>
where
Ix: IndexType,
{
type NodeId = NodeIndex<Ix>;
type EdgeId = EdgeIndex<Ix>;
type Weight = E;
fn source(&self) -> Self::NodeId {
self.node[0]
}
fn target(&self) -> Self::NodeId {
self.node[1]
}
fn weight(&self) -> &E {
self.weight
}
fn id(&self) -> Self::EdgeId {
self.index
}
}
impl<'a, N, E, Ty, Ix> IntoEdges for &'a StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type Edges = Edges<'a, E, Ty, Ix>;
fn edges(self, a: Self::NodeId) -> Self::Edges {
self.edges(a)
}
}
impl<'a, N, E, Ty, Ix> IntoEdgesDirected for &'a StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type EdgesDirected = Edges<'a, E, Ty, Ix>;
fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected {
self.edges_directed(a, dir)
}
}
pub struct Edges<'a, E: 'a, Ty, Ix: 'a = DefaultIx>
where
Ty: EdgeType,
Ix: IndexType,
{
skip_start: NodeIndex<Ix>,
edges: &'a [Edge<Option<E>, Ix>],
next: [EdgeIndex<Ix>; 2],
direction: Direction,
ty: PhantomData<Ty>,
}
impl<'a, E, Ty, Ix> Iterator for Edges<'a, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type Item = EdgeReference<'a, E, Ix>;
fn next(&mut self) -> Option<Self::Item> {
let (iterate_over, reverse) = if Ty::is_directed() {
(Some(self.direction), None)
} else {
(None, Some(self.direction.opposite()))
};
if iterate_over.unwrap_or(Outgoing) == Outgoing {
let i = self.next[0].index();
if let Some(Edge {
node,
weight: Some(weight),
next,
}) = self.edges.get(i)
{
self.next[0] = next[0];
return Some(EdgeReference {
index: edge_index(i),
node: if reverse == Some(Outgoing) {
swap_pair(*node)
} else {
*node
},
weight,
});
}
}
if iterate_over.unwrap_or(Incoming) == Incoming {
while let Some(Edge { node, weight, next }) = self.edges.get(self.next[1].index()) {
debug_assert!(weight.is_some());
let edge_index = self.next[1];
self.next[1] = next[1];
if iterate_over.is_none() && node[0] == self.skip_start {
continue;
}
return Some(EdgeReference {
index: edge_index,
node: if reverse == Some(Incoming) {
swap_pair(*node)
} else {
*node
},
weight: weight.as_ref().unwrap(),
});
}
}
None
}
}
fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
x.swap(0, 1);
x
}
impl<'a, N: 'a, E: 'a, Ty, Ix> IntoEdgeReferences for &'a StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type EdgeRef = EdgeReference<'a, E, Ix>;
type EdgeReferences = EdgeReferences<'a, E, Ix>;
fn edge_references(self) -> Self::EdgeReferences {
EdgeReferences {
iter: self.g.edges.iter().enumerate(),
}
}
}
pub struct EdgeReferences<'a, E: 'a, Ix: 'a = DefaultIx> {
iter: iter::Enumerate<slice::Iter<'a, Edge<Option<E>, Ix>>>,
}
impl<'a, E, Ix> Iterator for EdgeReferences<'a, E, Ix>
where
Ix: IndexType,
{
type Item = EdgeReference<'a, E, Ix>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.ex_find_map(|(i, edge)| {
edge.weight.as_ref().map(move |weight| EdgeReference {
index: edge_index(i),
node: edge.node,
weight,
})
})
}
}
impl<'a, E, Ix> DoubleEndedIterator for EdgeReferences<'a, E, Ix>
where
Ix: IndexType,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.ex_rfind_map(|(i, edge)| {
edge.weight.as_ref().map(move |weight| EdgeReference {
index: edge_index(i),
node: edge.node,
weight,
})
})
}
}
pub struct Externals<'a, N: 'a, Ty, Ix: IndexType = DefaultIx> {
iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
dir: Direction,
ty: PhantomData<Ty>,
}
impl<'a, N: 'a, Ty, Ix> Iterator for Externals<'a, N, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<NodeIndex<Ix>> {
let k = self.dir.index();
loop {
match self.iter.next() {
None => return None,
Some((index, node)) => {
if node.weight.is_some()
&& node.next[k] == EdgeIndex::end()
&& (Ty::is_directed() || node.next[1 - k] == EdgeIndex::end())
{
return Some(NodeIndex::new(index));
} else {
continue;
}
}
}
}
}
}
pub struct Neighbors<'a, E: 'a, Ix: 'a = DefaultIx> {
skip_start: NodeIndex<Ix>,
edges: &'a [Edge<Option<E>, Ix>],
next: [EdgeIndex<Ix>; 2],
}
impl<'a, E, Ix> Neighbors<'a, E, Ix>
where
Ix: IndexType,
{
pub fn detach(&self) -> WalkNeighbors<Ix> {
WalkNeighbors {
inner: super::WalkNeighbors {
skip_start: self.skip_start,
next: self.next,
},
}
}
}
impl<'a, E, Ix> Iterator for Neighbors<'a, E, Ix>
where
Ix: IndexType,
{
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<NodeIndex<Ix>> {
match self.edges.get(self.next[0].index()) {
None => {}
Some(edge) => {
debug_assert!(edge.weight.is_some());
self.next[0] = edge.next[0];
return Some(edge.node[1]);
}
}
while let Some(edge) = self.edges.get(self.next[1].index()) {
debug_assert!(edge.weight.is_some());
self.next[1] = edge.next[1];
if edge.node[0] != self.skip_start {
return Some(edge.node[0]);
}
}
None
}
}
pub struct WalkNeighbors<Ix> {
inner: super::WalkNeighbors<Ix>,
}
impl<Ix: IndexType> Clone for WalkNeighbors<Ix> {
clone_fields!(WalkNeighbors, inner);
}
impl<Ix: IndexType> WalkNeighbors<Ix> {
pub fn next<N, E, Ty: EdgeType>(
&mut self,
g: &StableGraph<N, E, Ty, Ix>,
) -> Option<(EdgeIndex<Ix>, NodeIndex<Ix>)> {
self.inner.next(&g.g)
}
pub fn next_node<N, E, Ty: EdgeType>(
&mut self,
g: &StableGraph<N, E, Ty, Ix>,
) -> Option<NodeIndex<Ix>> {
self.next(g).map(|t| t.1)
}
pub fn next_edge<N, E, Ty: EdgeType>(
&mut self,
g: &StableGraph<N, E, Ty, Ix>,
) -> Option<EdgeIndex<Ix>> {
self.next(g).map(|t| t.0)
}
}
pub struct NodeIndices<'a, N: 'a, Ix: 'a = DefaultIx> {
iter: iter::Enumerate<slice::Iter<'a, Node<Option<N>, Ix>>>,
}
impl<'a, N, Ix: IndexType> Iterator for NodeIndices<'a, N, Ix> {
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.ex_find_map(|(i, node)| {
if node.weight.is_some() {
Some(node_index(i))
} else {
None
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
(0, hi)
}
}
impl<'a, N, Ix: IndexType> DoubleEndedIterator for NodeIndices<'a, N, Ix> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.ex_rfind_map(|(i, node)| {
if node.weight.is_some() {
Some(node_index(i))
} else {
None
}
})
}
}
impl<N, E, Ty, Ix> NodeIndexable for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn node_bound(&self) -> usize {
self.node_indices().next_back().map_or(0, |i| i.index() + 1)
}
fn to_index(&self, ix: NodeIndex<Ix>) -> usize {
ix.index()
}
fn from_index(&self, ix: usize) -> Self::NodeId {
NodeIndex::new(ix)
}
}
pub struct EdgeIndices<'a, E: 'a, Ix: 'a = DefaultIx> {
iter: iter::Enumerate<slice::Iter<'a, Edge<Option<E>, Ix>>>,
}
impl<'a, E, Ix: IndexType> Iterator for EdgeIndices<'a, E, Ix> {
type Item = EdgeIndex<Ix>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.ex_find_map(|(i, node)| {
if node.weight.is_some() {
Some(edge_index(i))
} else {
None
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let (_, hi) = self.iter.size_hint();
(0, hi)
}
}
impl<'a, E, Ix: IndexType> DoubleEndedIterator for EdgeIndices<'a, E, Ix> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.ex_rfind_map(|(i, node)| {
if node.weight.is_some() {
Some(edge_index(i))
} else {
None
}
})
}
}
#[test]
fn stable_graph() {
let mut gr = StableGraph::<_, _>::with_capacity(0, 0);
let a = gr.add_node(0);
let b = gr.add_node(1);
let c = gr.add_node(2);
let _ed = gr.add_edge(a, b, 1);
println!("{:?}", gr);
gr.remove_node(b);
println!("{:?}", gr);
let d = gr.add_node(3);
println!("{:?}", gr);
gr.check_free_lists();
gr.remove_node(a);
gr.check_free_lists();
gr.remove_node(c);
gr.check_free_lists();
println!("{:?}", gr);
gr.add_edge(d, d, 2);
println!("{:?}", gr);
let e = gr.add_node(4);
gr.add_edge(d, e, 3);
println!("{:?}", gr);
for neigh in gr.neighbors(d) {
println!("edge {:?} -> {:?}", d, neigh);
}
gr.check_free_lists();
}
#[test]
fn dfs() {
use crate::visit::Dfs;
let mut gr = StableGraph::<_, _>::with_capacity(0, 0);
let a = gr.add_node("a");
let b = gr.add_node("b");
let c = gr.add_node("c");
let d = gr.add_node("d");
gr.add_edge(a, b, 1);
gr.add_edge(a, c, 2);
gr.add_edge(b, c, 3);
gr.add_edge(b, d, 4);
gr.add_edge(c, d, 5);
gr.add_edge(d, b, 6);
gr.add_edge(c, b, 7);
println!("{:?}", gr);
let mut dfs = Dfs::new(&gr, a);
while let Some(next) = dfs.next(&gr) {
println!("dfs visit => {:?}, weight={:?}", next, &gr[next]);
}
}
#[test]
fn test_retain_nodes() {
let mut gr = StableGraph::<_, _>::with_capacity(6, 6);
let a = gr.add_node("a");
let f = gr.add_node("f");
let b = gr.add_node("b");
let c = gr.add_node("c");
let d = gr.add_node("d");
let e = gr.add_node("e");
gr.add_edge(a, b, 1);
gr.add_edge(a, c, 2);
gr.add_edge(b, c, 3);
gr.add_edge(b, d, 4);
gr.add_edge(c, d, 5);
gr.add_edge(d, b, 6);
gr.add_edge(c, b, 7);
gr.add_edge(d, e, 8);
gr.remove_node(f);
assert_eq!(gr.node_count(), 5);
assert_eq!(gr.edge_count(), 8);
gr.retain_nodes(|frozen_gr, ix| frozen_gr[ix] >= "c");
assert_eq!(gr.node_count(), 3);
assert_eq!(gr.edge_count(), 2);
gr.check_free_lists();
}