use indexmap::map::Keys;
use indexmap::map::{Iter as IndexMapIter, IterMut as IndexMapIterMut};
use indexmap::IndexMap;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{self, Hash};
use std::iter::FromIterator;
use std::iter::{Cloned, DoubleEndedIterator};
use std::marker::PhantomData;
use std::ops::{Deref, Index, IndexMut};
use std::slice::Iter;
use crate::{Directed, Direction, EdgeType, Incoming, Outgoing, Undirected};
use crate::graph::node_index;
use crate::graph::Graph;
use crate::visit::{IntoEdgeReferences, IntoEdges, NodeCompactIndexable};
use crate::visit::{IntoNodeIdentifiers, IntoNodeReferences, NodeCount, NodeIndexable};
use crate::IntoWeightedEdge;
pub type UnGraphMap<N, E> = GraphMap<N, E, Undirected>;
pub type DiGraphMap<N, E> = GraphMap<N, E, Directed>;
#[derive(Clone)]
pub struct GraphMap<N, E, Ty> {
nodes: IndexMap<N, Vec<(N, CompactDirection)>>,
edges: IndexMap<(N, N), E>,
ty: PhantomData<Ty>,
}
impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug, Ty: EdgeType> fmt::Debug for GraphMap<N, E, Ty> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.nodes.fmt(f)
}
}
pub trait NodeTrait: Copy + Ord + Hash {}
impl<N> NodeTrait for N where N: Copy + Ord + Hash {}
#[derive(Copy, Clone, Debug, PartialEq)]
enum CompactDirection {
Outgoing,
Incoming,
}
impl From<Direction> for CompactDirection {
fn from(d: Direction) -> Self {
match d {
Outgoing => CompactDirection::Outgoing,
Incoming => CompactDirection::Incoming,
}
}
}
impl PartialEq<Direction> for CompactDirection {
fn eq(&self, rhs: &Direction) -> bool {
(*self as usize) == (*rhs as usize)
}
}
impl<N, E, Ty> GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(nodes: usize, edges: usize) -> Self {
GraphMap {
nodes: IndexMap::with_capacity(nodes),
edges: IndexMap::with_capacity(edges),
ty: PhantomData,
}
}
pub fn capacity(&self) -> (usize, usize) {
(self.nodes.capacity(), self.edges.capacity())
}
#[inline]
fn edge_key(a: N, b: N) -> (N, N) {
if Ty::is_directed() || a <= b {
(a, b)
} else {
(b, a)
}
}
pub fn is_directed(&self) -> bool {
Ty::is_directed()
}
pub fn from_edges<I>(iterable: I) -> Self
where
I: IntoIterator,
I::Item: IntoWeightedEdge<E, NodeId = N>,
{
Self::from_iter(iterable)
}
pub fn node_count(&self) -> usize {
self.nodes.len()
}
pub fn edge_count(&self) -> usize {
self.edges.len()
}
pub fn clear(&mut self) {
self.nodes.clear();
self.edges.clear();
}
pub fn add_node(&mut self, n: N) -> N {
self.nodes.entry(n).or_insert(Vec::new());
n
}
pub fn remove_node(&mut self, n: N) -> bool {
let links = match self.nodes.swap_remove(&n) {
None => return false,
Some(sus) => sus,
};
for (succ, _) in links {
self.remove_single_edge(&succ, &n, Incoming);
self.edges.swap_remove(&Self::edge_key(n, succ));
}
true
}
pub fn contains_node(&self, n: N) -> bool {
self.nodes.contains_key(&n)
}
pub fn add_edge(&mut self, a: N, b: N, weight: E) -> Option<E> {
if let old @ Some(_) = self.edges.insert(Self::edge_key(a, b), weight) {
old
} else {
self.nodes
.entry(a)
.or_insert_with(|| Vec::with_capacity(1))
.push((b, CompactDirection::Outgoing));
if a != b {
self.nodes
.entry(b)
.or_insert_with(|| Vec::with_capacity(1))
.push((a, CompactDirection::Incoming));
}
None
}
}
fn remove_single_edge(&mut self, a: &N, b: &N, dir: Direction) -> bool {
match self.nodes.get_mut(a) {
None => false,
Some(sus) => {
if Ty::is_directed() {
match sus
.iter()
.position(|elt| elt == &(*b, CompactDirection::from(dir)))
{
Some(index) => {
sus.swap_remove(index);
true
}
None => false,
}
} else {
match sus.iter().position(|elt| &elt.0 == b) {
Some(index) => {
sus.swap_remove(index);
true
}
None => false,
}
}
}
}
}
pub fn remove_edge(&mut self, a: N, b: N) -> Option<E> {
let exist1 = self.remove_single_edge(&a, &b, Outgoing);
let exist2 = if a != b {
self.remove_single_edge(&b, &a, Incoming)
} else {
exist1
};
let weight = self.edges.remove(&Self::edge_key(a, b));
debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
weight
}
pub fn contains_edge(&self, a: N, b: N) -> bool {
self.edges.contains_key(&Self::edge_key(a, b))
}
pub fn nodes(&self) -> Nodes<N> {
Nodes {
iter: self.nodes.keys().cloned(),
}
}
pub fn neighbors(&self, a: N) -> Neighbors<N, Ty> {
Neighbors {
iter: match self.nodes.get(&a) {
Some(neigh) => neigh.iter(),
None => [].iter(),
},
ty: self.ty,
}
}
pub fn neighbors_directed(&self, a: N, dir: Direction) -> NeighborsDirected<N, Ty> {
NeighborsDirected {
iter: match self.nodes.get(&a) {
Some(neigh) => neigh.iter(),
None => [].iter(),
},
start_node: a,
dir,
ty: self.ty,
}
}
pub fn edges(&self, from: N) -> Edges<N, E, Ty> {
Edges {
from,
iter: self.neighbors(from),
edges: &self.edges,
}
}
pub fn edge_weight(&self, a: N, b: N) -> Option<&E> {
self.edges.get(&Self::edge_key(a, b))
}
pub fn edge_weight_mut(&mut self, a: N, b: N) -> Option<&mut E> {
self.edges.get_mut(&Self::edge_key(a, b))
}
pub fn all_edges(&self) -> AllEdges<N, E, Ty> {
AllEdges {
inner: self.edges.iter(),
ty: self.ty,
}
}
pub fn all_edges_mut(&mut self) -> AllEdgesMut<N, E, Ty> {
AllEdgesMut {
inner: self.edges.iter_mut(),
ty: self.ty,
}
}
pub fn into_graph<Ix>(self) -> Graph<N, E, Ty, Ix>
where
Ix: crate::graph::IndexType,
{
let mut gr = Graph::with_capacity(self.node_count(), self.edge_count());
for (&node, _) in &self.nodes {
gr.add_node(node);
}
for ((a, b), edge_weight) in self.edges {
let (ai, _, _) = self.nodes.get_full(&a).unwrap();
let (bi, _, _) = self.nodes.get_full(&b).unwrap();
gr.add_edge(node_index(ai), node_index(bi), edge_weight);
}
gr
}
}
impl<N, E, Ty, Item> FromIterator<Item> for GraphMap<N, E, Ty>
where
Item: IntoWeightedEdge<E, NodeId = N>,
N: NodeTrait,
Ty: EdgeType,
{
fn from_iter<I>(iterable: I) -> Self
where
I: IntoIterator<Item = Item>,
{
let iter = iterable.into_iter();
let (low, _) = iter.size_hint();
let mut g = Self::with_capacity(0, low);
g.extend(iter);
g
}
}
impl<N, E, Ty, Item> Extend<Item> for GraphMap<N, E, Ty>
where
Item: IntoWeightedEdge<E, NodeId = N>,
N: NodeTrait,
Ty: EdgeType,
{
fn extend<I>(&mut self, iterable: I)
where
I: IntoIterator<Item = Item>,
{
let iter = iterable.into_iter();
let (low, _) = iter.size_hint();
self.edges.reserve(low);
for elt in iter {
let (source, target, weight) = elt.into_weighted_edge();
self.add_edge(source, target, weight);
}
}
}
macro_rules! iterator_wrap {
($name: ident <$($typarm:tt),*> where { $($bounds: tt)* }
item: $item: ty,
iter: $iter: ty,
) => (
pub struct $name <$($typarm),*> where $($bounds)* {
iter: $iter,
}
impl<$($typarm),*> Iterator for $name <$($typarm),*>
where $($bounds)*
{
type Item = $item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
);
}
iterator_wrap! {
Nodes <'a, N> where { N: 'a + NodeTrait }
item: N,
iter: Cloned<Keys<'a, N, Vec<(N, CompactDirection)>>>,
}
pub struct Neighbors<'a, N, Ty = Undirected>
where
N: 'a,
Ty: EdgeType,
{
iter: Iter<'a, (N, CompactDirection)>,
ty: PhantomData<Ty>,
}
impl<'a, N, Ty> Iterator for Neighbors<'a, N, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type Item = N;
fn next(&mut self) -> Option<N> {
if Ty::is_directed() {
(&mut self.iter)
.filter_map(|&(n, dir)| if dir == Outgoing { Some(n) } else { None })
.next()
} else {
self.iter.next().map(|&(n, _)| n)
}
}
}
pub struct NeighborsDirected<'a, N, Ty>
where
N: 'a,
Ty: EdgeType,
{
iter: Iter<'a, (N, CompactDirection)>,
start_node: N,
dir: Direction,
ty: PhantomData<Ty>,
}
impl<'a, N, Ty> Iterator for NeighborsDirected<'a, N, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type Item = N;
fn next(&mut self) -> Option<N> {
if Ty::is_directed() {
let self_dir = self.dir;
let start_node = self.start_node;
(&mut self.iter)
.filter_map(move |&(n, dir)| {
if dir == self_dir || n == start_node {
Some(n)
} else {
None
}
})
.next()
} else {
self.iter.next().map(|&(n, _)| n)
}
}
}
pub struct Edges<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
Ty: EdgeType,
{
from: N,
edges: &'a IndexMap<(N, N), E>,
iter: Neighbors<'a, N, Ty>,
}
impl<'a, N, E, Ty> Iterator for Edges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, N, &'a E);
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(b) => {
let a = self.from;
match self.edges.get(&GraphMap::<N, E, Ty>::edge_key(a, b)) {
None => unreachable!(),
Some(edge) => Some((a, b, edge)),
}
}
}
}
}
impl<'a, N: 'a, E: 'a, Ty> IntoEdgeReferences for &'a GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type EdgeRef = (N, N, &'a E);
type EdgeReferences = AllEdges<'a, N, E, Ty>;
fn edge_references(self) -> Self::EdgeReferences {
self.all_edges()
}
}
pub struct AllEdges<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
{
inner: IndexMapIter<'a, (N, N), E>,
ty: PhantomData<Ty>,
}
impl<'a, N, E, Ty> Iterator for AllEdges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, N, &'a E);
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
None => None,
Some((&(a, b), v)) => Some((a, b, v)),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
fn count(self) -> usize {
self.inner.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.inner
.nth(n)
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
fn last(self) -> Option<Self::Item> {
self.inner
.last()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
impl<'a, N, E, Ty> DoubleEndedIterator for AllEdges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
pub struct AllEdgesMut<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
{
inner: IndexMapIterMut<'a, (N, N), E>,
ty: PhantomData<Ty>,
}
impl<'a, N, E, Ty> Iterator for AllEdgesMut<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, N, &'a mut E);
fn next(&mut self) -> Option<Self::Item> {
self.inner
.next()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
fn count(self) -> usize {
self.inner.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.inner
.nth(n)
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
fn last(self) -> Option<Self::Item> {
self.inner
.last()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
impl<'a, N, E, Ty> DoubleEndedIterator for AllEdgesMut<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
impl<'a, N: 'a, E: 'a, Ty> IntoEdges for &'a GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type Edges = Edges<'a, N, E, Ty>;
fn edges(self, a: Self::NodeId) -> Self::Edges {
self.edges(a)
}
}
impl<N, E, Ty> Index<(N, N)> for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type Output = E;
fn index(&self, index: (N, N)) -> &E {
let index = Self::edge_key(index.0, index.1);
self.edge_weight(index.0, index.1)
.expect("GraphMap::index: no such edge")
}
}
impl<N, E, Ty> IndexMut<(N, N)> for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
fn index_mut(&mut self, index: (N, N)) -> &mut E {
let index = Self::edge_key(index.0, index.1);
self.edge_weight_mut(index.0, index.1)
.expect("GraphMap::index: no such edge")
}
}
impl<N, E, Ty> Default for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
fn default() -> Self {
GraphMap::with_capacity(0, 0)
}
}
pub struct Ptr<'b, T: 'b>(pub &'b T);
impl<'b, T> Copy for Ptr<'b, T> {}
impl<'b, T> Clone for Ptr<'b, T> {
fn clone(&self) -> Self {
*self
}
}
fn ptr_eq<T>(a: *const T, b: *const T) -> bool {
a == b
}
impl<'b, T> PartialEq for Ptr<'b, T> {
fn eq(&self, other: &Ptr<'b, T>) -> bool {
ptr_eq(self.0, other.0)
}
}
impl<'b, T> PartialOrd for Ptr<'b, T> {
fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'b, T> Ord for Ptr<'b, T> {
fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
let a: *const T = self.0;
let b: *const T = other.0;
a.cmp(&b)
}
}
impl<'b, T> Deref for Ptr<'b, T> {
type Target = T;
fn deref(&self) -> &T {
self.0
}
}
impl<'b, T> Eq for Ptr<'b, T> {}
impl<'b, T> Hash for Ptr<'b, T> {
fn hash<H: hash::Hasher>(&self, st: &mut H) {
let ptr = (self.0) as *const T;
ptr.hash(st)
}
}
impl<'b, T: fmt::Debug> fmt::Debug for Ptr<'b, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl<'a, N, E: 'a, Ty> IntoNodeIdentifiers for &'a GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type NodeIdentifiers = NodeIdentifiers<'a, N, E, Ty>;
fn node_identifiers(self) -> Self::NodeIdentifiers {
NodeIdentifiers {
iter: self.nodes.iter(),
ty: self.ty,
edge_ty: PhantomData,
}
}
}
impl<N, E, Ty> NodeCount for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
fn node_count(&self) -> usize {
(*self).node_count()
}
}
pub struct NodeIdentifiers<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
{
iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>,
ty: PhantomData<Ty>,
edge_ty: PhantomData<E>,
}
impl<'a, N, E, Ty> Iterator for NodeIdentifiers<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = N;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(&n, _)| n)
}
}
impl<'a, N, E, Ty> IntoNodeReferences for &'a GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
type NodeRef = (N, &'a N);
type NodeReferences = NodeReferences<'a, N, E, Ty>;
fn node_references(self) -> Self::NodeReferences {
NodeReferences {
iter: self.nodes.iter(),
ty: self.ty,
edge_ty: PhantomData,
}
}
}
pub struct NodeReferences<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
{
iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>,
ty: PhantomData<Ty>,
edge_ty: PhantomData<E>,
}
impl<'a, N, E, Ty> Iterator for NodeReferences<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, &'a N);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(n, _)| (*n, n))
}
}
impl<N, E, Ty> NodeIndexable for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
fn node_bound(&self) -> usize {
self.node_count()
}
fn to_index(&self, ix: Self::NodeId) -> usize {
let (i, _, _) = self.nodes.get_full(&ix).unwrap();
i
}
fn from_index(&self, ix: usize) -> Self::NodeId {
let (&key, _) = self.nodes.get_index(ix).unwrap();
key
}
}
impl<N, E, Ty> NodeCompactIndexable for GraphMap<N, E, Ty>
where
N: NodeTrait,
Ty: EdgeType,
{
}