2022-04-08 23:36:29 +02:00
|
|
|
// ----------------------------------------------------------------
|
|
|
|
// IMPORTS
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
use rstest::fixture;
|
|
|
|
use rstest::rstest;
|
|
|
|
use std::fmt::Display;
|
|
|
|
use std::hash::Hash;
|
|
|
|
|
|
|
|
use ads2::core::utils;
|
|
|
|
use ads2::graphs::graph;
|
|
|
|
use ads2::graphs::tarjan;
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
// Fixtures
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
#[fixture]
|
|
|
|
fn fixture_graph1() -> graph::Graph<i32> {
|
|
|
|
return graph::Graph::<i32>::new(
|
|
|
|
vec![1,2,3,4],
|
|
|
|
vec![(1,2), (2,4), (4,2)]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[fixture]
|
|
|
|
fn fixture_graph2() -> graph::Graph<i32> {
|
|
|
|
return graph::Graph::<i32>::new(
|
|
|
|
vec![1,2,3,4,5,6,7],
|
|
|
|
vec![(1,2), (1,3), (2,3), (3,4), (4,5), (5,2), (5,6), (5,7), (6,7)]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-13 23:13:14 +02:00
|
|
|
#[fixture]
|
|
|
|
fn fixture_graph3() -> graph::Graph<i32> {
|
|
|
|
return graph::Graph::<i32>::new(
|
|
|
|
vec![1,2,3,4,5,6,7,8],
|
|
|
|
vec![
|
|
|
|
(1,2),
|
|
|
|
(1,3),
|
|
|
|
(2,4),
|
|
|
|
(2,5),
|
|
|
|
(3,5),
|
|
|
|
(3,6),
|
|
|
|
(3,8),
|
|
|
|
(4,5),
|
|
|
|
(4,7),
|
|
|
|
(5,1),
|
|
|
|
(5,8),
|
|
|
|
(6,8),
|
|
|
|
(7,8),
|
2022-04-13 23:32:19 +02:00
|
|
|
(8,6),
|
2022-04-13 23:13:14 +02:00
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-04-08 23:36:29 +02:00
|
|
|
// ----------------------------------------------------------------
|
2022-04-18 19:03:28 +02:00
|
|
|
// Test Tarjan-Algorithm
|
2022-04-08 23:36:29 +02:00
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
#[rstest]
|
|
|
|
#[case(fixture_graph1(), vec![vec![1], vec![3], vec![2,4]])]
|
|
|
|
#[case(fixture_graph2(), vec![vec![1], vec![6], vec![7], vec![2,3,4,5]])]
|
2022-04-13 23:32:19 +02:00
|
|
|
#[case(fixture_graph3(), vec![vec![1,2,3,4,5], vec![7], vec![6,8]])]
|
2022-04-08 23:36:29 +02:00
|
|
|
fn test_tarjan<T>(#[case] gph: graph::Graph<T>, #[case] expected: Vec<Vec<T>>)
|
2022-04-14 05:01:30 +02:00
|
|
|
where T: Eq + Hash + Clone + Copy + Display
|
2022-04-08 23:36:29 +02:00
|
|
|
{
|
2022-04-14 05:01:30 +02:00
|
|
|
let components = tarjan::tarjan_algorithm(&gph, false);
|
2022-04-13 23:13:14 +02:00
|
|
|
assert_components_eq(&components, &expected)
|
2022-04-08 23:36:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
// AUXILIARY METHODS
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
fn check_components_eq<T>(components1: &Vec<Vec<T>>, components2: &Vec<Vec<T>>) -> bool
|
|
|
|
where T: Eq + Hash + Clone
|
|
|
|
{
|
|
|
|
if components1.len() != components2.len() {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
for component1 in components1 {
|
|
|
|
let mut found = false;
|
|
|
|
for component2 in components2 {
|
|
|
|
if utils::vec_to_set(component1) == utils::vec_to_set(component2) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn assert_components_eq<T>(components1: &Vec<Vec<T>>, components2: &Vec<Vec<T>>)
|
|
|
|
where T: Eq + Hash + Clone
|
|
|
|
{
|
|
|
|
assert!(check_components_eq(components1, components2));
|
|
|
|
}
|