diff --git a/code/rust/src/graphs/tarjan.rs b/code/rust/src/graphs/tarjan.rs index 8ee853a..bc00161 100644 --- a/code/rust/src/graphs/tarjan.rs +++ b/code/rust/src/graphs/tarjan.rs @@ -7,6 +7,7 @@ use std::hash::Hash; use std::collections::HashMap; use crate::core::utils; +use crate::core::log::log_debug; use crate::stacks::stack::Stack; use crate::graphs::graph::Graph; @@ -28,10 +29,10 @@ enum State { /// # Tarjan Algorithm # /// Runs the Tarjan-Algorithm to compute the strongly connected components. -pub fn tarjan_algorithm(gph: &Graph) -> Vec> - where T: Eq + Hash + Clone + Display +pub fn tarjan_algorithm(gph: &Graph, debug: bool) -> Vec> + where T: Eq + Hash + Clone + Copy + Display { - let mut ctx = Context::new(&gph); + let mut ctx = Context::new(&gph, debug); for u in gph.nodes.iter() { tarjan_visit(gph, u, &mut ctx); @@ -41,7 +42,7 @@ pub fn tarjan_algorithm(gph: &Graph) -> Vec> /// recursive depth-first search algorithm to compute components fn tarjan_visit(gph: &Graph, v: &T, ctx: &mut Context) - where T: Eq + Hash + Clone + Display + where T: Eq + Hash + Clone + Copy + Display { if !(ctx.get_state(v) == State::UNTOUCHED) { return; @@ -66,6 +67,10 @@ fn tarjan_visit(gph: &Graph, v: &T, ctx: &mut Context) } } ctx.set_state(v, State::FINISHED); + if ctx.debug { + let info = ctx.get_info(&v); + log_debug!("node, index, component: ({}, {}, {})", info.node, info.index, info.root); + } if ctx.get_index(v) == ctx.get_root(v) { let mut component: Vec = Vec::new(); @@ -73,9 +78,7 @@ fn tarjan_visit(gph: &Graph, v: &T, ctx: &mut Context) let u = ctx.top(); ctx.pop(); component.push(u.clone()); - if u == *v { - break; - } + if u == *v { break; } } ctx.components.push(component); } @@ -86,7 +89,8 @@ fn tarjan_visit(gph: &Graph, v: &T, ctx: &mut Context) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #[derive(Clone, Copy)] -struct NodeInformation { +struct NodeInformation { + node: T, root: usize, index: usize, state: State, @@ -95,23 +99,25 @@ struct NodeInformation { struct Context { stack: Stack, max_index: usize, - infos: HashMap, + infos: HashMap>, components: Vec>, + debug: bool, } impl Context - where T: Eq + Hash + Clone + Display + where T: Eq + Hash + Clone + Copy + Display { - fn new(gph: &Graph) -> Context { - let mut infos = HashMap::::new(); + fn new(gph: &Graph, debug: bool) -> Context { + let mut infos = HashMap::>::new(); for u in gph.nodes.iter() { - infos.entry(u.clone()).or_insert(NodeInformation::new()); + infos.entry(u.clone()).or_insert(NodeInformation::::new(&u)); } return Context { stack: Stack::new(), max_index: 0, infos: infos, components: vec![], + debug: debug, }; } @@ -127,7 +133,7 @@ impl Context return self.stack.pop(); } - fn update_infos(self: &mut Self, u: &T, info: NodeInformation) { + fn update_infos(self: &mut Self, u: &T, info: NodeInformation) { self.infos.insert(u.clone(), info); } @@ -149,25 +155,29 @@ impl Context self.update_infos(u, info); } + fn get_info(self: &mut Self, u: &T) -> NodeInformation { + return *self.infos.get(u).unwrap(); + } + fn get_state(self: &mut Self, u: &T) -> State { - let info = *self.infos.get(u).unwrap(); - return info.state; + return self.get_info(u).state; } fn get_root(self: &mut Self, u: &T) -> usize { - let info = *self.infos.get(u).unwrap(); - return info.root; + return self.get_info(u).root; } fn get_index(self: &mut Self, u: &T) -> usize { - let info = *self.infos.get(u).unwrap(); - return info.index; + return self.get_info(u).index; } } -impl NodeInformation { - fn new() -> NodeInformation { +impl NodeInformation + where T: Clone + Copy +{ + fn new(node: &T) -> NodeInformation { return NodeInformation { + node: node.clone(), root: 0, index: 0, state: State::UNTOUCHED, diff --git a/code/rust/tests/test_graphs/test_tarjan.rs b/code/rust/tests/test_graphs/test_tarjan.rs index 916217b..81cbbaf 100644 --- a/code/rust/tests/test_graphs/test_tarjan.rs +++ b/code/rust/tests/test_graphs/test_tarjan.rs @@ -63,9 +63,9 @@ fn fixture_graph3() -> graph::Graph { #[case(fixture_graph2(), vec![vec![1], vec![6], vec![7], vec![2,3,4,5]])] #[case(fixture_graph3(), vec![vec![1,2,3,4,5], vec![7], vec![6,8]])] fn test_tarjan(#[case] gph: graph::Graph, #[case] expected: Vec>) - where T: Eq + Hash + Clone + Display + where T: Eq + Hash + Clone + Copy + Display { - let components = tarjan::tarjan_algorithm(&gph); + let components = tarjan::tarjan_algorithm(&gph, false); assert_components_eq(&components, &expected) }