implemented dfs

it's way faster now
This commit is contained in:
René Fuhry 2023-06-05 16:07:36 +02:00 committed by GitHub
parent 11f90b5cc8
commit 8962baadf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 199 additions and 99 deletions

View File

@ -1,18 +1,20 @@
use self::matrix::clone; use matrix::{clone, dfs_bridges, mult};
use self::matrix::dfs_articulations;
pub mod matrix; pub mod matrix;
pub fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> { pub fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut distanz_matrix: Vec<Vec<u8>> = vec![vec![]; adjazenz_matrix.len()]; let mut distanz_matrix: Vec<Vec<usize>> = vec![vec![]; adjazenz_matrix.len()];
let mut potenz_matrix = clone(adjazenz_matrix); let mut potenz_matrix = clone(adjazenz_matrix);
for k in 1..(adjazenz_matrix.len() + 1) { for k in 1..=adjazenz_matrix.len() {
potenz_matrix = matrix::mult(&potenz_matrix, adjazenz_matrix); potenz_matrix = mult(&potenz_matrix, adjazenz_matrix);
for i in 0..adjazenz_matrix.len() { for i in 0..adjazenz_matrix.len() {
for j in 0..adjazenz_matrix.len() { for j in 0..adjazenz_matrix.len() {
if k != 1 { if k != 1 {
if potenz_matrix[i][j] != 0 && distanz_matrix[i][j] == u8::MAX { if potenz_matrix[i][j] != 0 && distanz_matrix[i][j] == usize::MAX {
distanz_matrix[i][j] = u8::try_from(k).unwrap(); distanz_matrix[i][j] = k;
} }
continue; continue;
} }
@ -21,7 +23,7 @@ pub fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>>
} else if adjazenz_matrix[i][j] == 1 { } else if adjazenz_matrix[i][j] == 1 {
distanz_matrix[i].push(1); distanz_matrix[i].push(1);
} else { } else {
distanz_matrix[i].push(u8::MAX); distanz_matrix[i].push(usize::MAX);
} }
} }
} }
@ -29,12 +31,12 @@ pub fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>>
distanz_matrix distanz_matrix
} }
pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> { pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut weg_matrix: Vec<Vec<u8>> = vec![vec![]; adjazenz_matrix.len()]; let mut weg_matrix: Vec<Vec<usize>> = vec![vec![]; adjazenz_matrix.len()];
let mut potenz_matrix = clone(adjazenz_matrix); let mut potenz_matrix = clone(adjazenz_matrix);
for k in 1..(adjazenz_matrix.len() + 1) { for k in 1..=adjazenz_matrix.len() {
potenz_matrix = matrix::mult(&potenz_matrix, adjazenz_matrix); potenz_matrix = mult(&potenz_matrix, adjazenz_matrix);
for i in 0..adjazenz_matrix.len() { for i in 0..adjazenz_matrix.len() {
for j in 0..adjazenz_matrix.len() { for j in 0..adjazenz_matrix.len() {
if k != 1 { if k != 1 {
@ -54,15 +56,15 @@ pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> {
weg_matrix weg_matrix
} }
pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<u8>>) -> Vec<u8> { pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<usize>>) -> Vec<usize> {
let mut exzentrizitaeten: Vec<u8> = vec![]; let mut exzentrizitaeten = vec![];
let mut exzentrizitaet: u8; let mut exzentrizitaet: usize;
for vector in distanz_matrix { for vector in distanz_matrix {
exzentrizitaet = 0; exzentrizitaet = 0;
for value in vector { for value in vector {
if value == u8::MAX { if value == usize::MAX {
continue; continue;
} }
exzentrizitaet = exzentrizitaet.max(value); exzentrizitaet = exzentrizitaet.max(value);
@ -72,23 +74,23 @@ pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<u8>>) -> Vec<u8> {
exzentrizitaeten exzentrizitaeten
} }
pub fn calculate_properties(exzentrizitaeten: &[u8]) -> (u8, u8, Vec<u8>, bool) { pub fn calculate_properties(exzentrizitaeten: &[usize]) -> (usize, usize, Vec<usize>, bool) {
let mut radius = u8::MAX; let mut radius = usize::MAX;
let mut diameter: u8 = 0; let mut diameter = 0;
let mut centre: Vec<u8> = vec![]; let mut centre = vec![];
let mut connected: bool = true; let mut connected = true;
for (index, value) in exzentrizitaeten.iter().enumerate() { for (index, value) in exzentrizitaeten.iter().enumerate() {
if value > &diameter { if value > &diameter {
diameter = *value; diameter = *value;
} }
if value == &radius { if value == &radius {
centre.push(u8::try_from(index + 1).unwrap()); centre.push(index + 1);
} }
if value < &radius { if value < &radius {
radius = *value; radius = *value;
centre.clear(); centre.clear();
centre.push(u8::try_from(index + 1).unwrap()); centre.push(index + 1);
} }
if value == &0 { if value == &0 {
connected = false; connected = false;
@ -97,15 +99,15 @@ pub fn calculate_properties(exzentrizitaeten: &[u8]) -> (u8, u8, Vec<u8>, bool)
(radius, diameter, centre, connected) (radius, diameter, centre, connected)
} }
pub fn find_components(weg_matrix: Vec<Vec<u8>>) -> Vec<Vec<u8>> { pub fn find_components(weg_matrix: Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut components: Vec<Vec<u8>> = vec![]; let mut components: Vec<Vec<usize>> = vec![];
let mut component: Vec<u8>; let mut component: Vec<usize>;
for array in weg_matrix { for array in weg_matrix {
component = vec![]; component = vec![];
for (index, value) in array.iter().enumerate() { for (index, value) in array.iter().enumerate() {
if value == &1 { if value == &1 {
component.push(u8::try_from(index + 1).unwrap()); component.push(index + 1);
} }
} }
if !components.contains(&component) { if !components.contains(&component) {
@ -115,46 +117,56 @@ pub fn find_components(weg_matrix: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
components components
} }
pub fn find_articulations_and_bridges( pub fn find_bridges(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
adjazenz_matrix: &mut Vec<Vec<u8>>, let size = adjazenz_matrix.len();
components: &Vec<Vec<u8>>, let mut bridges: Vec<Vec<usize>> = vec![];
) -> (Vec<u8>, Vec<Vec<u8>>) { let mut visited = vec![false; size];
let mut bridges: Vec<Vec<u8>> = vec![]; let mut discovery_time = vec![0; size];
let mut articulations: Vec<u8> = vec![]; let mut low_time = vec![0; size];
let mut temp_matrix = adjazenz_matrix.clone(); let time = 0;
for n in 0..temp_matrix.len() { for i in 0..size {
for i in 0..temp_matrix.len() { if !visited[i] {
for j in 0..temp_matrix.len() { dfs_bridges(
temp_matrix[i][n] = 0; &mut bridges,
temp_matrix[n][j] = 0; adjazenz_matrix,
&mut visited,
if n != 0 { &mut discovery_time,
continue; &mut low_time,
} time,
let bridge = vec![ i,
u8::try_from(usize::min(i + 1, j + 1)).unwrap(), usize::MAX,
u8::try_from(usize::max(i + 1, j + 1)).unwrap(), );
];
let prev_value = adjazenz_matrix[i][j];
adjazenz_matrix[i][j] = 0;
adjazenz_matrix[j][i] = 0;
if find_components(calculate_weg_matrix(adjazenz_matrix)).len() > components.len()
&& !bridges.contains(&bridge)
{
bridges.push(bridge);
}
adjazenz_matrix[i][j] = prev_value;
adjazenz_matrix[j][i] = prev_value;
}
} }
if find_components(calculate_weg_matrix(&temp_matrix)).len() > (components.len() + 1) {
articulations.push(u8::try_from(n + 1).unwrap());
}
temp_matrix = adjazenz_matrix.clone();
} }
(articulations, bridges) bridges
}
pub fn find_articulations(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<usize> {
let size = adjazenz_matrix.len();
let mut ariculations = vec![];
let mut is_articulation = vec![false; size];
let mut visited = vec![false; size];
let mut discovery_time = vec![0; size];
let mut low_time = vec![0; size];
let time = 0;
for i in 0..size {
if !visited[i] {
dfs_articulations(
&mut ariculations,
&mut is_articulation,
adjazenz_matrix,
&mut visited,
&mut discovery_time,
&mut low_time,
time,
i,
usize::MAX,
);
}
}
ariculations
} }

View File

@ -1,33 +1,26 @@
use csv::ReaderBuilder; pub fn fill_with_random(size: usize) -> Vec<Vec<usize>> {
let mut matrix = vec![vec![0; size]; size];
let mut random_value: usize;
pub fn fill_with_random(size: usize) -> Vec<Vec<u8>> {
assert!(
(size < u8::MAX.into() && size > 0),
"fill_with_random: size must not be bigger than 255 or smaller than 1, size was: {size}"
);
let mut matrix: Vec<Vec<u8>> = vec![];
for i in 0..size { for i in 0..size {
matrix.push(vec![]);
for j in 0..size { for j in 0..size {
if i == j { random_value = fastrand::usize(0..=1);
matrix[i].push(0); matrix[i][j] = random_value;
continue; matrix[j][i] = random_value;
} matrix[i][i] = 0;
matrix[i].push(fastrand::u8(0..2));
} }
} }
matrix matrix
} }
pub fn mult(matrix1: &Vec<Vec<usize>>, matrix2: &Vec<Vec<u8>>) -> Vec<Vec<usize>> { pub fn mult(matrix1: &Vec<Vec<usize>>, matrix2: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut product: Vec<Vec<usize>> = vec![vec![]; matrix2.len()]; let mut product = vec![vec![]; matrix2.len()];
let mut vector: Vec<usize>; let mut vector: Vec<usize>;
for (index, k) in (0..matrix1.len()).enumerate() { for (index, k) in (0..matrix1.len()).enumerate() {
vector = vec![]; vector = vec![];
for array in matrix2 { for array in matrix2 {
vector.push(array[index].into()); vector.push(array[index]);
} }
for array in matrix1 { for array in matrix1 {
product[k].push(array.iter().zip(vector.iter()).map(|(x, y)| x * y).sum()); product[k].push(array.iter().zip(vector.iter()).map(|(x, y)| x * y).sum());
@ -36,20 +29,115 @@ pub fn mult(matrix1: &Vec<Vec<usize>>, matrix2: &Vec<Vec<u8>>) -> Vec<Vec<usize>
product product
} }
pub fn clone(matrix: &Vec<Vec<u8>>) -> Vec<Vec<usize>> { pub fn dfs_bridges(
bridges: &mut Vec<Vec<usize>>,
adjazenz_matrix: &Vec<Vec<usize>>,
visited: &mut Vec<bool>,
discovery_time: &mut Vec<usize>,
low_time: &mut Vec<usize>,
time: usize,
vertex: usize,
parent: usize,
) {
let time = time + 1;
visited[vertex] = true;
discovery_time[vertex] = time;
low_time[vertex] = time;
for neighbor in 0..adjazenz_matrix.len() {
if adjazenz_matrix[vertex][neighbor] != 1 || visited[neighbor] {
continue;
}
if neighbor != parent {
low_time[vertex] = usize::min(low_time[vertex], discovery_time[neighbor]);
}
dfs_bridges(
bridges,
adjazenz_matrix,
visited,
discovery_time,
low_time,
time,
neighbor,
vertex,
);
low_time[vertex] = usize::min(low_time[vertex], low_time[neighbor]);
if discovery_time[vertex] < low_time[neighbor] {
bridges.push(vec![vertex + 1, neighbor + 1]);
}
}
}
pub fn dfs_articulations(
articulations: &mut Vec<usize>,
is_articulation: &mut Vec<bool>,
adjazenz_matrix: &Vec<Vec<usize>>,
visited: &mut Vec<bool>,
discovery_time: &mut Vec<usize>,
low_time: &mut Vec<usize>,
time: usize,
vertex: usize,
parent: usize,
) {
let time = time + 1;
visited[vertex] = true;
discovery_time[vertex] = time;
low_time[vertex] = time;
let mut child_count: usize = 0;
let mut articulation = false;
for neighbor in 0..adjazenz_matrix.len() {
if visited[neighbor] || neighbor == parent || parent == usize::MAX {
continue;
}
child_count += 1;
dfs_articulations(
articulations,
is_articulation,
adjazenz_matrix,
visited,
discovery_time,
low_time,
time,
vertex,
parent,
);
low_time[vertex] = usize::min(low_time[vertex], low_time[neighbor]);
if discovery_time[vertex] <= low_time[neighbor] {
articulation = true;
}
}
if parent != usize::MAX && child_count > 1 {
articulation = true;
}
if articulation {
is_articulation[vertex] = true;
articulations.push(vertex + 1);
}
}
pub fn clone(matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut new_matrix: Vec<Vec<usize>> = vec![]; let mut new_matrix: Vec<Vec<usize>> = vec![];
for i in 0..matrix.len() { for i in 0..matrix.len() {
new_matrix.push(vec![]); new_matrix.push(vec![]);
for j in 0..matrix.len() { for j in 0..matrix.len() {
new_matrix[i].push(matrix[i][j].into()); new_matrix[i].push(matrix[i][j]);
} }
} }
new_matrix new_matrix
} }
pub fn show(matrix: &Vec<Vec<u8>>) { pub fn show(matrix: &Vec<Vec<usize>>) {
for vector in matrix { for vector in matrix {
for value in vector { for value in vector {
print!("{value} "); print!("{value} ");
@ -58,10 +146,10 @@ pub fn show(matrix: &Vec<Vec<u8>>) {
} }
} }
pub fn read_csv(file_name: &str) -> Vec<Vec<u8>> { pub fn read_csv(file_name: &str) -> Vec<Vec<usize>> {
let mut matrix: Vec<Vec<u8>> = vec![]; let mut matrix: Vec<Vec<usize>> = vec![];
let dir: String = "/home/rene/projects/Java/graphprogram/csv/".into(); let dir: String = "/home/rene/projects/Java/graphprogram/csv/".into();
let mut csv = ReaderBuilder::new() let mut csv = csv::ReaderBuilder::new()
.has_headers(false) .has_headers(false)
.delimiter(b';') .delimiter(b';')
.from_path(dir + file_name) .from_path(dir + file_name)

View File

@ -6,7 +6,7 @@ mod tests {
#[test] #[test]
fn graph() { fn graph() {
let mut adjazenz_matrix = read_csv("art-brck.csv"); let adjazenz_matrix = read_csv("art-brck.csv");
let distanz_matrix = calculate_distanz_matrix(&adjazenz_matrix); let distanz_matrix = calculate_distanz_matrix(&adjazenz_matrix);
let weg_matrix = calculate_weg_matrix(&adjazenz_matrix); let weg_matrix = calculate_weg_matrix(&adjazenz_matrix);
@ -44,7 +44,8 @@ mod tests {
let exzentrizitaeten = calculate_exzentrizitaeten(distanz_matrix); let exzentrizitaeten = calculate_exzentrizitaeten(distanz_matrix);
let properties = calculate_properties(&exzentrizitaeten); let properties = calculate_properties(&exzentrizitaeten);
let components = find_components(weg_matrix); let components = find_components(weg_matrix);
let result = find_articulations_and_bridges(&mut adjazenz_matrix, &components); let bridges = find_bridges(&adjazenz_matrix);
let articulations = find_articulations(&adjazenz_matrix);
assert_eq!(exzentrizitaeten, vec![2, 2, 2, 1, 2]); assert_eq!(exzentrizitaeten, vec![2, 2, 2, 1, 2]);
assert_eq!(properties.0, 1); assert_eq!(properties.0, 1);
@ -52,8 +53,8 @@ mod tests {
assert_eq!(properties.2, vec![4]); assert_eq!(properties.2, vec![4]);
assert_eq!(properties.3, true); assert_eq!(properties.3, true);
assert_eq!(components, vec![vec![1, 2, 3, 4, 5]]); assert_eq!(components, vec![vec![1, 2, 3, 4, 5]]);
assert_eq!(result.1, vec![vec![4, 5]]); assert_eq!(bridges, vec![vec![4, 5]]);
assert_eq!(result.0, vec![4]); assert_eq!(articulations, vec![4]);
} }
#[test] #[test]

View File

@ -7,13 +7,13 @@ use crate::graph::{
pub mod graph; pub mod graph;
pub fn main() { pub fn main() {
//let file_name = "50n.csv"; let file_name = "24n.csv";
//let mut adjazenz_matrix = read_csv(file_name); let adjazenz_matrix = read_csv(file_name);
let mut adjazenz_matrix = fill_with_random(1); // with 48 verteces, it runs in about 10.2 seconds (run on the 2023-06-03 at 12:36) //let adjazenz_matrix = fill_with_random(320); // with 320 verteces, it runs in about 10 seconds on an Intel i5-10300H @4.3 GHz (2023-06-05 15:48)
let distanz_matrix = calculate_distanz_matrix(&adjazenz_matrix); let distanz_matrix = calculate_distanz_matrix(&adjazenz_matrix);
let weg_matrix = calculate_weg_matrix(&adjazenz_matrix); let weg_matrix = calculate_weg_matrix(&adjazenz_matrix);
println!("adjazen matrix:"); println!("adjazenz matrix:");
show(&adjazenz_matrix); show(&adjazenz_matrix);
println!("\ndistanz matrix:"); println!("\ndistanz matrix:");
show(&distanz_matrix); show(&distanz_matrix);
@ -37,7 +37,6 @@ pub fn main() {
let components = find_components(weg_matrix); let components = find_components(weg_matrix);
println!("components: {components:?}"); println!("components: {components:?}");
let result = find_articulations_and_bridges(&mut adjazenz_matrix, &components); println!("bridges: {:?}", find_bridges(&adjazenz_matrix));
println!("bridges: {:?}", result.1); println!("articulations: {:?}", find_articulations(&adjazenz_matrix));
println!("articulations: {:?}", result.0);
} }