use crate::graph::{Edge, Graph};
use crate::layout::types::{EdgeLabel, NodeLabel};
use std::collections::BTreeSet;
pub(crate) fn longest_path(g: &mut Graph<NodeLabel, EdgeLabel>) {
let mut visited = BTreeSet::new();
fn dfs(g: &mut Graph<NodeLabel, EdgeLabel>, v: &str, visited: &mut BTreeSet<String>) -> i32 {
if visited.contains(v) {
return g.node(v).and_then(|n| n.rank).unwrap_or(0);
}
visited.insert(v.to_string());
let out_edges = g.out_edges(v, None).unwrap_or_default();
let min_rank: Option<i32> = out_edges
.iter()
.map(|e| {
let minlen = g
.edge(&e.v, &e.w, e.name.as_deref())
.map(|l| l.minlen)
.unwrap_or(1);
dfs(g, &e.w, visited) - minlen
})
.min();
let rank = min_rank.unwrap_or(0);
if let Some(node) = g.node_mut(v) {
node.rank = Some(rank);
}
rank
}
let sources = g.sources();
for v in &sources {
dfs(g, v, &mut visited);
}
}
pub(crate) fn slack(g: &Graph<NodeLabel, EdgeLabel>, e: &Edge) -> i32 {
let Some(w_rank) = g.node(&e.w).and_then(|n| n.rank) else {
return 0;
};
let Some(v_rank) = g.node(&e.v).and_then(|n| n.rank) else {
return 0;
};
let minlen = g
.edge(&e.v, &e.w, e.name.as_deref())
.map(|l| l.minlen)
.unwrap_or(1);
w_rank - v_rank - minlen
}