master > master: code-rust - debugging im Alg
This commit is contained in:
parent
d0099eb7f9
commit
c17ba0fefb
@ -7,6 +7,7 @@ use std::hash::Hash;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::core::utils;
|
use crate::core::utils;
|
||||||
|
use crate::core::log::log_debug;
|
||||||
use crate::stacks::stack::Stack;
|
use crate::stacks::stack::Stack;
|
||||||
use crate::graphs::graph::Graph;
|
use crate::graphs::graph::Graph;
|
||||||
|
|
||||||
@ -28,10 +29,10 @@ enum State {
|
|||||||
|
|
||||||
/// # Tarjan Algorithm #
|
/// # Tarjan Algorithm #
|
||||||
/// Runs the Tarjan-Algorithm to compute the strongly connected components.
|
/// Runs the Tarjan-Algorithm to compute the strongly connected components.
|
||||||
pub fn tarjan_algorithm<T>(gph: &Graph<T>) -> Vec<Vec<T>>
|
pub fn tarjan_algorithm<T>(gph: &Graph<T>, debug: bool) -> Vec<Vec<T>>
|
||||||
where T: Eq + Hash + Clone + Display
|
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() {
|
for u in gph.nodes.iter() {
|
||||||
tarjan_visit(gph, u, &mut ctx);
|
tarjan_visit(gph, u, &mut ctx);
|
||||||
@ -41,7 +42,7 @@ pub fn tarjan_algorithm<T>(gph: &Graph<T>) -> Vec<Vec<T>>
|
|||||||
|
|
||||||
/// recursive depth-first search algorithm to compute components
|
/// recursive depth-first search algorithm to compute components
|
||||||
fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
||||||
where T: Eq + Hash + Clone + Display
|
where T: Eq + Hash + Clone + Copy + Display
|
||||||
{
|
{
|
||||||
if !(ctx.get_state(v) == State::UNTOUCHED) {
|
if !(ctx.get_state(v) == State::UNTOUCHED) {
|
||||||
return;
|
return;
|
||||||
@ -66,6 +67,10 @@ fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.set_state(v, State::FINISHED);
|
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) {
|
if ctx.get_index(v) == ctx.get_root(v) {
|
||||||
let mut component: Vec<T> = Vec::new();
|
let mut component: Vec<T> = Vec::new();
|
||||||
@ -73,9 +78,7 @@ fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
|||||||
let u = ctx.top();
|
let u = ctx.top();
|
||||||
ctx.pop();
|
ctx.pop();
|
||||||
component.push(u.clone());
|
component.push(u.clone());
|
||||||
if u == *v {
|
if u == *v { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx.components.push(component);
|
ctx.components.push(component);
|
||||||
}
|
}
|
||||||
@ -86,7 +89,8 @@ fn tarjan_visit<T>(gph: &Graph<T>, v: &T, ctx: &mut Context<T>)
|
|||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct NodeInformation {
|
struct NodeInformation<T> {
|
||||||
|
node: T,
|
||||||
root: usize,
|
root: usize,
|
||||||
index: usize,
|
index: usize,
|
||||||
state: State,
|
state: State,
|
||||||
@ -95,23 +99,25 @@ struct NodeInformation {
|
|||||||
struct Context<T> {
|
struct Context<T> {
|
||||||
stack: Stack<T>,
|
stack: Stack<T>,
|
||||||
max_index: usize,
|
max_index: usize,
|
||||||
infos: HashMap<T, NodeInformation>,
|
infos: HashMap<T, NodeInformation<T>>,
|
||||||
components: Vec<Vec<T>>,
|
components: Vec<Vec<T>>,
|
||||||
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Context<T>
|
impl<T> Context<T>
|
||||||
where T: Eq + Hash + Clone + Display
|
where T: Eq + Hash + Clone + Copy + Display
|
||||||
{
|
{
|
||||||
fn new(gph: &Graph<T>) -> Context<T> {
|
fn new(gph: &Graph<T>, debug: bool) -> Context<T> {
|
||||||
let mut infos = HashMap::<T, NodeInformation>::new();
|
let mut infos = HashMap::<T, NodeInformation<T>>::new();
|
||||||
for u in gph.nodes.iter() {
|
for u in gph.nodes.iter() {
|
||||||
infos.entry(u.clone()).or_insert(NodeInformation::new());
|
infos.entry(u.clone()).or_insert(NodeInformation::<T>::new(&u));
|
||||||
}
|
}
|
||||||
return Context {
|
return Context {
|
||||||
stack: Stack::new(),
|
stack: Stack::new(),
|
||||||
max_index: 0,
|
max_index: 0,
|
||||||
infos: infos,
|
infos: infos,
|
||||||
components: vec![],
|
components: vec![],
|
||||||
|
debug: debug,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +133,7 @@ impl<T> Context<T>
|
|||||||
return self.stack.pop();
|
return self.stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_infos(self: &mut Self, u: &T, info: NodeInformation) {
|
fn update_infos(self: &mut Self, u: &T, info: NodeInformation<T>) {
|
||||||
self.infos.insert(u.clone(), info);
|
self.infos.insert(u.clone(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,25 +155,29 @@ impl<T> Context<T>
|
|||||||
self.update_infos(u, info);
|
self.update_infos(u, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_info(self: &mut Self, u: &T) -> NodeInformation<T> {
|
||||||
|
return *self.infos.get(u).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn get_state(self: &mut Self, u: &T) -> State {
|
fn get_state(self: &mut Self, u: &T) -> State {
|
||||||
let info = *self.infos.get(u).unwrap();
|
return self.get_info(u).state;
|
||||||
return info.state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_root(self: &mut Self, u: &T) -> usize {
|
fn get_root(self: &mut Self, u: &T) -> usize {
|
||||||
let info = *self.infos.get(u).unwrap();
|
return self.get_info(u).root;
|
||||||
return info.root;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_index(self: &mut Self, u: &T) -> usize {
|
fn get_index(self: &mut Self, u: &T) -> usize {
|
||||||
let info = *self.infos.get(u).unwrap();
|
return self.get_info(u).index;
|
||||||
return info.index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeInformation {
|
impl<T> NodeInformation<T>
|
||||||
fn new() -> NodeInformation {
|
where T: Clone + Copy
|
||||||
|
{
|
||||||
|
fn new(node: &T) -> NodeInformation<T> {
|
||||||
return NodeInformation {
|
return NodeInformation {
|
||||||
|
node: node.clone(),
|
||||||
root: 0,
|
root: 0,
|
||||||
index: 0,
|
index: 0,
|
||||||
state: State::UNTOUCHED,
|
state: State::UNTOUCHED,
|
||||||
|
@ -63,9 +63,9 @@ fn fixture_graph3() -> graph::Graph<i32> {
|
|||||||
#[case(fixture_graph2(), vec![vec![1], vec![6], vec![7], vec![2,3,4,5]])]
|
#[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]])]
|
#[case(fixture_graph3(), vec![vec![1,2,3,4,5], vec![7], vec![6,8]])]
|
||||||
fn test_tarjan<T>(#[case] gph: graph::Graph<T>, #[case] expected: Vec<Vec<T>>)
|
fn test_tarjan<T>(#[case] gph: graph::Graph<T>, #[case] expected: Vec<Vec<T>>)
|
||||||
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)
|
assert_components_eq(&components, &expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user