use std::collections::HashSet;
use std::marker::PhantomData;
use crate::graph::{DefaultEdge, DirectedEdge, Edge, EdgeDir, FlowEdge, UndirectedEdge};
use crate::storage::GraphStorage;
pub type List<W, Dir = UndirectedEdge> = AdjList<W, DefaultEdge<W>, Dir>;
pub type DiList<W> = AdjList<W, DefaultEdge<W>, DirectedEdge>;
pub type FlowList<W, Dir = UndirectedEdge> = AdjList<W, FlowEdge<W>, Dir>;
pub type DiFlowList<W> = AdjList<W, FlowEdge<W>, DirectedEdge>;
pub struct AdjList<W, E: Edge<W>, Dir: EdgeDir = UndirectedEdge> {
edges_of: Vec<Vec<(usize, E)>>,
reusable_vertex_ids: HashSet<usize>,
max_edge_id: usize,
reusable_edge_ids: HashSet<usize>,
vertex_count: usize,
phantom_w: PhantomData<W>,
phantom_dir: PhantomData<Dir>,
}
impl<W, E: Edge<W>, Dir: EdgeDir> AdjList<W, E, Dir> {
pub fn init() -> Self {
AdjList {
edges_of: vec![],
reusable_vertex_ids: HashSet::new(),
max_edge_id: 0,
reusable_edge_ids: HashSet::new(),
vertex_count: 0,
phantom_w: PhantomData,
phantom_dir: PhantomData,
}
}
fn next_reusable_vertex_id(&mut self) -> Option<usize> {
if let Some(id) = self.reusable_vertex_ids.iter().take(1).next().copied() {
self.reusable_vertex_ids.remove(&id);
Some(id)
} else {
None
}
}
fn next_reusable_edge_id(&mut self) -> Option<usize> {
if let Some(id) = self.reusable_edge_ids.iter().take(1).next().copied() {
self.reusable_edge_ids.remove(&id);
Some(id)
} else {
None
}
}
pub fn total_vertex_count(&self) -> usize {
self.edges_of.len()
}
}
impl<W: Copy, E: Edge<W> + Copy, Dir: EdgeDir> GraphStorage<W, E, Dir> for AdjList<W, E, Dir> {
fn add_vertex(&mut self) -> usize {
self.vertex_count += 1;
if let Some(reusable_id) = self.next_reusable_vertex_id() {
reusable_id
} else {
self.edges_of.push(vec![]);
self.edges_of.len() - 1
}
}
fn remove_vertex_unchecked(&mut self, vertex_id: usize) {
self.edges_of[vertex_id].clear();
for src_id in self.vertices() {
self.edges_of[src_id].retain(|(dst_id, _)| *dst_id != vertex_id)
}
self.vertex_count -= 1;
self.reusable_vertex_ids.insert(vertex_id);
}
fn add_edge_unchecked(&mut self, src_id: usize, dst_id: usize, mut edge: E) -> usize {
let edge_id = if let Some(id) = self.next_reusable_edge_id() {
id
} else {
self.max_edge_id += 1;
self.max_edge_id - 1
};
edge.set_id(edge_id);
self.edges_of[src_id].push((dst_id, edge));
if self.is_undirected() {
self.edges_of[dst_id].push((src_id, edge));
}
edge_id
}
fn update_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize, mut edge: E) {
let removed_edge = self.remove_edge_unchecked(src_id, dst_id, edge_id);
edge.set_id(removed_edge.get_id());
self.add_edge_unchecked(src_id, dst_id, edge);
}
fn remove_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> E {
let index = self.edges_of[src_id]
.iter()
.position(|(_, edge)| edge.get_id() == edge_id)
.unwrap();
self.reusable_edge_ids.insert(edge_id);
if self.is_undirected() {
self.edges_of[dst_id].retain(|(_, edge)| edge.get_id() != edge_id);
}
self.edges_of[src_id].remove(index).1
}
fn vertex_count(&self) -> usize {
self.vertex_count
}
fn edge_count(&self) -> usize {
self.max_edge_id - self.reusable_edge_ids.len()
}
fn vertices(&self) -> Vec<usize> {
(0..self.edges_of.len())
.filter(|vertex_id| !self.reusable_vertex_ids.contains(vertex_id))
.collect()
}
fn edges_from_unchecked(&self, src_id: usize) -> Vec<(usize, &E)> {
self.edges_of[src_id]
.iter()
.map(|(dst_id, edge)| (*dst_id, edge))
.collect()
}
fn contains_vertex(&self, vertex_id: usize) -> bool {
vertex_id < self.total_vertex_count() && !self.reusable_vertex_ids.contains(&vertex_id)
}
fn contains_edge(&self, edge_id: usize) -> bool {
edge_id < self.max_edge_id && !self.reusable_edge_ids.contains(&edge_id)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn directed_empty_list() {
let list = DiList::<usize>::init();
assert_eq!(list.edge_count(), 0);
assert_eq!(list.vertex_count(), 0);
assert_eq!(list.edges_of.len(), 0);
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.is_directed(), true);
}
#[test]
fn undirected_empty_list() {
let list = List::<usize>::init();
assert_eq!(list.edge_count(), 0);
assert_eq!(list.vertex_count(), 0);
assert_eq!(list.edges_of.len(), 0);
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.is_directed(), false);
}
#[test]
fn directed_add_vertex() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.is_empty()));
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| list.vertices().contains(vertex_id)));
assert!(vec![a, b, c]
.into_iter()
.flat_map(|vertex_id| vec![(vertex_id, a), (vertex_id, b), (vertex_id, c)])
.all(|(src_id, dst_id)| !list.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn undirected_add_vertex() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| list.vertices().contains(vertex_id)));
assert!(vec![a, b, c]
.into_iter()
.flat_map(|vertex_id| vec![(vertex_id, a), (vertex_id, b), (vertex_id, c)])
.all(|(src_id, dst_id)| !list.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn directed_delete_vertex() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.remove_vertex_unchecked(a);
list.remove_vertex_unchecked(b);
assert_eq!(list.vertex_count(), 1);
assert_eq!(list.edges_of.len(), 3);
assert_eq!(list.reusable_vertex_ids.len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| list.reusable_vertex_ids.contains(vertex_id)));
assert_eq!(list.vertices().len(), 1);
assert!(list.vertices().contains(&c));
assert!(!list.has_any_edge_unchecked(c, c));
}
#[test]
fn undirected_delete_vertex() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.remove_vertex_unchecked(a);
list.remove_vertex_unchecked(b);
assert_eq!(list.vertex_count(), 1);
assert_eq!(list.edges_of.len(), 3);
assert_eq!(list.reusable_vertex_ids.len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| list.reusable_vertex_ids.contains(vertex_id)));
assert_eq!(list.vertices().len(), 1);
assert!(list.vertices().contains(&c));
assert!(!list.has_any_edge_unchecked(c, c));
}
#[test]
fn directed_add_vertex_after_vertex_deletion() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.remove_vertex_unchecked(a);
list.remove_vertex_unchecked(b);
let _ = list.add_vertex();
let _ = list.add_vertex();
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| list.vertices().contains(vertex_id)));
assert!(vec![a, b, c]
.into_iter()
.flat_map(|vertex_id| vec![(vertex_id, a), (vertex_id, b), (vertex_id, c)])
.all(|(src_id, dst_id)| !list.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn undirected_add_vertex_after_vertex_deletion() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.remove_vertex_unchecked(a);
list.remove_vertex_unchecked(b);
let _ = list.add_vertex();
let _ = list.add_vertex();
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert_eq!(list.reusable_vertex_ids.len(), 0);
assert_eq!(list.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| list.vertices().contains(vertex_id)));
assert!(vec![a, b, c]
.into_iter()
.flat_map(|vertex_id| vec![(vertex_id, a), (vertex_id, b), (vertex_id, c)])
.all(|(src_id, dst_id)| !list.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn directed_add_edge() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 1));
assert_eq!(list.edges().len(), 3);
for (src_id, dst_id, edge) in list.edges() {
match (src_id, dst_id) {
(0, 1) => assert_eq!(edge.get_weight().unwrap(), 1),
(1, 2) => assert_eq!(edge.get_weight().unwrap(), 2),
(2, 0) => assert_eq!(edge.get_weight().unwrap(), 3),
_ => panic!("Unknown vertex id"),
}
}
}
#[test]
fn undirected_add_edge() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 2));
assert_eq!(list.edges().len(), 3);
for (src_id, dst_id, edge) in list.edges() {
match (src_id, dst_id) {
(0, 1) | (1, 0) => assert_eq!(edge.get_weight().unwrap(), 1),
(1, 2) | (2, 1) => assert_eq!(edge.get_weight().unwrap(), 2),
(2, 0) | (0, 2) => assert_eq!(edge.get_weight().unwrap(), 3),
_ => panic!("Unknown vertex id"),
}
}
}
#[test]
fn directed_has_edge() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert!(list.has_any_edge_unchecked(a, b));
assert!(list.has_any_edge_unchecked(b, c));
assert!(list.has_any_edge_unchecked(c, a));
}
#[test]
fn undirected_has_edge() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert!(list.has_any_edge_unchecked(a, b));
assert!(list.has_any_edge_unchecked(b, a));
assert!(list.has_any_edge_unchecked(b, c));
assert!(list.has_any_edge_unchecked(c, b));
assert!(list.has_any_edge_unchecked(c, a));
assert!(list.has_any_edge_unchecked(a, c));
}
#[test]
fn directed_update_edge() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
let ab = list.add_edge_unchecked(a, b, 1.into());
let bc = list.add_edge_unchecked(b, c, 2.into());
let ca = list.add_edge_unchecked(c, a, 3.into());
list.update_edge_unchecked(a, b, ab, 2.into());
list.update_edge_unchecked(b, c, bc, 3.into());
list.update_edge_unchecked(c, a, ca, 4.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 1));
assert_eq!(list.edges().len(), 3);
for (src_id, dst_id, edge) in list.edges() {
match (src_id, dst_id) {
(0, 1) => assert_eq!(edge.get_weight().unwrap(), 2),
(1, 2) => assert_eq!(edge.get_weight().unwrap(), 3),
(2, 0) => assert_eq!(edge.get_weight().unwrap(), 4),
_ => panic!("Unknown vertex id"),
}
}
}
#[test]
fn undirected_update_edge() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
let ab = list.add_edge_unchecked(a, b, 1.into());
let bc = list.add_edge_unchecked(b, c, 2.into());
let ca = list.add_edge_unchecked(c, a, 3.into());
list.update_edge_unchecked(a, b, ab, 2.into());
list.update_edge_unchecked(b, c, bc, 3.into());
list.update_edge_unchecked(c, a, ca, 4.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 2));
assert_eq!(list.edges().len(), 3);
for (src_id, dst_id, edge) in list.edges() {
match (src_id, dst_id) {
(0, 1) | (1, 0) => assert_eq!(edge.get_weight().unwrap(), 2),
(1, 2) | (2, 1) => assert_eq!(edge.get_weight().unwrap(), 3),
(2, 0) | (0, 2) => assert_eq!(edge.get_weight().unwrap(), 4),
_ => panic!("Unknown vertex id"),
}
}
}
#[test]
fn directed_remove_edge() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
let ab = list.add_edge_unchecked(a, b, 1.into());
let bc = list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
list.remove_edge_unchecked(a, b, ab);
list.remove_edge_unchecked(b, c, bc);
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of[a].is_empty());
assert!(list.edges_of[b].is_empty());
assert_eq!(list.edges_of[c].len(), 1);
assert_eq!(list.edges().len(), 1);
assert_eq!(
list.edges_between_unchecked(c, a)[0].get_weight().unwrap(),
3
);
}
#[test]
fn undirected_remove_edge() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
let ab = list.add_edge_unchecked(a, b, 1.into());
let bc = list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
list.remove_edge_unchecked(a, b, ab);
list.remove_edge_unchecked(b, c, bc);
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of[a].len(), 1);
assert!(list.edges_of[b].is_empty());
assert_eq!(list.edges_of[c].len(), 1);
assert_eq!(list.edges().len(), 1);
assert_eq!(
list.edges_between_unchecked(a, c)[0].get_weight().unwrap(),
3
);
}
#[test]
fn directed_neighbors() {
let mut list = DiList::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 1));
assert_eq!(list.neighbors_unchecked(a).len(), 1);
assert_eq!(*list.neighbors_unchecked(a).get(0).unwrap(), b);
assert_eq!(list.neighbors_unchecked(b).len(), 1);
assert_eq!(*list.neighbors_unchecked(b).get(0).unwrap(), c);
assert_eq!(list.neighbors_unchecked(c).len(), 1);
assert_eq!(*list.neighbors_unchecked(c).get(0).unwrap(), a);
}
#[test]
fn undirected_neighbors() {
let mut list = List::<usize>::init();
let a = list.add_vertex();
let b = list.add_vertex();
let c = list.add_vertex();
list.add_edge_unchecked(a, b, 1.into());
list.add_edge_unchecked(b, c, 2.into());
list.add_edge_unchecked(c, a, 3.into());
assert_eq!(list.vertex_count(), 3);
assert_eq!(list.edges_of.len(), 3);
assert!(list.edges_of.iter().all(|edges| edges.len() == 2));
assert_eq!(list.neighbors_unchecked(a).len(), 2);
assert!(vec![b, c]
.iter()
.all(|vertex_id| list.neighbors_unchecked(a).contains(vertex_id)));
assert_eq!(list.neighbors_unchecked(b).len(), 2);
assert!(vec![a, c]
.iter()
.all(|vertex_id| list.neighbors_unchecked(b).contains(vertex_id)));
assert_eq!(list.neighbors_unchecked(c).len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| list.neighbors_unchecked(c).contains(vertex_id)));
}
#[test]
fn edge_count() {
let mut mat = List::<usize>::init();
let a = mat.add_vertex();
let b = mat.add_vertex();
let c = mat.add_vertex();
let ab = mat.add_edge_unchecked(a, b, 1.into());
let bc = mat.add_edge_unchecked(b, c, 1.into());
let ca = mat.add_edge_unchecked(c, a, 1.into());
assert_eq!(mat.edge_count(), 3);
mat.remove_edge_unchecked(a, b, ab);
mat.remove_edge_unchecked(b, c, bc);
mat.remove_edge_unchecked(c, a, ca);
assert_eq!(mat.edge_count(), 0);
let mut di_mat = DiList::<usize>::init();
let a = di_mat.add_vertex();
let b = di_mat.add_vertex();
let c = di_mat.add_vertex();
let ab = di_mat.add_edge_unchecked(a, b, 1.into());
let bc = di_mat.add_edge_unchecked(b, c, 1.into());
let ca = di_mat.add_edge_unchecked(c, a, 1.into());
assert_eq!(di_mat.edge_count(), 3);
di_mat.remove_edge_unchecked(a, b, ab);
di_mat.remove_edge_unchecked(b, c, bc);
di_mat.remove_edge_unchecked(c, a, ca);
assert_eq!(di_mat.edge_count(), 0);
}
}