mod utils;
use std::any::Any;
use std::collections::HashSet;
use std::marker::PhantomData;
use crate::graph::{DefaultEdge, DirectedEdge, Edge, EdgeDir, FlowEdge, UndirectedEdge};
use crate::storage::GraphStorage;
pub type Mat<W, Dir = UndirectedEdge> = AdjMatrix<W, DefaultEdge<W>, Dir>;
pub type DiMat<W> = AdjMatrix<W, DefaultEdge<W>, DirectedEdge>;
pub type FlowMat<W, Dir = UndirectedEdge> = AdjMatrix<W, FlowEdge<W>, Dir>;
pub type DiFlowMat<W> = AdjMatrix<W, FlowEdge<W>, DirectedEdge>;
pub struct AdjMatrix<W, E: Edge<W>, Dir: EdgeDir = UndirectedEdge> {
vec: Vec<Vec<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> AdjMatrix<W, E, Dir> {
pub fn init() -> Self {
AdjMatrix {
vec: 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.vertex_count + self.reusable_vertex_ids.len()
}
}
impl<W: Any, E: Edge<W>, Dir: EdgeDir> GraphStorage<W, E, Dir> for AdjMatrix<W, E, Dir> {
fn add_vertex(&mut self) -> usize {
if let Some(reusable_id) = self.next_reusable_vertex_id() {
self.vertex_count += 1;
reusable_id
} else {
let new_size = if self.is_directed() {
self.vec.len() + 2 * self.total_vertex_count() + 1
} else {
self.vec.len() + self.total_vertex_count() + 1
};
self.vec.resize_with(new_size, || vec![]);
self.vertex_count += 1;
self.vertex_count - 1
}
}
fn remove_vertex_unchecked(&mut self, vertex_id: usize) {
for other_id in 0..self.total_vertex_count() {
self[(vertex_id, other_id)].clear();
self[(other_id, vertex_id)].clear();
}
self.reusable_vertex_ids.insert(vertex_id);
self.vertex_count -= 1;
}
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[(src_id, dst_id)].push(edge);
edge_id
}
fn update_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize, mut edge: E) {
if let Some(index) = self[(src_id, dst_id)]
.iter()
.position(|edge| edge.get_id() == edge_id)
{
edge.set_id(edge_id);
self[(src_id, dst_id)][index] = edge;
}
}
fn remove_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> E {
let index = self[(src_id, dst_id)]
.iter()
.position(|edge| edge.get_id() == edge_id)
.unwrap();
self.reusable_edge_ids.insert(edge_id);
self[(src_id, dst_id)].swap_remove(index)
}
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.total_vertex_count())
.into_iter()
.filter(|v_id| !self.reusable_vertex_ids.contains(v_id))
.collect()
}
fn edges_from_unchecked(&self, src_id: usize) -> Vec<(usize, &E)> {
(0..self.total_vertex_count())
.into_iter()
.flat_map(|dst_id| {
self.edges_between_unchecked(src_id, dst_id)
.into_iter()
.map(|edge| (dst_id, edge))
.collect::<Vec<(usize, &E)>>()
})
.collect()
}
fn neighbors_unchecked(&self, src_id: usize) -> Vec<usize> {
(0..self.total_vertex_count())
.into_iter()
.filter(|dst_id| !self[(src_id, *dst_id)].is_empty())
.collect()
}
fn edges_between_unchecked(&self, src_id: usize, dst_id: usize) -> Vec<&E> {
self[(src_id, dst_id)].iter().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)
}
}
use std::ops::{Index, IndexMut};
impl<W: Any, E: Edge<W>, Dir: EdgeDir> Index<(usize, usize)> for AdjMatrix<W, E, Dir> {
type Output = Vec<E>;
fn index(&self, (src_id, dst_id): (usize, usize)) -> &Self::Output {
let index = utils::from_ij(src_id, dst_id, self.is_directed());
&self.vec[index]
}
}
impl<W: Any, E: Edge<W>, Dir: EdgeDir> IndexMut<(usize, usize)> for AdjMatrix<W, E, Dir> {
fn index_mut(&mut self, (src_id, dst_id): (usize, usize)) -> &mut Self::Output {
let index = utils::from_ij(src_id, dst_id, self.is_directed());
&mut self.vec[index]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn directed_empty_matrix() {
let matrix = DiMat::<usize>::init();
assert_eq!(matrix.edge_count(), 0);
assert_eq!(matrix.vertex_count(), 0);
assert_eq!(matrix.total_vertex_count(), 0);
assert_eq!(matrix.vec.len(), 0);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.is_directed(), true);
}
#[test]
fn undirected_empty_matrix() {
let matrix = Mat::<usize>::init();
assert_eq!(matrix.edge_count(), 0);
assert_eq!(matrix.vertex_count(), 0);
assert_eq!(matrix.total_vertex_count(), 0);
assert_eq!(matrix.vec.len(), 0);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.is_directed(), false);
}
#[test]
fn directed_add_vertex() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| matrix.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)| !matrix.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn undirected_add_vertex() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| matrix.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)| !matrix.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn directed_delete_vertex() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.remove_vertex_unchecked(a);
matrix.remove_vertex_unchecked(b);
assert_eq!(matrix.edges().len(), 0);
assert_eq!(matrix.vertex_count(), 1);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.reusable_vertex_ids.len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| matrix.reusable_vertex_ids.contains(vertex_id)));
assert_eq!(matrix.vertices().len(), 1);
assert!(matrix.vertices().contains(&c));
assert!(!matrix.has_any_edge_unchecked(c, c));
}
#[test]
fn undirected_delete_vertex() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.remove_vertex_unchecked(a);
matrix.remove_vertex_unchecked(b);
assert_eq!(matrix.vertex_count(), 1);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.reusable_vertex_ids.len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| matrix.reusable_vertex_ids.contains(vertex_id)));
assert_eq!(matrix.vertices().len(), 1);
assert!(matrix.vertices().contains(&c));
assert!(!matrix.has_any_edge_unchecked(c, c));
}
#[test]
fn directed_add_vertex_after_vertex_deletion() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.remove_vertex_unchecked(a);
matrix.remove_vertex_unchecked(b);
let _ = matrix.add_vertex();
let _ = matrix.add_vertex();
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| matrix.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)| !matrix.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn undirected_add_vertex_after_vertex_deletion() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.remove_vertex_unchecked(a);
matrix.remove_vertex_unchecked(b);
let _ = matrix.add_vertex();
let _ = matrix.add_vertex();
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.reusable_vertex_ids.len(), 0);
assert_eq!(matrix.vertices().len(), 3);
assert!(vec![a, b, c]
.iter()
.all(|vertex_id| matrix.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)| !matrix.has_any_edge_unchecked(src_id, dst_id)));
}
#[test]
fn directed_add_edge() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.edges().len(), 3);
for (src_id, dst_id, edge) in matrix.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 matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.edges().len(), 3);
for (src_id, dst_id, edge) in matrix.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 matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert!(matrix.has_any_edge_unchecked(a, b));
assert!(matrix.has_any_edge_unchecked(b, c));
assert!(matrix.has_any_edge_unchecked(c, a));
}
#[test]
fn undirected_has_edge() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert!(matrix.has_any_edge_unchecked(a, b));
assert!(matrix.has_any_edge_unchecked(b, a));
assert!(matrix.has_any_edge_unchecked(b, c));
assert!(matrix.has_any_edge_unchecked(c, b));
assert!(matrix.has_any_edge_unchecked(c, a));
assert!(matrix.has_any_edge_unchecked(a, c));
}
#[test]
fn directed_update_edge() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
let ab = matrix.add_edge_unchecked(a, b, 1.into());
let bc = matrix.add_edge_unchecked(b, c, 2.into());
let ca = matrix.add_edge_unchecked(c, a, 3.into());
matrix.update_edge_unchecked(a, b, ab, 2.into());
matrix.update_edge_unchecked(b, c, bc, 3.into());
matrix.update_edge_unchecked(c, a, ca, 4.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.edges().len(), 3);
for (src_id, dst_id, edge) in matrix.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 matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
let ab = matrix.add_edge_unchecked(a, b, 1.into());
let bc = matrix.add_edge_unchecked(b, c, 2.into());
let ca = matrix.add_edge_unchecked(c, a, 3.into());
matrix.update_edge_unchecked(a, b, ab, 2.into());
matrix.update_edge_unchecked(b, c, bc, 3.into());
matrix.update_edge_unchecked(c, a, ca, 4.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.edges().len(), 3);
for (src_id, dst_id, edge) in matrix.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 matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
let ab = matrix.add_edge_unchecked(a, b, 1.into());
let bc = matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
matrix.remove_edge_unchecked(a, b, ab);
matrix.remove_edge_unchecked(b, c, bc);
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.edges().len(), 1);
assert_eq!(
matrix.edges_between_unchecked(c, a)[0]
.get_weight()
.unwrap(),
3
);
}
#[test]
fn undirected_remove_edge() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
let ab = matrix.add_edge_unchecked(a, b, 1.into());
let bc = matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
matrix.remove_edge_unchecked(a, b, ab);
matrix.remove_edge_unchecked(b, c, bc);
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.edges().len(), 1);
assert_eq!(
matrix.edges_between_unchecked(a, c)[0]
.get_weight()
.unwrap(),
3
);
}
#[test]
fn directed_neighbors() {
let mut matrix = DiMat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 9);
assert_eq!(matrix.neighbors_unchecked(a).len(), 1);
assert_eq!(*matrix.neighbors_unchecked(a).get(0).unwrap(), b);
assert_eq!(matrix.neighbors_unchecked(b).len(), 1);
assert_eq!(*matrix.neighbors_unchecked(b).get(0).unwrap(), c);
assert_eq!(matrix.neighbors_unchecked(c).len(), 1);
assert_eq!(*matrix.neighbors_unchecked(c).get(0).unwrap(), a);
}
#[test]
fn undirected_neighbors() {
let mut matrix = Mat::<usize>::init();
let a = matrix.add_vertex();
let b = matrix.add_vertex();
let c = matrix.add_vertex();
matrix.add_edge_unchecked(a, b, 1.into());
matrix.add_edge_unchecked(b, c, 2.into());
matrix.add_edge_unchecked(c, a, 3.into());
assert_eq!(matrix.vertex_count(), 3);
assert_eq!(matrix.total_vertex_count(), 3);
assert_eq!(matrix.vec.len(), 6);
assert_eq!(matrix.neighbors_unchecked(a).len(), 2);
assert!(vec![b, c]
.iter()
.all(|vertex_id| matrix.neighbors_unchecked(a).contains(vertex_id)));
assert_eq!(matrix.neighbors_unchecked(b).len(), 2);
assert!(vec![a, c]
.iter()
.all(|vertex_id| matrix.neighbors_unchecked(b).contains(vertex_id)));
assert_eq!(matrix.neighbors_unchecked(c).len(), 2);
assert!(vec![a, b]
.iter()
.all(|vertex_id| matrix.neighbors_unchecked(c).contains(vertex_id)));
}
#[test]
fn edge_count() {
let mut mat = Mat::<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 = DiMat::<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);
}
}