//! Simple adjacency list. use crate::data::{Build, DataMap, DataMapMut}; use crate::iter_format::NoPretty; use crate::visit::{ self, EdgeCount, EdgeRef, GetAdjacencyMatrix, IntoEdgeReferences, IntoNeighbors, NodeCount, }; use fixedbitset::FixedBitSet; use std::fmt; use std::ops::Range; #[doc(no_inline)] pub use crate::graph::{DefaultIx, IndexType}; /// Adjacency list node index type, a plain integer. pub type NodeIndex = Ix; /// Adjacency list edge index type, a pair of integers. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct EdgeIndex where Ix: IndexType, { /// Source of the edge. from: NodeIndex, /// Index of the sucessor in the successor list. successor_index: usize, } iterator_wrap! { impl (Iterator) for /// An Iterator over the indices of the outgoing edges from a node. /// /// It does not borrow the graph during iteration. #[derive(Debug, Clone)] struct OutgoingEdgeIndices where { Ix: IndexType } item: EdgeIndex, iter: std::iter::Map, std::iter::Repeat>>, fn((usize, NodeIndex)) -> EdgeIndex>, } /// Weighted sucessor #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] struct WSuc { /// Index of the sucessor. suc: Ix, /// Weight of the edge to `suc`. weight: E, } /// One row of the adjacency list. type Row = Vec>; type RowIter<'a, E, Ix> = std::slice::Iter<'a, WSuc>; iterator_wrap! { impl (Iterator DoubleEndedIterator ExactSizeIterator) for /// An iterator over the indices of the neighbors of a node. #[derive(Debug, Clone)] struct Neighbors<'a, E, Ix> where { Ix: IndexType } item: NodeIndex, iter: std::iter::Map, fn(&WSuc) -> NodeIndex>, } /// A reference to an edge of the graph. #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct EdgeReference<'a, E, Ix: IndexType> { /// index of the edge id: EdgeIndex, /// a reference to the corresponding item in the adjacency list edge: &'a WSuc, } impl<'a, E, Ix: IndexType> Copy for EdgeReference<'a, E, Ix> {} impl<'a, E, Ix: IndexType> Clone for EdgeReference<'a, E, Ix> { fn clone(&self) -> Self { *self } } impl<'a, E, Ix: IndexType> visit::EdgeRef for EdgeReference<'a, E, Ix> { type NodeId = NodeIndex; type EdgeId = EdgeIndex; type Weight = E; fn source(&self) -> Self::NodeId { self.id.from } fn target(&self) -> Self::NodeId { self.edge.suc } fn id(&self) -> Self::EdgeId { self.id } fn weight(&self) -> &Self::Weight { &self.edge.weight } } #[derive(Debug, Clone)] pub struct EdgeIndices<'a, E, Ix: IndexType> { rows: std::iter::Enumerate>>, row_index: usize, row_len: usize, cur: usize, } impl<'a, E, Ix: IndexType> Iterator for EdgeIndices<'a, E, Ix> { type Item = EdgeIndex; fn next(&mut self) -> Option> { loop { if self.cur < self.row_len { let res = self.cur; self.cur += 1; return Some(EdgeIndex { from: Ix::new(self.row_index), successor_index: res, }); } else { match self.rows.next() { Some((index, row)) => { self.row_index = index; self.cur = 0; self.row_len = row.len(); } None => return None, } } } } } iterator_wrap! { impl (Iterator DoubleEndedIterator ExactSizeIterator) for /// An iterator over all node indices in the graph. #[derive(Debug, Clone)] struct NodeIndices where {} item: Ix, iter: std::iter::Map, fn(usize) -> Ix>, } /// An adjacency list with labeled edges. /// /// Can be interpreted as a directed graph /// with unweighted nodes. /// /// This is the most simple adjacency list you can imagine. [`Graph`](../graph/struct.Graph.html), in contrast, /// maintains both the list of successors and predecessors for each node, /// which is a different trade-off. /// /// Allows parallel edges and self-loops. /// /// This data structure is append-only (except for [`clear`](#method.clear)), so indices /// returned at some point for a given graph will stay valid with this same /// graph until it is dropped or [`clear`](#method.clear) is called. /// /// Space consumption: **O(|E|)**. #[derive(Clone, Default)] pub struct List where Ix: IndexType, { suc: Vec>, } impl List { /// Creates a new, empty adjacency list. pub fn new() -> List { List { suc: Vec::new() } } /// Creates a new, empty adjacency list tailored for `nodes` nodes. pub fn with_capacity(nodes: usize) -> List { List { suc: Vec::with_capacity(nodes), } } /// Removes all nodes and edges from the list. pub fn clear(&mut self) { self.suc.clear() } /// Returns the number of edges in the list /// /// Computes in **O(|V|)** time. pub fn edge_count(&self) -> usize { self.suc.iter().map(|x| x.len()).sum() } /// Adds a new node to the list. This allocates a new `Vec` and then should /// run in amortized **O(1)** time. pub fn add_node(&mut self) -> NodeIndex { let i = self.suc.len(); self.suc.push(Vec::new()); Ix::new(i) } /// Adds a new node to the list. This allocates a new `Vec` and then should /// run in amortized **O(1)** time. pub fn add_node_with_capacity(&mut self, successors: usize) -> NodeIndex { let i = self.suc.len(); self.suc.push(Vec::with_capacity(successors)); Ix::new(i) } /// Adds a new node to the list by giving its list of successors and the corresponding /// weigths. pub fn add_node_from_edges, E)>>( &mut self, edges: I, ) -> NodeIndex { let i = self.suc.len(); self.suc .push(edges.map(|(suc, weight)| WSuc { suc, weight }).collect()); Ix::new(i) } /// Add an edge from `a` to `b` to the graph, with its associated /// data `weight`. /// /// Return the index of the new edge. /// /// Computes in **O(1)** time. /// /// **Panics** if the source node does not exist.
/// /// **Note:** `List` allows adding parallel (“duplicate”) edges. If you want /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { if b.index() >= self.suc.len() { panic!( "{} is not a valid node index for a {} nodes adjacency list", b.index(), self.suc.len() ); } let row = &mut self.suc[a.index()]; let rank = row.len(); row.push(WSuc { suc: b, weight }); EdgeIndex { from: a, successor_index: rank, } } fn get_edge(&self, e: EdgeIndex) -> Option<&WSuc> { self.suc .get(e.from.index()) .and_then(|row| row.get(e.successor_index)) } fn get_edge_mut(&mut self, e: EdgeIndex) -> Option<&mut WSuc> { self.suc .get_mut(e.from.index()) .and_then(|row| row.get_mut(e.successor_index)) } /// Accesses the source and target of edge `e` /// /// Computes in **O(1)** pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> { self.get_edge(e).map(|x| (e.from, x.suc)) } pub fn edge_indices_from(&self, a: NodeIndex) -> OutgoingEdgeIndices { let proj: fn((usize, NodeIndex)) -> EdgeIndex = |(successor_index, from)| EdgeIndex { from, successor_index, }; let iter = (0..(self.suc[a.index()].len())) .zip(std::iter::repeat(a)) .map(proj); OutgoingEdgeIndices { iter } } /// Lookups whether there is an edge from `a` to `b`. /// /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. pub fn contains_edge(&self, a: NodeIndex, b: NodeIndex) -> bool { match self.suc.get(a.index()) { None => false, Some(row) => row.iter().any(|x| x.suc == b), } } /// Lookups whether there is an edge from `a` to `b`. /// /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option> { self.suc.get(a.index()).and_then(|row| { row.iter() .enumerate() .find(|(_, x)| x.suc == b) .map(|(i, _)| EdgeIndex { from: a, successor_index: i, }) }) } /// Returns an iterator over all node indices of the graph. /// /// Consuming the whole iterator take **O(|V|)**. pub fn node_indices(&self) -> NodeIndices { NodeIndices { iter: (0..self.suc.len()).map(Ix::new), } } /// Returns an iterator over all edge indices of the graph. /// /// Consuming the whole iterator take **O(|V| + |E|)**. pub fn edge_indices(&self) -> EdgeIndices { EdgeIndices { rows: self.suc.iter().enumerate(), row_index: 0, row_len: 0, cur: 0, } } } /// A very simple adjacency list with no node or label weights. pub type UnweightedList = List<(), Ix>; impl Build for List { /// Adds a new node to the list. This allocates a new `Vec` and then should /// run in amortized **O(1)** time. fn add_node(&mut self, _weight: ()) -> NodeIndex { self.add_node() } /// Add an edge from `a` to `b` to the graph, with its associated /// data `weight`. /// /// Return the index of the new edge. /// /// Computes in **O(1)** time. /// /// **Panics** if the source node does not exist.
/// /// **Note:** `List` allows adding parallel (“duplicate”) edges. If you want /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead. fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> Option> { Some(self.add_edge(a, b, weight)) } /// Updates or adds an edge from `a` to `b` to the graph, with its associated /// data `weight`. /// /// Return the index of the new edge. /// /// Computes in **O(e')** time, where **e'** is the number of successors of `a`. /// /// **Panics** if the source node does not exist.
fn update_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex { let row = &mut self.suc[a.index()]; for (i, info) in row.iter_mut().enumerate() { if info.suc == b { info.weight = weight; return EdgeIndex { from: a, successor_index: i, }; } } let rank = row.len(); row.push(WSuc { suc: b, weight }); EdgeIndex { from: a, successor_index: rank, } } } impl<'a, E, Ix> fmt::Debug for EdgeReferences<'a, E, Ix> where E: fmt::Debug, Ix: IndexType, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut edge_list = f.debug_list(); let iter: Self = self.clone(); for e in iter { if std::mem::size_of::() != 0 { edge_list.entry(&( NoPretty((e.source().index(), e.target().index())), e.weight(), )); } else { edge_list.entry(&NoPretty((e.source().index(), e.target().index()))); } } edge_list.finish() } } impl fmt::Debug for List where E: fmt::Debug, Ix: IndexType, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut fmt_struct = f.debug_struct("adj::List"); fmt_struct.field("node_count", &self.node_count()); fmt_struct.field("edge_count", &self.edge_count()); if self.edge_count() > 0 { fmt_struct.field("edges", &self.edge_references()); } fmt_struct.finish() } } impl visit::GraphBase for List where Ix: IndexType, { type NodeId = NodeIndex; type EdgeId = EdgeIndex; } impl visit::Visitable for List where Ix: IndexType, { type Map = FixedBitSet; fn visit_map(&self) -> FixedBitSet { FixedBitSet::with_capacity(self.node_count()) } fn reset_map(&self, map: &mut Self::Map) { map.clear(); map.grow(self.node_count()); } } impl<'a, E, Ix: IndexType> visit::IntoNodeIdentifiers for &'a List { type NodeIdentifiers = NodeIndices; fn node_identifiers(self) -> NodeIndices { self.node_indices() } } impl visit::NodeRef for NodeIndex { type NodeId = NodeIndex; type Weight = (); fn id(&self) -> Self::NodeId { *self } fn weight(&self) -> &Self::Weight { &() } } impl<'a, Ix: IndexType, E> visit::IntoNodeReferences for &'a List { type NodeRef = NodeIndex; type NodeReferences = NodeIndices; fn node_references(self) -> Self::NodeReferences { self.node_indices() } } impl visit::Data for List { type NodeWeight = (); type EdgeWeight = E; } impl<'a, E, Ix: IndexType> IntoNeighbors for &'a List { type Neighbors = Neighbors<'a, E, Ix>; /// Returns an iterator of all nodes with an edge starting from `a`. /// Panics if `a` is out of bounds. /// Use [`List::edge_indices_from`] instead if you do not want to borrow the adjacency list while /// iterating. fn neighbors(self, a: NodeIndex) -> Self::Neighbors { let proj: fn(&WSuc) -> NodeIndex = |x| x.suc; let iter = self.suc[a.index()].iter().map(proj); Neighbors { iter } } } type SomeIter<'a, E, Ix> = std::iter::Map< std::iter::Zip>, std::iter::Repeat>, fn(((usize, &'a WSuc), Ix)) -> EdgeReference<'a, E, Ix>, >; iterator_wrap! { impl (Iterator) for /// An iterator over the [`EdgeReference`] of all the edges of the graph. struct EdgeReferences<'a, E, Ix> where { Ix: IndexType } item: EdgeReference<'a, E, Ix>, iter: std::iter::FlatMap< std::iter::Enumerate< std::slice::Iter<'a, Row> >, SomeIter<'a, E, Ix>, fn( (usize, &'a Vec>) ) -> SomeIter<'a, E, Ix>, >, } impl<'a, E, Ix: IndexType> Clone for EdgeReferences<'a, E, Ix> { fn clone(&self) -> Self { EdgeReferences { iter: self.iter.clone(), } } } fn proj1( ((successor_index, edge), from): ((usize, &WSuc), Ix), ) -> EdgeReference { let id = EdgeIndex { from, successor_index, }; EdgeReference { id, edge } } fn proj2((row_index, row): (usize, &Vec>)) -> SomeIter { row.iter() .enumerate() .zip(std::iter::repeat(Ix::new(row_index))) .map(proj1 as _) } impl<'a, Ix: IndexType, E> visit::IntoEdgeReferences for &'a List { type EdgeRef = EdgeReference<'a, E, Ix>; type EdgeReferences = EdgeReferences<'a, E, Ix>; fn edge_references(self) -> Self::EdgeReferences { let iter = self.suc.iter().enumerate().flat_map(proj2 as _); EdgeReferences { iter } } } iterator_wrap! { impl (Iterator) for /// Iterator over the [`EdgeReference`] of the outgoing edges from a node. #[derive(Debug, Clone)] struct OutgoingEdgeReferences<'a, E, Ix> where { Ix: IndexType } item: EdgeReference<'a, E, Ix>, iter: SomeIter<'a, E, Ix>, } impl<'a, Ix: IndexType, E> visit::IntoEdges for &'a List { type Edges = OutgoingEdgeReferences<'a, E, Ix>; fn edges(self, a: Self::NodeId) -> Self::Edges { let iter = self.suc[a.index()] .iter() .enumerate() .zip(std::iter::repeat(a)) .map(proj1 as _); OutgoingEdgeReferences { iter } } } impl visit::GraphProp for List { type EdgeType = crate::Directed; fn is_directed(&self) -> bool { true } } impl NodeCount for List { /// Returns the number of nodes in the list /// /// Computes in **O(1)** time. fn node_count(&self) -> usize { self.suc.len() } } impl EdgeCount for List { /// Returns the number of edges in the list /// /// Computes in **O(|V|)** time. fn edge_count(&self) -> usize { List::edge_count(self) } } impl visit::NodeIndexable for List { fn node_bound(&self) -> usize { self.node_count() } #[inline] fn to_index(&self, a: Self::NodeId) -> usize { a.index() } #[inline] fn from_index(&self, i: usize) -> Self::NodeId { Ix::new(i) } } impl visit::NodeCompactIndexable for List {} impl DataMap for List { fn node_weight(&self, n: Self::NodeId) -> Option<&()> { if n.index() < self.suc.len() { Some(&()) } else { None } } /// Accesses the weight of edge `e` /// /// Computes in **O(1)** fn edge_weight(&self, e: EdgeIndex) -> Option<&E> { self.get_edge(e).map(|x| &x.weight) } } impl DataMapMut for List { fn node_weight_mut(&mut self, n: Self::NodeId) -> Option<&mut ()> { if n.index() < self.suc.len() { // A hack to produce a &'static mut () // It does not actually allocate according to godbolt let b = Box::new(()); Some(Box::leak(b)) } else { None } } /// Accesses the weight of edge `e` /// /// Computes in **O(1)** fn edge_weight_mut(&mut self, e: EdgeIndex) -> Option<&mut E> { self.get_edge_mut(e).map(|x| &mut x.weight) } } /// The adjacency matrix for **List** is a bitmap that's computed by /// `.adjacency_matrix()`. impl GetAdjacencyMatrix for List where Ix: IndexType, { type AdjMatrix = FixedBitSet; fn adjacency_matrix(&self) -> FixedBitSet { let n = self.node_count(); let mut matrix = FixedBitSet::with_capacity(n * n); for edge in self.edge_references() { let i = edge.source().index() * n + edge.target().index(); matrix.put(i); let j = edge.source().index() + n * edge.target().index(); matrix.put(j); } matrix } fn is_adjacent(&self, matrix: &FixedBitSet, a: NodeIndex, b: NodeIndex) -> bool { let n = self.edge_count(); let index = n * a.index() + b.index(); matrix.contains(index) } }