use crate::{
error::{AddEdgeError, InvalidEdgeError, NodeExistsError, RemoveNodeError},
graph::entry::{Entry, OccupiedEntry, VacantEntry},
map::{ExtKeyMap, IntKeyMap, Map, MapEntry, MapWithCapacity, MapWithEntry, OrderedKeyMap},
};
use core::{
borrow::{Borrow, BorrowMut},
fmt::Debug,
mem,
ops::{Deref, DerefMut, RangeBounds},
};
#[cfg(feature = "rayon")]
use {
crate::{
map::ParIterMap,
util::{EdgeMapFn, EdgeMapMutFn, ParNodeWeightIter, ParNodeWeightIterMut},
},
rayon::iter::Map as ParMap,
};
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Node<N, EI: Copy + Eq + Debug + 'static> {
weight: N,
next_incoming_edge: Option<EI>,
next_outgoing_edge: Option<EI>,
}
impl<N, EI: Copy + Eq + Debug + 'static> Node<N, EI> {
pub fn weight(&self) -> &N {
&self.weight
}
pub fn weight_mut(&mut self) -> &mut N {
&mut self.weight
}
pub fn walk_outputs(&self) -> iter::WalkOutputs<EI> {
iter::WalkOutputs {
next: self.next_outgoing_edge,
}
}
pub fn walk_inputs(&self) -> iter::WalkInputs<EI> {
iter::WalkInputs {
next: self.next_incoming_edge,
}
}
pub fn walk_successors(&self) -> iter::WalkSuccessors<EI> {
iter::WalkSuccessors {
next: self.next_outgoing_edge,
}
}
pub fn walk_predecessors(&self) -> iter::WalkPredecessors<EI> {
iter::WalkPredecessors {
next: self.next_incoming_edge,
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Edge<E, NI, EI>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
{
weight: E,
from: NI,
to: NI,
next_incoming_edge: Option<EI>,
next_outgoing_edge: Option<EI>,
}
impl<E, NI, EI> Edge<E, NI, EI>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
{
pub fn weight(&self) -> &E {
&self.weight
}
pub fn weight_mut(&mut self) -> &mut E {
&mut self.weight
}
pub fn from(&self) -> NI {
self.from
}
pub fn to(&self) -> NI {
self.to
}
}
fn find_edge_impl<E, NI, EI, EM>(
edges: &Edges<E, NI, EI, EM>,
first_index: Option<EI>,
to: NI,
) -> Option<EI>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
let mut next_edge_index = first_index;
while let Some(edge_index) = next_edge_index {
let edge = edges.get(edge_index).expect("edge list is broken");
if edge.to == to {
return Some(edge_index);
}
next_edge_index = edge.next_outgoing_edge;
}
None
}
fn insert_edge_impl<N, E, NI, EI, NM, EM, RF, ERR>(
graph: &mut FrozenGraph<N, E, NI, EI, NM, EM>,
from: NI,
to: NI,
weight: E,
replace: RF,
) -> Result<(EI, Option<E>), ERR>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
RF: FnOnce(E, EI, &mut Edges<E, NI, EI, EM>) -> Result<E, ERR>,
ERR: From<InvalidEdgeError>,
{
let from_node = graph
.nodes
.get_mut(from)
.ok_or(InvalidEdgeError::InvalidSourceIndex)?;
if let Some(edge_index) = find_edge_impl(&graph.edges, from_node.next_outgoing_edge, to) {
if !graph.nodes.contains_key(to) {
return Err(InvalidEdgeError::InvalidDestIndex.into());
}
let old_weight = replace(weight, edge_index, &mut graph.edges)?;
Ok((edge_index, Some(old_weight)))
} else {
let index = insert_edge(&mut graph.nodes.map, &mut graph.edges.map, from, to, weight)?;
Ok((index, None))
}
}
fn insert_edge<N, E, NI, EI, NM, EM>(
nodes: &mut NM,
edges: &mut EM,
from: NI,
to: NI,
weight: E,
) -> Result<EI, InvalidEdgeError>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
let edge_index = edges.insert(Edge {
weight,
from,
to,
next_incoming_edge: None,
next_outgoing_edge: None,
});
let next_outgoing_edge = nodes
.get_mut(from)
.ok_or_else(|| {
edges.remove(edge_index);
InvalidEdgeError::InvalidSourceIndex
})
.map(|node| node.next_outgoing_edge.replace(edge_index))?;
if let Some(node) = nodes.get_mut(to) {
let next_incoming_edge = node.next_incoming_edge.replace(edge_index);
let edge = edges.get_mut(edge_index).expect("invalid edge map state");
edge.next_outgoing_edge = next_outgoing_edge;
edge.next_incoming_edge = next_incoming_edge;
Ok(edge_index)
} else {
edges.remove(edge_index);
nodes
.get_mut(from)
.expect("invalid node map state")
.next_outgoing_edge = next_outgoing_edge;
Err(InvalidEdgeError::InvalidDestIndex)
}
}
#[cfg(test)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum EdgeKind {
Outgoing,
Incoming,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FrozenGraph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
nodes: Nodes<N, EI, NM>,
edges: Edges<E, NI, EI, EM>,
}
impl<N, E, NI, EI, NM, EM> FrozenGraph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn node(&self, index: NI) -> Option<&Node<N, EI>> {
self.nodes.get(index)
}
pub fn node_mut(&mut self, index: NI) -> Option<&mut Node<N, EI>> {
self.nodes.get_mut(index)
}
pub fn nodes_count(&self) -> usize {
self.nodes.len()
}
pub fn node_weight(&self, index: NI) -> Option<&N> {
self.nodes.get(index).map(Node::weight)
}
pub fn node_weight_mut(&mut self, index: NI) -> Option<&mut N> {
self.nodes.get_mut(index).map(Node::weight_mut)
}
pub fn edge(&self, index: EI) -> Option<&Edge<E, NI, EI>> {
self.edges.get(index)
}
pub fn edge_mut(&mut self, index: EI) -> Option<&mut Edge<E, NI, EI>> {
self.edges.get_mut(index)
}
pub fn edges_count(&self) -> usize {
self.edges.len()
}
pub fn edge_weight(&self, index: EI) -> Option<&E> {
self.edge(index).map(Edge::weight)
}
pub fn edge_weight_mut(&mut self, index: EI) -> Option<&mut E> {
self.edge_mut(index).map(Edge::weight_mut)
}
#[allow(clippy::type_complexity)]
pub fn as_nodes_mut_and_edges(&mut self) -> (&mut Nodes<N, EI, NM>, &Edges<E, NI, EI, EM>) {
(&mut self.nodes, &self.edges)
}
#[allow(clippy::type_complexity)]
pub fn as_nodes_and_edges_mut(&mut self) -> (&Nodes<N, EI, NM>, &mut Edges<E, NI, EI, EM>) {
(&self.nodes, &mut self.edges)
}
#[allow(clippy::type_complexity)]
pub fn as_nodes_mut_and_edges_mut(
&mut self,
) -> (&mut Nodes<N, EI, NM>, &mut Edges<E, NI, EI, EM>) {
(&mut self.nodes, &mut self.edges)
}
pub fn find_edge(&self, from: NI, to: NI) -> Result<Option<EI>, InvalidEdgeError> {
let from_node = self
.node(from)
.ok_or(InvalidEdgeError::InvalidSourceIndex)?;
if !self.nodes.contains_key(to) {
return Err(InvalidEdgeError::InvalidDestIndex);
}
Ok(find_edge_impl(
&self.edges,
from_node.next_outgoing_edge,
to,
))
}
pub fn find_node<F: FnMut(&N) -> bool>(&self, mut f: F) -> Option<NI> {
for (i, node) in &self.nodes {
if f(&node.weight) {
return Some(i);
}
}
None
}
pub fn node_weights(&self) -> iter::NodeWeights<'_, N, NI, EI, NM> {
iter::NodeWeights {
inner: self.nodes.iter(),
}
}
pub fn node_weights_mut(&mut self) -> iter::NodeWeightsMut<'_, N, NI, EI, NM> {
iter::NodeWeightsMut {
inner: self.nodes.iter_mut(),
}
}
pub fn edge_weights(&self) -> iter::EdgeWeights<'_, E, NI, EI, EM> {
iter::EdgeWeights {
inner: self.edges.iter(),
}
}
pub fn edge_weights_mut(&mut self) -> iter::EdgeWeightsMut<'_, E, NI, EI, EM> {
iter::EdgeWeightsMut {
inner: self.edges.iter_mut(),
}
}
pub fn outputs(&self, node_index: NI) -> iter::Outputs<'_, E, NI, EI, EM> {
let next = self.nodes[node_index].next_outgoing_edge;
iter::Outputs::new(&self.edges.map, next)
}
pub fn inputs(&self, node_index: NI) -> iter::Inputs<'_, E, NI, EI, EM> {
let next = self.nodes[node_index].next_incoming_edge;
iter::Inputs::new(&self.edges.map, next)
}
pub fn successors(&self, node_index: NI) -> iter::Successors<'_, N, E, NI, EI, NM, EM> {
let next = self.nodes[node_index].next_outgoing_edge;
iter::Successors { graph: self, next }
}
pub fn predecessors(&self, node_index: NI) -> iter::Predecessors<'_, N, E, NI, EI, NM, EM> {
let next = self.nodes[node_index].next_incoming_edge;
iter::Predecessors { graph: self, next }
}
pub fn walk_successors(&self, node_index: NI) -> iter::WalkSuccessors<EI> {
let next = self.nodes[node_index].next_outgoing_edge;
iter::WalkSuccessors { next }
}
pub fn walk_predecessors(&self, node_index: NI) -> iter::WalkPredecessors<EI> {
let next = self.nodes[node_index].next_incoming_edge;
iter::WalkPredecessors { next }
}
pub fn walk_inputs(&self, node_index: NI) -> iter::WalkInputs<EI> {
let next = self.nodes[node_index].next_incoming_edge;
iter::WalkInputs { next }
}
pub fn walk_outputs(&self, node_index: NI) -> iter::WalkOutputs<EI> {
let next = self.nodes[node_index].next_outgoing_edge;
iter::WalkOutputs { next }
}
pub fn unfreeze(self) -> Graph<N, E, NI, EI, NM, EM> {
self.into()
}
#[cfg(test)]
fn is_valid_node_index(&self, index: NI) -> bool {
self.nodes.contains_key(index)
}
#[cfg(test)]
fn is_valid_edge_index(&self, index: EI) -> bool {
self.edges.contains_key(index)
}
#[cfg(test)]
fn is_valid_edge_index_or_none(&self, index: Option<EI>) -> bool {
if let Some(index) = index {
self.is_valid_edge_index(index)
} else {
true
}
}
#[cfg(test)]
fn validate_edges_list(&self, first_edge_index: Option<EI>, node_index: NI, kind: EdgeKind) {
assert!(self.is_valid_edge_index_or_none(first_edge_index));
let mut next_edge_index = first_edge_index;
while let Some(index) = next_edge_index {
let edge = self.edges.get(index).unwrap();
match kind {
EdgeKind::Outgoing => {
next_edge_index = edge.next_outgoing_edge;
assert_eq!(edge.from, node_index);
}
EdgeKind::Incoming => {
next_edge_index = edge.next_incoming_edge;
assert_eq!(edge.to, node_index);
}
};
}
}
#[cfg(test)]
#[allow(unused)]
fn validate(&self) {
for (_, edge) in self.edges.iter() {
assert!(self.is_valid_edge_index_or_none(edge.next_outgoing_edge));
assert!(self.is_valid_edge_index_or_none(edge.next_incoming_edge));
assert!(self.is_valid_node_index(edge.from));
assert!(self.is_valid_node_index(edge.to));
}
for (node_index, node) in self.nodes.iter() {
self.validate_edges_list(node.next_outgoing_edge, node_index, EdgeKind::Outgoing);
self.validate_edges_list(node.next_incoming_edge, node_index, EdgeKind::Incoming);
}
}
}
impl<N, E, NI, EI, NM, EM> FrozenGraph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Ord + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: OrderedKeyMap<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn nodes_range<R: RangeBounds<NI>>(
&self,
range: R,
) -> impl DoubleEndedIterator<Item = (NI, &N)> {
self.nodes.range(range).map(|(k, n)| (k, &n.weight))
}
pub fn nodes_range_mut<R: RangeBounds<NI>>(
&mut self,
range: R,
) -> impl DoubleEndedIterator<Item = (NI, &mut N)> {
self.nodes.range_mut(range).map(|(k, n)| (k, &mut n.weight))
}
pub fn first_node(&self) -> Option<(NI, &N)> {
self.nodes.first().map(|(k, v)| (k, &v.weight))
}
pub fn first_node_mut(&mut self) -> Option<(NI, &mut N)> {
self.nodes.first_mut().map(|(k, v)| (k, &mut v.weight))
}
pub fn last_node(&self) -> Option<(NI, &N)> {
self.nodes.last().map(|(k, v)| (k, &v.weight))
}
pub fn last_node_mut(&mut self) -> Option<(NI, &mut N)> {
self.nodes.last_mut().map(|(k, v)| (k, &mut v.weight))
}
}
#[cfg(feature = "rayon")]
impl<N, E, NI, EI, NM, EM> FrozenGraph<N, E, NI, EI, NM, EM>
where
N: Send + Sync,
NI: Copy + Eq + Ord + Send + Sync + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: ParIterMap<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn par_iter_nodes(&self) -> NM::ParIter<'_> {
self.nodes.par_iter()
}
pub fn par_iter_nodes_mut(&mut self) -> NM::ParIterMut<'_> {
self.nodes.par_iter_mut()
}
pub fn par_iter_node_weights(&self) -> ParNodeWeightIter<NM::ParIter<'_>, NI, EI, N> {
self.nodes.par_iter_weights()
}
pub fn par_iter_node_weights_mut(
&mut self,
) -> ParNodeWeightIterMut<NM::ParIterMut<'_>, NI, EI, N> {
self.nodes.par_iter_weights_mut()
}
}
#[cfg(feature = "rayon")]
impl<N, E, NI, EI, NM, EM> FrozenGraph<N, E, NI, EI, NM, EM>
where
E: Send + Sync,
NI: Copy + Eq + Ord + Send + Sync + Debug + 'static,
EI: Copy + Eq + Send + Sync + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI> + ParIterMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn par_iter_edges(&self) -> EM::ParIter<'_> {
self.edges.par_iter()
}
pub fn par_iter_edges_mut(&mut self) -> EM::ParIterMut<'_> {
self.edges.par_iter_mut()
}
pub fn par_iter_edge_weights(&self) -> ParMap<EM::ParIter<'_>, EdgeMapFn<NI, EI, E>> {
self.edges.par_iter_weights()
}
pub fn par_iter_edge_weights_mut(
&mut self,
) -> ParMap<EM::ParIterMut<'_>, EdgeMapMutFn<NI, EI, E>> {
self.edges.par_iter_weights_mut()
}
}
impl<N, E, NI, EI, NM, EM> Default for FrozenGraph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn default() -> Self {
FrozenGraph {
nodes: Nodes::default(),
edges: Edges::default(),
}
}
}
impl<N, E, NI, EI, NM, EM> From<Graph<N, E, NI, EI, NM, EM>> for FrozenGraph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn from(value: Graph<N, E, NI, EI, NM, EM>) -> Self {
value.inner
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
inner: FrozenGraph<N, E, NI, EI, NM, EM>,
}
impl<N, E, NI, EI, NM, EM> Default for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn default() -> Self {
Self {
inner: FrozenGraph::default(),
}
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: MapWithCapacity<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI> + MapWithCapacity<Edge<E, NI, EI>, Key = EI>,
{
#[must_use]
pub fn with_capacities(nodes_capacity: usize, edges_capacity: usize) -> Self {
Graph {
inner: FrozenGraph {
nodes: Nodes::with_capacity(nodes_capacity),
edges: Edges::with_capacity(edges_capacity),
},
}
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn clear(&mut self) {
self.nodes.map.clear();
self.edges.map.clear();
}
pub fn add_edge(&mut self, weight: E, from: NI, to: NI) -> Result<EI, AddEdgeError> {
insert_edge_impl(&mut self.inner, from, to, weight, |_, _, _| {
Err(AddEdgeError::EdgeExists)
})
.map(|(index, _)| index)
}
pub fn add_edge_with_index<F: FnOnce(EI) -> E>(
&mut self,
from: NI,
to: NI,
f: F,
) -> Result<EI, AddEdgeError> {
let (nodes, edges) = self.as_nodes_mut_and_edges_mut();
if !nodes.contains_key(to) {
return Err(InvalidEdgeError::InvalidDestIndex.into());
}
let from_node = nodes
.get_mut(from)
.ok_or(InvalidEdgeError::InvalidSourceIndex)?;
if find_edge_impl(edges, from_node.next_outgoing_edge, to).is_some() {
Err(AddEdgeError::EdgeExists)
} else {
let index = edges.map.insert_with_key(|index| {
let next_outgoing_edge = from_node.next_outgoing_edge.replace(index);
Edge {
weight: f(index),
from,
to,
next_incoming_edge: None,
next_outgoing_edge,
}
});
let to_node = nodes.get_mut(to).expect("invalid node map state");
let next_incoming_edge = to_node.next_incoming_edge.replace(index);
let edge = &mut self.edges[index];
edge.next_incoming_edge = next_incoming_edge;
Ok(index)
}
}
pub fn replace_edge(
&mut self,
weight: E,
from: NI,
to: NI,
) -> Result<(EI, Option<E>), InvalidEdgeError> {
insert_edge_impl(
&mut self.inner,
from,
to,
weight,
|weight, edge_index, edges| Ok(mem::replace(&mut edges[edge_index].weight, weight)),
)
}
#[allow(clippy::missing_panics_doc)]
pub fn remove_node(&mut self, index: NI) -> Result<Option<N>, RemoveNodeError> {
let Some(node) = self.nodes.get(index) else {
return Ok(None);
};
if node.next_outgoing_edge.is_none() && node.next_incoming_edge.is_none() {
Ok(Some(
self.nodes
.map
.remove(index)
.expect("node should exist")
.weight,
))
} else {
Err(RemoveNodeError)
}
}
#[allow(clippy::missing_panics_doc)]
pub fn unlink_and_remove_node(&mut self, index: NI) -> Option<N> {
let removed_node = self.nodes.get(index)?;
let next_outgoing_edge = removed_node.next_outgoing_edge;
let next_incoming_edge = removed_node.next_incoming_edge;
let outgoing_edges = iter::DrainOutgoingEdges {
graph: self,
next_edge_index: next_outgoing_edge,
};
for _ in outgoing_edges {}
let incoming_edges = iter::DrainIncomingEdges {
graph: self,
next_edge_index: next_incoming_edge,
};
for _ in incoming_edges {}
Some(
self.nodes
.map
.remove(index)
.expect("node should exist")
.weight,
)
}
fn unlink_edge_from_outgoing_list(&mut self, index: EI, edge: &Edge<E, NI, EI>) {
let node = self
.nodes
.get_mut(edge.from)
.expect("invalid source node index");
if node.next_outgoing_edge == Some(index) {
node.next_outgoing_edge = edge.next_outgoing_edge;
} else {
let mut next = node.next_outgoing_edge;
while let Some(next_index) = next {
let next_edge = self
.edges
.get_mut(next_index)
.expect("invalid edge index in outgoing edges list");
next = next_edge.next_outgoing_edge;
if next == Some(index) {
next_edge.next_outgoing_edge = edge.next_outgoing_edge;
break;
}
}
if next != Some(index) {
unreachable!("an edge wasn't found in its outgoing edges list");
}
}
}
fn unlink_edge_from_incoming_list(&mut self, index: EI, edge: &Edge<E, NI, EI>) {
let node = self
.nodes
.get_mut(edge.to)
.expect("invalid destination node index");
if node.next_incoming_edge == Some(index) {
node.next_incoming_edge = edge.next_incoming_edge;
} else {
let mut next = node.next_incoming_edge;
while let Some(next_index) = next {
let next_edge = self
.edges
.get_mut(next_index)
.expect("invalid edge index in incoming edges list");
next = next_edge.next_incoming_edge;
if next == Some(index) {
next_edge.next_incoming_edge = edge.next_incoming_edge;
break;
}
}
if next != Some(index) {
unreachable!("an edge wasn't found in its incoming edges list");
}
}
}
pub fn remove_edge(&mut self, index: EI) -> Option<E> {
let removed_edge = self.edges.map.remove(index)?;
self.unlink_edge_from_outgoing_list(index, &removed_edge);
self.unlink_edge_from_incoming_list(index, &removed_edge);
Some(removed_edge.weight)
}
pub fn drain_outgoing_edges(
&mut self,
node_index: NI,
) -> iter::DrainOutgoingEdges<'_, N, E, NI, EI, NM, EM> {
let (nodes, edges) = self.as_nodes_mut_and_edges();
let node = &mut nodes[node_index];
let next_edge_index = node.next_outgoing_edge.take();
if let Some(ei) = next_edge_index {
node.next_outgoing_edge = edges[ei].next_outgoing_edge;
}
iter::DrainOutgoingEdges {
graph: self,
next_edge_index,
}
}
pub fn drain_incoming_edges(
&mut self,
node_index: NI,
) -> iter::DrainIncomingEdges<'_, N, E, NI, EI, NM, EM> {
let (nodes, edges) = self.as_nodes_mut_and_edges();
let node = &mut nodes[node_index];
let next_edge_index = node.next_incoming_edge.take();
if let Some(ei) = next_edge_index {
node.next_incoming_edge = edges[ei].next_incoming_edge;
}
iter::DrainIncomingEdges {
graph: self,
next_edge_index,
}
}
pub fn freeze(self) -> FrozenGraph<N, E, NI, EI, NM, EM> {
self.into()
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: MapWithCapacity<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn reserve_nodes(&mut self, additional: usize) {
self.inner.nodes.map.reserve(additional)
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI> + MapWithCapacity<Edge<E, NI, EI>, Key = EI>,
{
pub fn reserve_edges(&mut self, additional: usize) {
self.inner.edges.map.reserve(additional)
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: IntKeyMap<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn add_node(&mut self, weight: N) -> NI {
self.nodes.map.insert(Node {
weight,
next_incoming_edge: None,
next_outgoing_edge: None,
})
}
#[allow(clippy::missing_panics_doc)]
pub fn add_connected_node(
&mut self,
node_weight: N,
from: NI,
edge_weight: E,
) -> Result<(NI, EI), InvalidEdgeError> {
if !self.nodes.contains_key(from) {
return Err(InvalidEdgeError::InvalidSourceIndex);
}
let to = self.nodes.map.insert(Node {
weight: node_weight,
next_incoming_edge: None,
next_outgoing_edge: None,
});
let edge_index = insert_edge(
&mut self.inner.nodes.map,
&mut self.inner.edges.map,
from,
to,
edge_weight,
)
.expect("all error conditions should have been prevented");
Ok((to, edge_index))
}
pub fn add_node_with_key<F: FnOnce(NM::Key) -> N>(&mut self, f: F) -> NI {
self.nodes.map.insert_with_key(|key| Node {
weight: f(key),
next_incoming_edge: None,
next_outgoing_edge: None,
})
}
pub fn split_node<F: FnOnce(&mut N) -> N>(&mut self, index: NI, splitter: F) -> NI {
let node = &mut self.nodes[index];
let mut next_outgoing_edge = node.next_outgoing_edge.take();
let new_weight = splitter(&mut node.weight);
let new_node_index = self.nodes.map.insert(Node {
weight: new_weight,
next_incoming_edge: None,
next_outgoing_edge,
});
while let Some(edge_index) = next_outgoing_edge {
let edge = self.edge_mut(edge_index).expect("corrupt edge list");
edge.from = new_node_index;
next_outgoing_edge = edge.next_outgoing_edge;
}
new_node_index
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
N: Default,
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: IntKeyMap<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn add_default_node(&mut self) -> NI {
self.nodes.map.insert(Node {
weight: Default::default(),
next_incoming_edge: None,
next_outgoing_edge: None,
})
}
}
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: ExtKeyMap<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn try_add_node_at_index(
&mut self,
index: NM::Key,
weight: N,
) -> Result<(), NodeExistsError> {
self.nodes
.map
.try_insert(
index,
Node {
weight,
next_incoming_edge: None,
next_outgoing_edge: None,
},
)
.map_err(|_| NodeExistsError(()))
}
pub fn try_split_node_at_index<F>(
&mut self,
index: NI,
new_index: NI,
splitter: F,
) -> Result<(), NodeExistsError>
where
F: FnOnce(&mut N) -> N,
{
let node = &mut self.nodes[index];
let mut next_outgoing_edge = node.next_outgoing_edge.take();
let new_weight = splitter(&mut node.weight);
let result = self.nodes.map.try_insert(
new_index,
Node {
weight: new_weight,
next_incoming_edge: None,
next_outgoing_edge,
},
);
if result.is_err() {
self.nodes[index].next_outgoing_edge = next_outgoing_edge;
return Err(NodeExistsError(()));
}
while let Some(edge_index) = next_outgoing_edge {
let edge = self.edge_mut(edge_index).expect("corrupt edge list");
debug_assert_eq!(edge.from, index);
edge.from = new_index;
next_outgoing_edge = edge.next_outgoing_edge;
}
Ok(())
}
}
impl<N, E, NI, EI, NM, EM> Deref for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
type Target = FrozenGraph<N, E, NI, EI, NM, EM>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<N, E, NI, EI, NM, EM> DerefMut for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<N, E, NI, EI, NM, EM> From<FrozenGraph<N, E, NI, EI, NM, EM>> for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn from(value: FrozenGraph<N, E, NI, EI, NM, EM>) -> Self {
Graph { inner: value }
}
}
impl<N, E, NI, EI, NM, EM> AsRef<FrozenGraph<N, E, NI, EI, NM, EM>> for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn as_ref(&self) -> &FrozenGraph<N, E, NI, EI, NM, EM> {
self
}
}
impl<N, E, NI, EI, NM, EM> AsMut<FrozenGraph<N, E, NI, EI, NM, EM>> for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn as_mut(&mut self) -> &mut FrozenGraph<N, E, NI, EI, NM, EM> {
self
}
}
impl<N, E, NI, EI, NM, EM> Borrow<FrozenGraph<N, E, NI, EI, NM, EM>> for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn borrow(&self) -> &FrozenGraph<N, E, NI, EI, NM, EM> {
self
}
}
impl<N, E, NI, EI, NM, EM> BorrowMut<FrozenGraph<N, E, NI, EI, NM, EM>>
for Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: Map<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
fn borrow_mut(&mut self) -> &mut FrozenGraph<N, E, NI, EI, NM, EM> {
self
}
}
mod edges;
pub mod entry;
pub mod iter;
mod nodes;
pub use edges::Edges;
pub use nodes::Nodes;
impl<N, E, NI, EI, NM, EM> Graph<N, E, NI, EI, NM, EM>
where
NI: Copy + Eq + Debug + 'static,
EI: Copy + Eq + Debug + 'static,
NM: MapWithEntry<Node<N, EI>, Key = NI>,
EM: IntKeyMap<Edge<E, NI, EI>, Key = EI>,
{
pub fn node_entry(&mut self, node_index: NI) -> Entry<'_, N, NI, EI, NM> {
match self.inner.nodes.map.entry(node_index) {
MapEntry::Vacant(entry) => Entry::Vacant(VacantEntry { entry }),
MapEntry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry }),
}
}
}
#[cfg(all(test, feature = "alloc", feature = "slotmap"))]
mod tests;