blob: 3ddc677395eee8fc14f715f079337fb9589a59c6 [file] [log] [blame]
mod compat;
mod directed;
mod insert;
mod resize;
mod retain;
mod reverse;
use error_stack::Result;
use crate::{
edge::{DetachedEdge, Edge, EdgeId, EdgeMut},
node::{DetachedNode, Node, NodeId, NodeMut},
storage::GraphStorage,
};
/// A graph, which is generic over its storage.
///
/// This is the central point of interaction with `petgraph`, allowing for consistent access to a
/// graph, without worrying about the underlying storage implementations.
///
/// Limitations of the underlying storage implementation apply, meaning that some operations may be
/// more expensive than others, or certain capabilities such as parallel edges may not be available.
///
/// Each graph storage implementation has a section with more information about its capabilities.
///
/// For convenience each graph storage implementation has a type alias for the graph type, which
/// uses the implementation, such as [`DinoGraph`], [`DiDinoGraph`], and [`UnDinoGraph`] in
/// `petgraph-dino`.
///
/// Instead of relying on a single storage implementation, this design encourages (and recommends)
/// the use of `S` as a generic parameter for functions receiving a graph.
///
/// `petgraph` assumes that a directed graph is simply a specialization of an undirected graph where
/// edges have an additional property marking the directionality of the edge. This means that any
/// directed graph also necessarily implements the undirected graph interface, known simply as
/// [`GraphStorage`]. This is similar to other graph libraries such as `networkx` and `igraph`.
///
/// Endpoints of an edge are known as `u` and `v` in `petgraph`, where `u` and `v` are
/// interchangeable in an undirected graph, and `u` is the source and `v` is the target in a
/// directed graph.
///
/// # Storage Implementations
// TODO
///
/// # Example
///
/// ```
/// use petgraph_core::{
/// edge::marker::{Directed, Undirected},
/// Graph, GraphStorage,
/// };
/// use petgraph_dino::{DiDinoGraph, DinoGraph, DinoStorage, UnDinoGraph};
///
/// // we're using explicit generics here to illustrate the difference more clearly, but also
/// // because we do not insert/remove any nodes or edges, which means we cannot infer those types.
///
/// let digraph = Graph::<DinoStorage<u8, u8, Directed>>::new();
/// // ^ same as:
/// let digraph = DinoGraph::<u8, u8, Directed>::new();
/// // ^ same as:
/// let digraph = DiDinoGraph::<u8, u8>::new();
///
/// let ungraph = Graph::<DinoStorage<u8, u8, Undirected>>::new();
/// // ^ same as:
/// let ungraph = DinoGraph::<u8, u8, Undirected>::new();
/// // ^ same as:
/// let ungraph = UnDinoGraph::<u8, u8>::new();
///
/// fn sum_node_weights<S>(graph: &Graph<S>) -> u8
/// where
/// S: GraphStorage<NodeWeight = u8>,
/// {
/// graph.nodes().map(|node| *node.weight()).sum()
/// }
///
/// assert_eq!(sum_node_weights(&digraph), 0);
/// assert_eq!(sum_node_weights(&ungraph), 0);
/// ```
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Graph<S> {
storage: S,
}
impl<S> Default for Graph<S>
where
S: GraphStorage,
{
fn default() -> Self {
Self::new()
}
}
impl<S> Graph<S>
where
S: GraphStorage,
{
/// Create a new graph on-top of the given storage.
///
/// # Example
///
/// ```
/// use petgraph_core::{
/// edge::marker::{Directed, Undirected},
/// Graph, GraphStorage,
/// };
/// use petgraph_dino::DinoStorage;
///
/// let storage = DinoStorage::<u8, u8, Directed>::with_capacity(None, None);
/// let graph = Graph::new_in(storage);
/// // ^ this is the same as `Graph::new()`
/// # assert_eq!(graph.num_nodes(), 0);
/// # assert_eq!(graph.num_edges(), 0);
/// ```
#[must_use]
pub const fn new_in(storage: S) -> Self {
Self { storage }
}
/// Creates a new graph with the default capacity.
///
/// The default capacity is `None` for both nodes and edges.
///
/// # Example
///
/// ```
/// use petgraph_core::{edge::marker::Undirected, Graph};
/// use petgraph_dino::DinoStorage;
///
/// let graph = Graph::<DinoStorage<u8, u8, Undirected>>::new();
/// # assert_eq!(graph.num_nodes(), 0);
/// # assert_eq!(graph.num_edges(), 0);
/// ```
#[must_use]
pub fn new() -> Self {
Self::new_in(S::with_capacity(None, None))
}
/// Creates a new graph with the given capacity.
///
/// Helpful in cases where the number of nodes and edges is known in advance, and one wants to
/// avoid reallocations.
/// Be aware that some storage implementations may not support this and may not be able to
/// provide the requested capacity in advance.
///
/// # Example
///
/// ```
/// use petgraph_core::{edge::marker::Undirected, Graph};
/// use petgraph_dino::DinoStorage;
///
/// let graph = Graph::<DinoStorage<u8, u8, Undirected>>::with_capacity(Some(16), Some(16));
/// # assert_eq!(graph.num_nodes(), 0);
/// # assert_eq!(graph.num_edges(), 0);
/// ```
#[must_use]
pub fn with_capacity(node_capacity: Option<usize>, edge_capacity: Option<usize>) -> Self {
Self::new_in(S::with_capacity(node_capacity, edge_capacity))
}
/// Returns a reference to the underlying storage.
///
/// # Example
///
/// ```
/// use petgraph_core::{
/// edge::marker::{Directed, Undirected},
/// Graph, GraphStorage,
/// };
/// use petgraph_dino::DinoStorage;
///
/// let storage = DinoStorage::<u8, u8, Directed>::with_capacity(None, None);
/// let graph = Graph::new_in(storage);
///
/// assert_eq!(graph.storage().num_nodes(), 0);
/// assert_eq!(graph.storage().num_edges(), 0);
/// ```
pub const fn storage(&self) -> &S {
&self.storage
}
/// Returns the underlying storage.
///
/// # Example
///
/// ```
/// use petgraph_core::{
/// edge::marker::{Directed, Undirected},
/// Graph, GraphStorage,
/// };
/// use petgraph_dino::DinoStorage;
///
/// let storage = DinoStorage::<u8, u8, Directed>::with_capacity(None, None);
/// let graph = Graph::new_in(storage);
///
/// let storage = graph.into_storage();
/// assert_eq!(storage.num_nodes(), 0);
/// assert_eq!(storage.num_edges(), 0);
/// ```
pub fn into_storage(self) -> S {
self.storage
}
/// Create a new graph from the given nodes and edges.
///
/// Takes two iterators, one for nodes and one for edges, and returns a new graph with the given
/// nodes and edges, if the iterator is well-formed.
/// This is the reverse operation to [`Self::into_parts`], which converts a graph into its
/// parts.
///
/// The resulting graph may change the order of the nodes and edges and reassign their IDs.
/// The only properties that stay consistent are the weights and the structural equivalence of
/// the graph.
/// For more information see [`GraphStorage::from_parts`].
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use petgraph_dino::DiDinoGraph;
///
/// let mut other = DiDinoGraph::new();
/// let a = *other.insert_node(0).id();
/// let b = *other.insert_node(1).id();
/// let c = *other.insert_node(2).id();
///
/// other.insert_edge(u8::MAX, &a, &b);
/// other.insert_edge(u8::MAX - 1, &b, &c);
///
/// let other = other.into_parts();
///
/// let graph = DiDinoGraph::from_parts(other.0, other.1).unwrap();
/// assert_eq!(graph.num_nodes(), 3);
/// assert_eq!(graph.num_edges(), 2);
///
/// assert_eq!(
/// graph
/// .nodes()
/// .map(|node| *node.weight())
/// .collect::<HashSet<_>>(),
/// [0, 1, 2].into_iter().collect::<HashSet<_>>(),
/// );
///
/// let a = *graph.nodes().find(|node| *node.weight() == 0).unwrap().id();
/// let b = *graph.nodes().find(|node| *node.weight() == 1).unwrap().id();
/// let c = *graph.nodes().find(|node| *node.weight() == 2).unwrap().id();
///
/// assert_eq!(
/// graph
/// .edges()
/// .map(|edge| (*edge.weight(), edge.endpoint_ids()))
/// .collect::<HashSet<_>>(),
/// [(u8::MAX, (&a, &b)), (u8::MAX - 1, (&b, &c))]
/// .into_iter()
/// .collect::<HashSet<_>>(),
/// );
/// ```
///
/// # Errors
///
/// If any of the nodes or edges are invalid, or any of the constraint checks of the underlying
/// implementation fail, an error is returned.
pub fn from_parts(
nodes: impl IntoIterator<Item = DetachedNode<S::NodeWeight>>,
edges: impl IntoIterator<Item = DetachedEdge<S::EdgeWeight>>,
) -> Result<Self, S::Error> {
Ok(Self {
storage: S::from_parts(nodes, edges)?,
})
}
/// Converts the graph into its parts.
///
/// This is the reverse operation to [`Self::from_parts`], which creates a graph from its parts.
///
/// The iterables returned by this function are not guaranteed to be in any particular order,
/// but must contain all nodes and edges.
///
/// For more information see [`GraphStorage::into_parts`].
///
/// # Example
///
/// ```
/// use std::collections::HashSet;
///
/// use petgraph_core::{DetachedEdge, DetachedNode};
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
///
/// let (nodes, edges) = graph.into_parts();
/// let (nodes, edges) = (
/// nodes
/// .into_iter()
/// .map(|node| node.weight)
/// .collect::<HashSet<_>>(),
/// edges
/// .into_iter()
/// .map(|edge| edge.weight)
/// .collect::<HashSet<_>>(),
/// );
///
/// assert_eq!(nodes.len(), 3);
/// assert_eq!(edges.len(), 2);
///
/// assert_eq!(nodes, [0, 1, 2].into_iter().collect::<HashSet<_>>());
/// assert_eq!(
/// edges,
/// [u8::MAX, u8::MAX - 1].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn into_parts(
self,
) -> (
impl IntoIterator<Item = DetachedNode<S::NodeWeight>>,
impl IntoIterator<Item = DetachedEdge<S::EdgeWeight>>,
) {
self.storage.into_parts()
}
/// Converts the graph into a graph with a different storage implementation.
///
/// Internally this simply calls [`GraphStorage::into_parts`] on `S` and then calls
/// [`Graph::from_parts`] on `T`.
///
/// # Errors
///
/// If any of the nodes or edges are invalid, or any of the constraint checks of the new storage
/// implementation fail, an error is returned.
///
/// An example would be switching between a storage implementation that supports parallel edges
/// to one that does not.
// TODO: example
pub fn convert<T>(self) -> Result<Graph<T>, T::Error>
where
T: GraphStorage<NodeWeight = S::NodeWeight, EdgeWeight = S::EdgeWeight>,
{
let (nodes, edges) = self.storage.into_parts();
Graph::from_parts(nodes, edges)
}
/// Returns the number of nodes in the graph.
///
/// This is generally faster than iterating over all nodes and counting them via
/// `self.nodes().count()`.
///
/// # Example
///
/// ```
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
///
/// assert_eq!(graph.num_nodes(), 3);
/// ```
pub fn num_nodes(&self) -> usize {
self.storage.num_nodes()
}
/// Returns the number of edges in the graph.
///
/// This is generally faster than iterating over all edges and counting them via
/// `self.edges().count()`.
///
/// # Example
///
/// ```
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
///
/// assert_eq!(graph.num_edges(), 2);
/// ```
pub fn num_edges(&self) -> usize {
self.storage.num_edges()
}
/// Returns `true` if the graph has no nodes or edges.
///
/// # Example
///
/// ```
/// use petgraph_dino::DiDinoGraph;
///
/// // we need to explicitly state the type of the edge weights, as we do insert any edges and
/// // therefore cannot infer them.
/// let mut graph = DiDinoGraph::<_, u8>::new();
/// assert!(graph.is_empty());
///
/// let a = *graph.insert_node(0).id();
/// assert!(!graph.is_empty());
///
/// graph.remove_node(&a);
/// assert!(graph.is_empty());
/// ```
pub fn is_empty(&self) -> bool {
self.num_nodes() == 0 && self.num_edges() == 0
}
/// Clears the graph, removing all nodes and edges.
///
/// # Example
///
/// ```
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
///
/// assert!(!graph.is_empty());
///
/// graph.clear();
///
/// assert!(graph.is_empty());
/// ```
pub fn clear(&mut self) {
self.storage.clear();
}
/// Returns the node with the given identifier, if it exists.
///
/// The returned [`Node`] has a reference to the current graph, meaning that you're able to
/// query for neighbours and [`Edge`]s on the returned value directly.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// // we need to explicitly state the type of the edge weights, as we do insert
/// // any edges and therefore cannot infer them.
/// let mut graph = DiDinoGraph::<_, u8>::new();
/// let a = *graph.insert_node(0).id();
/// # let b = graph.storage().next_node_id(NoValue::new());
///
/// assert_eq!(
/// graph.node(&a).map(|node| (*node.id(), *node.weight())),
/// Some((a, 0))
/// );
/// assert_eq!(
/// graph.node(&b).map(|node| (*node.id(), *node.weight())),
/// None
/// );
/// ```
pub fn node(&self, id: NodeId) -> Option<Node<S>> {
self.storage.node(id)
}
/// Returns the node, with a mutable weight, with the given identifier, if it exists.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// // we need to explicitly state the type of the edge weights, as we do insert
/// // any edges and therefore cannot infer them.
/// let mut graph = DiDinoGraph::<_, u8>::new();
/// let a = *graph.insert_node(0).id();
/// # let b = graph.storage().next_node_id(NoValue::new());
///
/// if let Some(mut node) = graph.node_mut(&a) {
/// *node.weight_mut() = 1;
/// }
///
/// assert_eq!(
/// graph.node(&a).map(|node| (*node.id(), *node.weight())),
/// Some((a, 1))
/// );
///
/// assert!(graph.node_mut(&b).is_none());
/// ```
pub fn node_mut(&mut self, id: NodeId) -> Option<NodeMut<S>> {
self.storage.node_mut(id)
}
/// Returns `true` if the graph contains a node with the given identifier.
///
/// This is generally faster than calling `self.node(id).is_some()`.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// // we need to explicitly state the type of the edge weights, as we do insert
/// // any edges and therefore cannot infer them.
/// let mut graph = DiDinoGraph::<_, u8>::new();
/// let a = *graph.insert_node(0).id();
/// # let b = graph.storage().next_node_id(NoValue::new());
///
/// assert!(graph.contains_node(&a));
/// assert!(!graph.contains_node(&b));
/// ```
pub fn contains_node(&self, id: NodeId) -> bool {
self.storage.contains_node(id)
}
/// Removes the node with the given identifier, if it exists.
///
/// This will return the detached representation of the node, which can be used to reinsert the
/// node into a new graph _or_ used to access any of the properties independently of the graph.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{DetachedNode, GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// // we need to explicitly state the type of the edge weights, as we do insert
/// // any edges and therefore cannot infer them.
/// let mut graph = DiDinoGraph::<_, u8>::new();
/// let a = *graph.insert_node(0).id();
/// # let b = graph.storage().next_node_id(NoValue::new());
///
/// assert_eq!(
/// graph.remove_node(&a),
/// Some(DetachedNode { id: a, weight: 0 })
/// );
/// assert_eq!(graph.remove_node(&a), None);
/// assert_eq!(graph.remove_node(&b), None);
/// ```
pub fn remove_node(&mut self, id: NodeId) -> Option<DetachedNode<S::NodeWeight>> {
self.storage.remove_node(id)
}
/// Returns the edge with the given identifier, if it exists.
///
/// The returned [`Edge`] has a reference to the current graph, meaning that you're able to
/// query the [`Node`] endpoints directly on the edge.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{DetachedNode, GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// # let bc = graph.storage().next_edge_id(NoValue::new());
///
/// assert_eq!(
/// graph
/// .edge(&ab)
/// .map(|edge| (*edge.id(), *edge.weight(), edge.endpoint_ids())),
/// Some((ab, u8::MAX, (&a, &b)))
/// );
/// assert!(graph.edge(&bc).is_none());
/// ```
pub fn edge(&self, id: EdgeId) -> Option<Edge<S>> {
self.storage.edge(id)
}
/// Returns the edge, with a mutable weight, with the given identifier, if it exists.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{DetachedNode, GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// # let bc = graph.storage().next_edge_id(NoValue::new());
///
/// if let Some(mut edge) = graph.edge_mut(&ab) {
/// *edge.weight_mut() = u8::MAX - 1;
/// }
///
/// assert_eq!(
/// graph
/// .edge(&ab)
/// .map(|edge| (*edge.id(), *edge.weight(), edge.endpoint_ids())),
/// Some((ab, u8::MAX - 1, (&a, &b)))
/// );
/// assert!(graph.edge_mut(&bc).is_none());
/// ```
pub fn edge_mut(&mut self, id: EdgeId) -> Option<EdgeMut<S>> {
self.storage.edge_mut(id)
}
/// Returns `true` if the graph contains an edge with the given identifier.
///
/// This is generally faster than calling `self.edge(id).is_some()`.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{DetachedNode, GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// # let bc = graph.storage().next_edge_id(NoValue::new());
///
/// assert!(graph.contains_edge(&ab));
/// assert!(!graph.contains_edge(&bc));
/// ```
pub fn contains_edge(&self, id: EdgeId) -> bool {
self.storage.contains_edge(id)
}
/// Removes the edge with the given identifier, if it exists.
///
/// This will return the detached representation of the edge, which can be used to reinsert the
/// edge into a new graph _or_ used to access any of the properties independently of the graph.
///
/// # Example
///
/// ```
/// # use petgraph_core::attributes::NoValue;
/// # use petgraph_core::{DetachedEdge, DetachedNode, GraphStorage, Node};
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// # let bc = graph.storage().next_edge_id(NoValue::new());
///
/// assert_eq!(
/// graph.remove_edge(&ab),
/// Some(DetachedEdge {
/// id: ab,
/// weight: u8::MAX,
/// u: a,
/// v: b,
/// })
/// );
/// assert_eq!(graph.remove_edge(&ab), None);
/// assert_eq!(graph.remove_edge(&bc), None);
/// ```
pub fn remove_edge(&mut self, id: EdgeId) -> Option<DetachedEdge<S::EdgeWeight>> {
self.storage.remove_edge(id)
}
/// Returns the neighbours of the node with the given identifier.
///
/// This is an alias for [`Self::neighbours`], as there's a spelling difference between the
/// American and British English.
#[inline]
pub fn neighbors(&self, id: NodeId) -> impl Iterator<Item = Node<'_, S>> {
self.neighbours(id)
}
/// Returns the neighbours of the node with the given identifier.
///
/// Returns an iterator over all nodes that are connected to the given node.
/// In the case of a directed graph all edges (both incoming and outgoing) are taken into
/// account.
///
/// If the graph allows self-loops, and a self-loop exists, then the node will be returned
/// as its own neighbour.
///
/// The results won't be in any particular order.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
/// let ca = *graph.insert_edge(u8::MAX - 2, &c, &a).id();
/// let aa = *graph.insert_edge(u8::MAX - 3, &a, &a).id();
///
/// assert_eq!(
/// graph
/// .neighbours(&a)
/// .map(|node| *node.id())
/// .collect::<HashSet<_>>(),
/// [a, b, c].into_iter().collect::<HashSet<_>>()
/// );
/// assert_eq!(
/// graph
/// .neighbours(&b)
/// .map(|node| *node.id())
/// .collect::<HashSet<_>>(),
/// [a, c].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn neighbours(&self, id: NodeId) -> impl Iterator<Item = Node<'_, S>> {
self.storage.node_neighbours(id)
}
/// Returns the neighbours of the node with the given identifier, with mutable weights.
///
/// This is an alias for [`Self::neighbours_mut`], as there's a spelling difference between
/// American and British English.
#[inline]
pub fn neighbors_mut(&mut self, id: NodeId) -> impl Iterator<Item = NodeMut<'_, S>> {
self.neighbours_mut(id)
}
/// Returns the neighbours of the node with the given identifier, with mutable weights.
///
/// Returns an iterator over all nodes that are connected to the given node.
/// In the case of a directed graph all edges (both incoming and outgoing) are taken into
/// account.
///
/// If the graph allows self-loops, and a self-loop exists, then the node will be returned as
/// well.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
/// let d = *graph.insert_node(3).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
/// let ca = *graph.insert_edge(u8::MAX - 2, &c, &a).id();
/// let aa = *graph.insert_edge(u8::MAX - 3, &a, &a).id();
///
/// for mut node in graph.neighbours_mut(&a) {
/// *node.weight_mut() += 16;
/// }
///
/// assert_eq!(
/// graph
/// .neighbours(&a)
/// .map(|node| (*node.id(), *node.weight()))
/// .collect::<HashSet<_>>(),
/// [(a, 16), (b, 17), (c, 18)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// assert_eq!(
/// graph.node(&d).map(|node| (*node.id(), *node.weight())),
/// Some((d, 3))
/// );
/// ```
pub fn neighbours_mut(&mut self, id: NodeId) -> impl Iterator<Item = NodeMut<'_, S>> {
self.storage.node_neighbours_mut(id)
}
/// Returns the edges that are connected to the node with the given identifier.
///
/// Returns an iterator over all edges that are connected to the given node.
/// In the case of a directed graph this will return an iterator over all incoming and outgoing
/// edges.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
/// let d = *graph.insert_node(3).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
/// let ca = *graph.insert_edge(u8::MAX - 2, &c, &a).id();
/// let aa = *graph.insert_edge(u8::MAX - 3, &a, &a).id();
///
/// assert_eq!(
/// graph
/// .connections(&a)
/// .map(|edge| *edge.id())
/// .collect::<HashSet<_>>(),
/// [ab, ca, aa].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn connections(&self, id: NodeId) -> impl Iterator<Item = Edge<'_, S>> {
self.storage.node_connections(id)
}
/// Returns the edges that are connected to the node with the given identifier, with mutable
/// weights.
///
/// Returns an iterator over all edges that are connected to the given node.
/// In the case of a directed graph this will return an iterator over all incoming and outgoing
/// edges.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
/// let d = *graph.insert_node(3).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
/// let ca = *graph.insert_edge(u8::MAX - 2, &c, &a).id();
/// let aa = *graph.insert_edge(u8::MAX - 3, &a, &a).id();
///
/// for mut edge in graph.connections_mut(&a) {
/// *edge.weight_mut() -= 16;
/// }
///
/// assert_eq!(
/// graph
/// .connections(&a)
/// .map(|edge| (*edge.id(), *edge.weight()))
/// .collect::<HashSet<_>>(),
/// [(ab, u8::MAX - 16), (ca, u8::MAX - 18), (aa, u8::MAX - 19)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// assert_eq!(
/// graph.edge(&bc).map(|edge| (*edge.id(), *edge.weight())),
/// Some((bc, u8::MAX - 1))
/// );
/// ```
pub fn connections_mut(&mut self, id: NodeId) -> impl Iterator<Item = EdgeMut<'_, S>> {
self.storage.node_connections_mut(id)
}
/// Returns the degree of the node with the given identifier.
///
/// This is the number of edges that are connected to the given node, sometimes referred to as
/// valency.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
/// let d = *graph.insert_node(3).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let bc = *graph.insert_edge(u8::MAX - 1, &b, &c).id();
/// let ca = *graph.insert_edge(u8::MAX - 2, &c, &a).id();
/// let aa = *graph.insert_edge(u8::MAX - 3, &a, &a).id();
///
/// assert_eq!(graph.degree(&a), 3);
/// assert_eq!(graph.degree(&b), 2);
/// assert_eq!(graph.degree(&c), 2);
/// assert_eq!(graph.degree(&d), 0);
/// ```
pub fn degree(&self, id: NodeId) -> usize {
self.storage.node_degree(id)
}
// TODO: `map`, `filter`, `filter_map`, `find`, `reverse`, `any`, `all`, etc.
/// Returns all edges that are between the given
///
/// Returns an iterator over all edges that are between the given nodes.
/// In the case of a directed graph this will return an iterator over both `u → v` and `v → u`.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
/// let bc = *graph.insert_edge(u8::MAX - 2, &b, &c).id();
///
/// assert_eq!(
/// graph
/// .edges_between(&a, &b)
/// .map(|edge| *edge.id())
/// .collect::<HashSet<_>>(),
/// [ab, ba].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn edges_between(&self, u: NodeId, v: NodeId) -> impl Iterator<Item = Edge<'_, S>> {
self.storage.edges_between(u, v)
}
/// Returns all edges that are between the given nodes, with mutable weights.
///
/// Returns an iterator over all edges that are between the given nodes.
/// In the case of a directed graph this will return an iterator over both `u → v` and `v → u`.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
/// let bc = *graph.insert_edge(u8::MAX - 2, &b, &c).id();
///
/// for mut edge in graph.edges_between_mut(&a, &b) {
/// *edge.weight_mut() -= 16;
/// }
///
/// assert_eq!(
/// graph
/// .edges()
/// .map(|edge| (*edge.id(), *edge.weight()))
/// .collect::<HashSet<_>>(),
/// [(ab, u8::MAX - 16), (ba, u8::MAX - 17), (bc, u8::MAX - 2),]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// ```
pub fn edges_between_mut(
&mut self,
u: NodeId,
v: NodeId,
) -> impl Iterator<Item = EdgeMut<'_, S>> {
self.storage.edges_between_mut(u, v)
}
/// Returns all nodes that have no edges connected to them.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// assert_eq!(
/// graph
/// .isolated_nodes()
/// .map(|node| *node.id())
/// .collect::<HashSet<_>>(),
/// [c].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn isolated_nodes(&self) -> impl Iterator<Item = Node<S>> {
self.storage.isolated_nodes()
}
/// Returns all nodes that have no edges connected to them, with mutable weights.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// for mut node in graph.isolated_nodes_mut() {
/// *node.weight_mut() += 16;
/// }
///
/// assert_eq!(
/// graph
/// .nodes()
/// .map(|node| (*node.id(), *node.weight()))
/// .collect::<HashSet<_>>(),
/// [(a, 0), (b, 1), (c, 18)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// ```
pub fn isolated_nodes_mut(&mut self) -> impl Iterator<Item = NodeMut<S>> {
self.storage.isolated_nodes_mut()
}
/// Returns an iterator over all nodes in the graph.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// assert_eq!(
/// graph
/// .nodes()
/// .map(|node| (*node.id(), *node.weight()))
/// .collect::<HashSet<_>>(),
/// [(a, 0), (b, 1), (c, 2)].into_iter().collect::<HashSet<_>>()
/// );
/// ```
pub fn nodes(&self) -> impl Iterator<Item = Node<S>> {
self.storage.nodes()
}
/// Returns an iterator over all nodes in the graph, with mutable weights.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// for mut node in graph.nodes_mut() {
/// *node.weight_mut() += 16;
/// }
///
/// assert_eq!(
/// graph
/// .nodes()
/// .map(|node| (*node.id(), *node.weight()))
/// .collect::<HashSet<_>>(),
/// [(a, 16), (b, 17), (c, 18)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// ```
pub fn nodes_mut(&mut self) -> impl Iterator<Item = NodeMut<S>> {
self.storage.nodes_mut()
}
/// Returns an iterator over all edges in the graph.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// assert_eq!(
/// graph
/// .edges()
/// .map(|edge| (*edge.id(), *edge.weight()))
/// .collect::<HashSet<_>>(),
/// [(ab, u8::MAX), (ba, u8::MAX - 1)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// ```
pub fn edges(&self) -> impl Iterator<Item = Edge<S>> {
self.storage.edges()
}
/// Returns an iterator over all edges in the graph, with mutable weights.
///
/// # Example
///
/// ```
/// # use std::collections::HashSet;
/// use petgraph_dino::DiDinoGraph;
///
/// let mut graph = DiDinoGraph::new();
/// let a = *graph.insert_node(0).id();
/// let b = *graph.insert_node(1).id();
/// let c = *graph.insert_node(2).id();
///
/// let ab = *graph.insert_edge(u8::MAX, &a, &b).id();
/// let ba = *graph.insert_edge(u8::MAX - 1, &b, &a).id();
///
/// for mut edge in graph.edges_mut() {
/// *edge.weight_mut() -= 16;
/// }
///
/// assert_eq!(
/// graph
/// .edges()
/// .map(|edge| (*edge.id(), *edge.weight()))
/// .collect::<HashSet<_>>(),
/// [(ab, u8::MAX - 16), (ba, u8::MAX - 17)]
/// .into_iter()
/// .collect::<HashSet<_>>()
/// );
/// ```
pub fn edges_mut(&mut self) -> impl Iterator<Item = EdgeMut<S>> {
self.storage.edges_mut()
}
}