use crate::optimizer::error::RouteError;
use crate::optimizer::types::Node;
use petgraph::graph::{DiGraph, NodeIndex};
use petgraph::algo::kosaraju_scc;
use petgraph::visit::EdgeRef;
use std::collections::HashMap;
pub struct SccFilter;
impl SccFilter {
pub fn retain_largest<E: Clone>(
graph: &DiGraph<Node, E>
) -> Result<DiGraph<Node, E>, RouteError> {
if graph.node_count() == 0 {
return Ok(DiGraph::new());
}
let sccs = kosaraju_scc(graph);
let largest_scc = sccs.into_iter()
.max_by_key(Vec::len)
.ok_or(RouteError::NoStronglyConnectedComponent)?;
let mut new_graph = DiGraph::new();
let mut old_to_new: HashMap<NodeIndex, NodeIndex> = HashMap::with_capacity(largest_scc.len());
for &old_idx in &largest_scc {
let node = graph[old_idx].clone();
let new_idx = new_graph.add_node(node);
old_to_new.insert(old_idx, new_idx);
}
for &old_idx in &largest_scc {
let new_from = old_to_new[&old_idx];
for edge in graph.edges(old_idx) {
if let Some(&new_to) = old_to_new.get(&edge.target()) {
new_graph.add_edge(new_from, new_to, edge.weight().clone());
}
}
}
Ok(new_graph)
}
}