#![warn(missing_docs)]
use std::collections::BTreeSet;
use std::fmt::Debug;
use std::iter::FusedIterator;
use serde::{Deserialize, Serialize};
use slotmap::{Key, SecondaryMap, SlotMap};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(from = "EdgeList<V, E>", into = "EdgeList<V, E>")]
pub struct DiMulGraph<V, E>
where
V: Key,
E: Key,
{
edges: SlotMap<E, (V, V)>,
succs: SecondaryMap<V, Vec<E>>,
preds: SecondaryMap<V, Vec<E>>,
}
impl<V, E> Default for DiMulGraph<V, E>
where
V: Key,
E: Key,
{
fn default() -> Self {
let (edges, succs, preds) = Default::default();
Self {
edges,
succs,
preds,
}
}
}
impl<V, E> DiMulGraph<V, E>
where
V: Key,
E: Key,
{
pub fn new() -> Self {
Default::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
edges: SlotMap::with_capacity_and_key(capacity),
succs: SecondaryMap::with_capacity(capacity),
preds: SecondaryMap::with_capacity(capacity),
}
}
pub fn assert_valid(&self) {
for (edge_id, &(src, dst)) in self.edges.iter() {
assert!(self.succs[src].contains(&edge_id));
assert!(self.preds[dst].contains(&edge_id));
}
for succ_list in self.succs.values() {
let set: BTreeSet<&E> = succ_list.iter().collect();
assert_eq!(set.len(), succ_list.len());
}
for pred_list in self.succs.values() {
let set: BTreeSet<&E> = pred_list.iter().collect();
assert_eq!(set.len(), pred_list.len());
}
assert_eq!(
self.edges.len(),
self.succs.values().map(|vec| vec.len()).sum::<usize>(),
"succs broken (contains duplicate or removed edge?)"
);
assert_eq!(
self.edges.len(),
self.preds.values().map(|vec| vec.len()).sum::<usize>(),
"preds broken (contains duplicate or removed edge?)"
);
}
fn get_adj_edges(adj_list: &mut SecondaryMap<V, Vec<E>>, v: V) -> &mut Vec<E> {
if !adj_list.contains_key(v) {
adj_list.insert(v, Default::default());
}
&mut adj_list[v]
}
pub fn insert_edge(&mut self, src: V, dst: V) -> E {
let e = self.edges.insert((src, dst));
Self::get_adj_edges(&mut self.succs, src).push(e);
Self::get_adj_edges(&mut self.preds, dst).push(e);
e
}
pub fn insert_intermediate_vertex(&mut self, new_vertex: V, edge: E) -> Option<(E, E)> {
self.assert_valid();
let (src, dst) = self.edges.remove(edge)?;
let e0 = self.edges.insert((src, new_vertex));
let e1 = self.edges.insert((new_vertex, dst));
let succ_vec_idx = self.succs[src].iter().position(|&e| e == edge).unwrap();
let pred_vec_idx = self.preds[dst].iter().position(|&e| e == edge).unwrap();
assert_eq!(
edge,
std::mem::replace(&mut self.succs[src][succ_vec_idx], e0)
);
assert_eq!(
edge,
std::mem::replace(&mut self.preds[dst][pred_vec_idx], e1)
);
assert!(
self.preds.insert(new_vertex, vec![e0]).is_none(),
"Cannot insert intermediate vertex that already exists"
);
assert!(
self.succs.insert(new_vertex, vec![e1]).is_none(),
"Cannot insert intermediate vertex that already exists"
);
self.assert_valid();
Some((e0, e1))
}
pub fn remove_intermediate_vertex(&mut self, vertex: V) -> Option<(E, (E, E))> {
let preds = self.preds.remove(vertex)?;
let &[pred_edge] = &*preds else {
return None;
};
let succs = self.succs.remove(vertex).unwrap();
let &[succ_edge] = &*succs else {
return None;
};
let (src, _v) = self.edges.remove(pred_edge).unwrap();
let (_v, dst) = self.edges.remove(succ_edge).unwrap();
self.succs[src].retain(|&e| e != pred_edge);
self.preds[dst].retain(|&e| e != succ_edge);
let new_edge = self.insert_edge(src, dst);
Some((new_edge, (pred_edge, succ_edge)))
}
pub fn remove_edge(&mut self, e: E) -> Option<(V, V)> {
let (src, dst) = self.edges.remove(e)?;
self.succs[src].retain(|x| *x != e);
self.preds[dst].retain(|x| *x != e);
Some((src, dst))
}
pub fn remove_vertex(&mut self, v: V) {
assert!(self.preds[v].is_empty() && self.succs[v].is_empty());
self.preds.remove(v);
self.succs.remove(v);
}
pub fn edge(&self, e: E) -> Option<(V, V)> {
self.edges.get(e).copied()
}
pub fn edge_ids(&self) -> slotmap::basic::Keys<E, (V, V)> {
self.edges.keys()
}
pub fn edges(
&self,
) -> impl '_ + ExactSizeIterator<Item = (E, (V, V))> + FusedIterator + Clone + Debug {
self.edges.iter().map(|(e, &(src, dst))| (e, (src, dst)))
}
pub fn successor_edges(&self, v: V) -> std::iter::Copied<std::slice::Iter<'_, E>> {
self.succs
.get(v)
.map(|v| v.iter())
.unwrap_or_else(|| [].iter())
.copied()
}
pub fn predecessor_edges(&self, v: V) -> std::iter::Copied<std::slice::Iter<'_, E>> {
self.preds
.get(v)
.map(|v| v.iter())
.unwrap_or_else(|| [].iter())
.copied()
}
pub fn successor_vertices(
&self,
v: V,
) -> impl '_ + DoubleEndedIterator<Item = V> + ExactSizeIterator + FusedIterator + Clone + Debug
{
self.successor_edges(v).map(|edge_id| self.edges[edge_id].1)
}
pub fn predecessor_vertices(
&self,
v: V,
) -> impl '_ + DoubleEndedIterator<Item = V> + ExactSizeIterator + FusedIterator + Clone + Debug
{
self.predecessor_edges(v)
.map(|edge_id| self.edges[edge_id].0)
}
pub fn successors(
&self,
v: V,
) -> impl '_ + DoubleEndedIterator<Item = (E, V)> + ExactSizeIterator + FusedIterator + Clone + Debug
{
self.successor_edges(v)
.map(|edge_id| (edge_id, self.edges[edge_id].1))
}
pub fn predecessors(
&self,
v: V,
) -> impl '_ + DoubleEndedIterator<Item = (E, V)> + ExactSizeIterator + FusedIterator + Clone + Debug
{
self.predecessor_edges(v)
.map(|edge_id| (edge_id, self.edges[edge_id].0))
}
pub fn degree_out(&self, v: V) -> usize {
self.succs.get(v).map(Vec::len).unwrap_or_default()
}
pub fn degree_in(&self, v: V) -> usize {
self.preds.get(v).map(Vec::len).unwrap_or_default()
}
}
impl<V, E> From<DiMulGraph<V, E>> for EdgeList<V, E>
where
V: Key,
E: Key,
{
fn from(value: DiMulGraph<V, E>) -> Self {
value.edges
}
}
impl<V, E> From<EdgeList<V, E>> for DiMulGraph<V, E>
where
V: Key,
E: Key,
{
fn from(edges: EdgeList<V, E>) -> Self {
let mut out = Self {
edges,
..Default::default()
};
for (edge, &(src, dst)) in out.edges.iter() {
out.succs.entry(src).unwrap().or_default().push(edge);
out.preds.entry(dst).unwrap().or_default().push(edge);
}
out
}
}
#[expect(type_alias_bounds, reason = "code readability")]
pub type EdgeList<V, E>
where
V: Key,
E: Key,
= SlotMap<E, (V, V)>;