use std::cmp::max;
use std::ops::{Index, IndexMut};
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct NodeIndex(u32);
impl NodeIndex {
#[inline]
pub fn new(x: u32) -> Self {
NodeIndex(x)
}
#[inline]
pub fn index(self) -> usize {
self.0 as usize
}
#[inline]
pub fn end() -> Self {
NodeIndex(crate::INVALID_U32)
}
fn _into_edge(self) -> EdgeIndex {
EdgeIndex(self.0)
}
}
impl From<u32> for NodeIndex {
fn from(ix: u32) -> Self {
NodeIndex(ix)
}
}
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct EdgeIndex(u32);
impl EdgeIndex {
#[inline]
pub fn new(x: u32) -> Self {
EdgeIndex(x)
}
#[inline]
pub fn index(self) -> usize {
self.0 as usize
}
#[inline]
pub fn end() -> Self {
EdgeIndex(crate::INVALID_U32)
}
fn _into_node(self) -> NodeIndex {
NodeIndex(self.0)
}
}
impl From<u32> for EdgeIndex {
fn from(ix: u32) -> Self {
EdgeIndex(ix)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub enum Direction {
Outgoing = 0,
Incoming = 1,
}
impl Direction {
fn opposite(self) -> Direction {
match self {
Direction::Outgoing => Direction::Incoming,
Direction::Incoming => Direction::Outgoing,
}
}
}
const DIRECTIONS: [Direction; 2] = [Direction::Outgoing, Direction::Incoming];
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct Node<N> {
pub weight: N,
next: [EdgeIndex; 2],
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct Edge<E> {
pub weight: E,
next: [EdgeIndex; 2],
node: [NodeIndex; 2],
}
impl<E> Edge<E> {
pub fn source(&self) -> NodeIndex {
self.node[0]
}
pub fn target(&self) -> NodeIndex {
self.node[1]
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct Graph<N, E> {
pub(crate) nodes: Vec<Node<N>>,
pub(crate) edges: Vec<Edge<E>>,
}
enum Pair<T> {
Both(T, T),
One(T),
None,
}
fn index_twice<T>(arr: &mut [T], a: usize, b: usize) -> Pair<&mut T> {
if max(a, b) >= arr.len() {
Pair::None
} else if a == b {
Pair::One(&mut arr[max(a, b)])
} else {
unsafe {
let ar = &mut *(arr.get_unchecked_mut(a) as *mut _);
let br = &mut *(arr.get_unchecked_mut(b) as *mut _);
Pair::Both(ar, br)
}
}
}
impl<N, E> Graph<N, E> {
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
Graph {
nodes: Vec::with_capacity(nodes),
edges: Vec::with_capacity(edges),
}
}
pub fn add_node(&mut self, weight: N) -> NodeIndex {
let node = Node {
weight,
next: [EdgeIndex::end(), EdgeIndex::end()],
};
assert!(self.nodes.len() != crate::INVALID_USIZE);
let node_idx = NodeIndex::new(self.nodes.len() as u32);
self.nodes.push(node);
node_idx
}
pub fn node_weight(&self, a: NodeIndex) -> Option<&N> {
self.nodes.get(a.index()).map(|n| &n.weight)
}
pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> {
self.edges.get(a.index()).map(|e| &e.weight)
}
pub fn edge_weight_mut(&mut self, a: EdgeIndex) -> Option<&mut E> {
self.edges.get_mut(a.index()).map(|e| &mut e.weight)
}
pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex {
assert!(self.edges.len() != crate::INVALID_USIZE);
let edge_idx = EdgeIndex::new(self.edges.len() as u32);
let mut edge = Edge {
weight,
node: [a, b],
next: [EdgeIndex::end(); 2],
};
match index_twice(&mut self.nodes, a.index(), b.index()) {
Pair::None => panic!("Graph::add_edge: node indices out of bounds"),
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.edges.push(edge);
edge_idx
}
pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> {
self.edges
.get(e.index())
.map(|ed| (ed.source(), ed.target()))
}
pub fn remove_node(&mut self, a: NodeIndex) -> Option<N> {
self.nodes.get(a.index())?;
for d in &DIRECTIONS {
let k = *d as usize;
loop {
let next = self.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 = self.nodes.swap_remove(a.index());
let swap_edges = match self.nodes.get(a.index()) {
None => return Some(node.weight),
Some(ed) => ed.next,
};
let old_index = NodeIndex::new(self.nodes.len() as u32);
let new_index = a;
for &d in &DIRECTIONS {
let k = d as usize;
let mut edges = edges_walker_mut(&mut self.edges, swap_edges[k], d);
while let Some(curedge) = edges.next_edge() {
debug_assert!(curedge.node[k] == old_index);
curedge.node[k] = new_index;
}
}
Some(node.weight)
}
fn change_edge_links(
&mut self,
edge_node: [NodeIndex; 2],
e: EdgeIndex,
edge_next: [EdgeIndex; 2],
) {
for &d in &DIRECTIONS {
let k = d as usize;
let node = match self.nodes.get_mut(edge_node[k].index()) {
Some(r) => r,
None => {
debug_assert!(
false,
"Edge's endpoint dir={:?} index={:?} not found",
d, edge_node[k]
);
return;
}
};
let fst = node.next[k];
if fst == e {
node.next[k] = edge_next[k];
} else {
let mut edges = edges_walker_mut(&mut self.edges, fst, d);
while let Some(curedge) = edges.next_edge() {
if curedge.next[k] == e {
curedge.next[k] = edge_next[k];
break; }
}
}
}
}
pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E> {
let (edge_node, edge_next) = match self.edges.get(e.index()) {
None => return None,
Some(x) => (x.node, x.next),
};
self.change_edge_links(edge_node, e, edge_next);
self.remove_edge_adjust_indices(e)
}
fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option<E> {
let edge = self.edges.swap_remove(e.index());
let swap = match self.edges.get(e.index()) {
None => return Some(edge.weight),
Some(ed) => ed.node,
};
let swapped_e = EdgeIndex::new(self.edges.len() as u32);
self.change_edge_links(swap, swapped_e, [e, e]);
Some(edge.weight)
}
pub fn edges(&self, a: NodeIndex) -> Edges<E> {
self.edges_directed(a, Direction::Outgoing)
}
pub fn edges_directed(&self, a: NodeIndex, dir: Direction) -> Edges<E> {
Edges {
skip_start: a,
edges: &self.edges,
direction: dir,
next: match self.nodes.get(a.index()) {
None => [EdgeIndex::end(), EdgeIndex::end()],
Some(n) => n.next,
},
}
}
pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option<EdgeIndex> {
self.find_edge_undirected(a, b).map(|(ix, _)| ix)
}
pub fn find_edge_undirected(
&self,
a: NodeIndex,
b: NodeIndex,
) -> Option<(EdgeIndex, Direction)> {
match self.nodes.get(a.index()) {
None => None,
Some(node) => self.find_edge_undirected_from_node(node, b),
}
}
fn find_edge_undirected_from_node(
&self,
node: &Node<N>,
b: NodeIndex,
) -> Option<(EdgeIndex, Direction)> {
for &d in &DIRECTIONS {
let k = d as usize;
let mut edix = node.next[k];
while let Some(edge) = self.edges.get(edix.index()) {
if edge.node[1 - k] == b {
return Some((edix, d));
}
edix = edge.next[k];
}
}
None
}
pub fn raw_nodes(&self) -> &[Node<N>] {
&self.nodes
}
pub fn raw_edges(&self) -> &[Edge<E>] {
&self.edges
}
pub fn first_edge(&self, a: NodeIndex, dir: Direction) -> Option<EdgeIndex> {
match self.nodes.get(a.index()) {
None => None,
Some(node) => {
let edix = node.next[dir as usize];
if edix == EdgeIndex::end() {
None
} else {
Some(edix)
}
}
}
}
pub fn next_edge(&self, e: EdgeIndex, dir: Direction) -> Option<EdgeIndex> {
match self.edges.get(e.index()) {
None => None,
Some(node) => {
let edix = node.next[dir as usize];
if edix == EdgeIndex::end() {
None
} else {
Some(edix)
}
}
}
}
}
pub struct Externals<'a, N: 'a> {
iter: std::iter::Enumerate<std::slice::Iter<'a, Node<N>>>,
dir: Direction,
}
impl<'a, N: 'a> Iterator for Externals<'a, N> {
type Item = NodeIndex;
fn next(&mut self) -> Option<NodeIndex> {
let k = self.dir as usize;
loop {
match self.iter.next() {
None => return None,
Some((index, node)) => {
if node.next[k] == EdgeIndex::end() && node.next[1 - k] == EdgeIndex::end() {
return Some(NodeIndex::new(index as u32));
} else {
continue;
}
}
}
}
}
}
pub struct Neighbors<'a, E: 'a> {
skip_start: NodeIndex,
edges: &'a [Edge<E>],
next: [EdgeIndex; 2],
}
impl<'a, E> Iterator for Neighbors<'a, E> {
type Item = NodeIndex;
fn next(&mut self) -> Option<NodeIndex> {
match self.edges.get(self.next[0].index()) {
None => {}
Some(edge) => {
self.next[0] = edge.next[0];
return Some(edge.node[1]);
}
}
while let Some(edge) = self.edges.get(self.next[1].index()) {
self.next[1] = edge.next[1];
if edge.node[0] != self.skip_start {
return Some(edge.node[0]);
}
}
None
}
}
struct EdgesWalkerMut<'a, E: 'a> {
edges: &'a mut [Edge<E>],
next: EdgeIndex,
dir: Direction,
}
fn edges_walker_mut<E>(
edges: &mut [Edge<E>],
next: EdgeIndex,
dir: Direction,
) -> EdgesWalkerMut<E> {
EdgesWalkerMut { edges, next, dir }
}
impl<'a, E> EdgesWalkerMut<'a, E> {
fn next_edge(&mut self) -> Option<&mut Edge<E>> {
self.next().map(|t| t.1)
}
fn next(&mut self) -> Option<(EdgeIndex, &mut Edge<E>)> {
let this_index = self.next;
let k = self.dir as usize;
match self.edges.get_mut(self.next.index()) {
None => None,
Some(edge) => {
self.next = edge.next[k];
Some((this_index, edge))
}
}
}
}
pub struct Edges<'a, E: 'a> {
skip_start: NodeIndex,
edges: &'a [Edge<E>],
next: [EdgeIndex; 2],
direction: Direction,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = EdgeReference<'a, E>;
fn next(&mut self) -> Option<Self::Item> {
let (iterate_over, reverse) = (None, Some(self.direction.opposite()));
if iterate_over.unwrap_or(Direction::Outgoing) == Direction::Outgoing {
let i = self.next[0].index();
if let Some(Edge { node, weight, next }) = self.edges.get(i) {
self.next[0] = next[0];
return Some(EdgeReference {
index: EdgeIndex(i as u32),
node: if reverse == Some(Direction::Outgoing) {
swap_pair(*node)
} else {
*node
},
weight,
});
}
}
if iterate_over.unwrap_or(Direction::Incoming) == Direction::Incoming {
while let Some(Edge { node, weight, next }) = self.edges.get(self.next[1].index()) {
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(Direction::Incoming) {
swap_pair(*node)
} else {
*node
},
weight,
});
}
}
None
}
}
fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
x.swap(0, 1);
x
}
impl<'a, E> Clone for Edges<'a, E> {
fn clone(&self) -> Self {
Edges {
skip_start: self.skip_start,
edges: self.edges,
next: self.next,
direction: self.direction,
}
}
}
impl<N, E> Index<NodeIndex> for Graph<N, E> {
type Output = N;
fn index(&self, index: NodeIndex) -> &N {
&self.nodes[index.index()].weight
}
}
impl<N, E> IndexMut<NodeIndex> for Graph<N, E> {
fn index_mut(&mut self, index: NodeIndex) -> &mut N {
&mut self.nodes[index.index()].weight
}
}
impl<N, E> Index<EdgeIndex> for Graph<N, E> {
type Output = E;
fn index(&self, index: EdgeIndex) -> &E {
&self.edges[index.index()].weight
}
}
impl<N, E> IndexMut<EdgeIndex> for Graph<N, E> {
fn index_mut(&mut self, index: EdgeIndex) -> &mut E {
&mut self.edges[index.index()].weight
}
}
#[derive(Clone)]
pub struct WalkNeighbors {
skip_start: NodeIndex,
next: [EdgeIndex; 2],
}
#[derive(Debug)]
pub struct EdgeReference<'a, E: 'a> {
index: EdgeIndex,
node: [NodeIndex; 2],
weight: &'a E,
}
impl<'a, E: 'a> EdgeReference<'a, E> {
#[inline]
pub fn id(&self) -> EdgeIndex {
self.index
}
#[inline]
pub fn weight(&self) -> &'a E {
self.weight
}
}
impl<'a, E> Clone for EdgeReference<'a, E> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, E> Copy for EdgeReference<'a, E> {}
impl<'a, E> PartialEq for EdgeReference<'a, E>
where
E: PartialEq,
{
fn eq(&self, rhs: &Self) -> bool {
self.index == rhs.index && self.weight == rhs.weight
}
}
pub struct NodeReferences<'a, N: 'a> {
iter: std::iter::Enumerate<std::slice::Iter<'a, Node<N>>>,
}
impl<'a, N> Iterator for NodeReferences<'a, N> {
type Item = (NodeIndex, &'a N);
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|(i, node)| (NodeIndex::new(i as u32), &node.weight))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, N> DoubleEndedIterator for NodeReferences<'a, N> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|(i, node)| (NodeIndex::new(i as u32), &node.weight))
}
}
impl<'a, N> ExactSizeIterator for NodeReferences<'a, N> {}