use crate::{Graph, Vertex, utils};
use crate::algorithms::{VisitorDFS, dfs_with_visitor, VisitorBFS, bfs_with_visitor, VisitorDFSAction, VisitorBFSAction};
use crate::error::GraphError;
use crate::algorithms::definitions::ConnectedComponents;
struct CustomVisitor {
orders: Vec<usize>
}
impl <T> VisitorBFS<T> for CustomVisitor {
fn vertex_visited_event(&mut self, vertex: &Vertex<T>, _parents: &[Option<&Vertex<T>>]) -> Result<VisitorBFSAction, GraphError> {
self.orders.push(vertex.id());
Ok(VisitorBFSAction::Nothing)
}
}
pub fn find_connected_components<T>(graph: &Graph<T>) -> Result<Vec<Vec<& Vertex<T>>>, GraphError> {
let mut components = vec![];
let mut visited = vec![false; graph.size()];
for from in 1..graph.size() {
let from = graph.get_vertex(from)?;
if !visited[from.id()] {
let mut visitor = CustomVisitor{ orders: vec![] };
bfs_with_visitor(graph, from, &mut visitor)?;
let mut vec = vec![];
for vertex in visitor.orders {
vec.push(&graph.adj[vertex]);
visited[vertex] = true;
}
components.push(vec)
}
}
Ok(components)
}
struct CustomVisitorFirst {
orders: Vec<usize>,
visited: Vec<bool>
}
impl <T> VisitorDFS<T> for CustomVisitorFirst {
fn exit_from_vertex_event(&mut self, vertex: &Vertex<T>) -> Result<VisitorDFSAction, GraphError> {
if !self.visited[vertex.id()] {
self.visited[vertex.id()] = true;
self.orders.push(vertex.id());
Ok(VisitorDFSAction::Nothing)
} else {
Ok(VisitorDFSAction::Break)
}
}
}
struct CustomVisitorSecond {
orders: Vec<usize>,
visited: Vec<bool>
}
impl <T> VisitorDFS<T> for CustomVisitorSecond {
fn entry_to_vertex_event(&mut self, vertex: &Vertex<T>) -> Result<VisitorDFSAction, GraphError> {
if !self.visited[vertex.id()] {
self.visited[vertex.id()] = true;
self.orders.push(vertex.id());
Ok(VisitorDFSAction::Nothing)
} else {
Ok(VisitorDFSAction::Break)
}
}
}
pub fn find_strongly_connected_components_search<T>(graph: &Graph<T>) -> Result<ConnectedComponents<T>, GraphError> where T: Copy {
let graph_transp = utils::transpose(graph);
let mut components = vec![];
let mut orders = Vec::with_capacity(graph.size());
let mut visitor = CustomVisitorFirst {orders: vec![], visited: vec![false; graph.size()] };
for from in 1..graph.size() {
if !visitor.visited[from] {
dfs_with_visitor(&graph_transp, graph.get_vertex(from)?, &mut visitor)?;
for vertex in &visitor.orders {
orders.push(*vertex);
}
}
}
let mut visitor = CustomVisitorSecond {orders: vec![], visited: vec![false; graph.size()] };
for from in orders.iter().rev() {
if !visitor.visited[*from] {
visitor.orders.clear();
let mut component = vec![];
dfs_with_visitor(graph, graph.get_vertex(*from)?, &mut visitor)?;
for vertex in &visitor.orders {
component.push(&graph.adj[*vertex]);
}
components.push(component);
}
}
Ok(components)
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
#[test]
fn test_find_strongly_connected_components() {
let mut graph = Graph::new(8);
graph.add_edge(1, 2, 0.0).unwrap();
graph.add_edge(2, 6, 0.0).unwrap();
graph.add_edge(5, 1, 0.0).unwrap();
graph.add_edge(2, 5, 0.0).unwrap();
graph.add_edge(5, 6, 0.0).unwrap();
graph.add_edge(2, 3, 0.0).unwrap();
graph.add_edge(6, 7, 0.0).unwrap();
graph.add_edge(7, 6, 0.0).unwrap();
graph.add_edge(3, 7, 0.0).unwrap();
graph.add_edge(3, 4, 0.0).unwrap();
graph.add_edge(4, 3, 0.0).unwrap();
graph.add_edge(4, 8, 0.0).unwrap();
graph.add_edge(8, 4, 0.0).unwrap();
graph.add_edge(8, 7, 0.0).unwrap();
let components = find_strongly_connected_components_search(&graph).unwrap();
assert_eq!(components[0].iter().map(|vertex| vertex.id()).collect::<Vec<usize>>(), [6, 7]);
assert_eq!(components[1].iter().map(|vertex| vertex.id()).collect::<Vec<usize>>(), [3, 4, 8]);
assert_eq!(components[2].iter().map(|vertex| vertex.id()).collect::<Vec<usize>>(), [1, 2, 5]);
}
#[test]
fn test_find_connected_components(){
let mut graph = Graph::new(11);
graph.add_edge(1, 2, 0.0).unwrap();
graph.add_edge(2, 3, 0.0).unwrap();
graph.add_edge(3, 4, 0.0).unwrap();
graph.add_edge(5, 6, 0.0).unwrap();
graph.add_edge(6, 7, 0.0).unwrap();
graph.add_edge(8, 9, 0.0).unwrap();
graph.add_edge(9, 10, 0.0).unwrap();
graph.add_edge(10, 11, 0.0).unwrap();
let components = find_connected_components(&graph).unwrap();
assert_eq!(components[0].iter().map(|elem| elem.id()).collect::<Vec<usize>>(), [1, 2, 3, 4]);
assert_eq!(components[1].iter().map(|elem| elem.id()).collect::<Vec<usize>>(), [5, 6, 7]);
assert_eq!(components[2].iter().map(|elem| elem.id()).collect::<Vec<usize>>(), [8, 9, 10, 11]);
assert_eq!(components.len(), 3);
let graph = Graph::<i32>::new(100);
let components = find_connected_components(&graph).unwrap();
assert_eq!(components.len(), 100);
}
}