use std::collections::{hash_map::DefaultHasher, HashMap, HashSet, VecDeque};
use std::hash::Hasher;
use linked_hash_map::LinkedHashMap;
use linked_hash_set::LinkedHashSet;
use super::{GraphOperationError, Label, Result};
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct VertexId(u64);
#[derive(Debug, Default, Eq, PartialEq)]
pub struct Graph<V: Label, E: Label> {
pub(crate) vertices: LinkedHashMap<VertexId, LinkedHashSet<([VertexId; 2], E)>>,
pub(crate) vertices_data: HashMap<VertexId, V>,
}
impl<V: Label, E: Label> Graph<V, E> {
pub fn new() -> Self {
Self::default()
}
pub fn get_vertex_id(&self, vertex: &V) -> VertexId {
let mut hasher = DefaultHasher::new();
vertex.hash(&mut hasher);
VertexId(hasher.finish())
}
pub fn add_vertex(&mut self, vertex: V) -> Result<VertexId> {
let vertex_id = self.get_vertex_id(&vertex);
if self
.vertices
.insert(vertex_id, LinkedHashSet::new())
.is_some()
{
return Err(GraphOperationError::VertexAlreadyExists);
}
self.vertices_data.insert(vertex_id, vertex);
Ok(vertex_id)
}
pub fn get_vertex(&self, vertex: VertexId) -> Result<&V> {
self.vertices_data
.get(&vertex)
.ok_or(GraphOperationError::VertexDoesNotExist)
}
pub fn remove_vertex(&mut self, target_vertex: VertexId) -> Result<()> {
self.get_vertex(target_vertex)?;
let mut pairs = Vec::new();
for &other_vertex in self.vertices.keys() {
if let Ok(edge) = self.get_edge(other_vertex, target_vertex).cloned() {
pairs.push((other_vertex, edge));
}
}
for (other_vertex, edge) in &pairs {
if let Some(neighbours) = self.vertices.get_mut(other_vertex) {
neighbours.remove(edge);
}
}
self.vertices.remove(&target_vertex);
self.vertices_data.remove(&target_vertex);
Ok(())
}
pub fn add_edge(&mut self, from: VertexId, to: VertexId, edge: E) -> Result<()> {
if self.vertices.get(&to).is_some() {
if let Some(neighbours) = self.vertices.get_mut(&from) {
neighbours.insert(([from, to], edge));
return Ok(());
}
}
Err(GraphOperationError::VertexDoesNotExist)
}
pub fn get_edge(&self, from: VertexId, to: VertexId) -> Result<&([VertexId; 2], E)> {
if let Some(neighbours) = self.vertices.get(&from) {
for edge in neighbours {
let [_, destination_vertex] = edge.0;
if destination_vertex == to {
return Ok(edge);
}
}
}
Err(GraphOperationError::EdgeDoesNotExist)
}
pub fn get_edge_value(&self, from: VertexId, to: VertexId) -> Result<&E> {
let (_, value) = self.get_edge(from, to)?;
Ok(value)
}
pub fn remove_edge(&mut self, from: VertexId, to: VertexId) -> Result<()> {
if let Ok(edge) = self.get_edge(from, to).cloned() {
if let Some(neighbours) = self.vertices.get_mut(&from) {
neighbours.remove(&edge);
return Ok(());
}
}
Err(GraphOperationError::EdgeDoesNotExist)
}
pub fn vertices_count(&self) -> usize {
self.vertices.len()
}
pub fn edges_count(&self) -> usize {
let mut count = 0;
for (_, neighbours) in self.vertices.iter() {
count += neighbours.len();
}
count
}
#[allow(clippy::type_complexity)]
pub fn vertices(&self) -> Result<Vec<(&V, Vec<(&V, &E)>)>> {
self.vertices
.keys()
.map(|&id| self.get_vertex_info(id))
.collect::<Result<Vec<_>>>()
}
pub fn edges(&self) -> Result<Vec<([&V; 2], &E)>> {
let mut edges = Vec::new();
for (_, neighbours) in self.vertices.iter() {
for ([from, to], edge) in neighbours {
edges.push(([self.get_vertex(*from)?, self.get_vertex(*to)?], edge));
}
}
Ok(edges)
}
pub fn get_vertex_info(&self, vertex_id: VertexId) -> Result<(&V, Vec<(&V, &E)>)> {
let vertex = self.get_vertex(vertex_id)?;
let mut adjacent_vertices = Vec::new();
if let Some(neighbours) = self.vertices.get(&vertex_id) {
for ([_, vertex], edge) in neighbours {
adjacent_vertices.push((self.get_vertex(*vertex)?, edge));
}
}
Ok((vertex, adjacent_vertices))
}
fn generic_search<
QueueTy,
QueueInitFn: Fn() -> QueueTy,
QueueInsertFn: Fn(&mut QueueTy, VertexId),
QueueRemoveFn: Fn(&mut QueueTy) -> Option<VertexId>,
AccessFn: FnMut(&V, Vec<(&V, &E)>),
>(
&self,
queue_init: QueueInitFn,
queue_insert: QueueInsertFn,
queue_remove: QueueRemoveFn,
source: VertexId,
mut access: AccessFn,
) -> Result<()> {
let mut queue = queue_init();
let mut visited = HashSet::new();
queue_insert(&mut queue, source);
visited.insert(source);
while let Some(vertex) = queue_remove(&mut queue) {
let (vertex, adjacent_vertices) = self.get_vertex_info(vertex)?;
for (adjacent_vertex, _) in adjacent_vertices.iter() {
let id = self.get_vertex_id(adjacent_vertex);
if !visited.contains(&id) {
queue_insert(&mut queue, id);
visited.insert(id);
}
}
access(vertex, adjacent_vertices);
}
Ok(())
}
pub fn bfs<F: FnMut(&V, Vec<(&V, &E)>)>(&self, source: VertexId, access: F) -> Result<()> {
self.generic_search(
VecDeque::new,
|queue, vertex| queue.push_back(vertex),
|queue| queue.pop_front(),
source,
access,
)
}
pub fn dfs<F: FnMut(&V, Vec<(&V, &E)>)>(&self, source: VertexId, access: F) -> Result<()> {
self.generic_search(
Vec::new,
|stack, vertex| stack.push(vertex),
|stack| stack.pop(),
source,
access,
)
}
}