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 fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> {
let mut distanz_matrix: Vec<Vec<u8>> = vec![vec![]; adjazenz_matrix.len()];
pub fn calculate_distanz_matrix(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut distanz_matrix: Vec<Vec<usize>> = vec![vec![]; adjazenz_matrix.len()];
let mut potenz_matrix = clone(adjazenz_matrix);
for k in 1..(adjazenz_matrix.len() + 1) {
potenz_matrix = matrix::mult(&potenz_matrix, adjazenz_matrix);
for k in 1..=adjazenz_matrix.len() {
potenz_matrix = mult(&potenz_matrix, adjazenz_matrix);
for i in 0..adjazenz_matrix.len() {
for j in 0..adjazenz_matrix.len() {
if k != 1 {
if potenz_matrix[i][j] != 0 && distanz_matrix[i][j] == u8::MAX {
distanz_matrix[i][j] = u8::try_from(k).unwrap();
if potenz_matrix[i][j] != 0 && distanz_matrix[i][j] == usize::MAX {
distanz_matrix[i][j] = k;
}
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 {
distanz_matrix[i].push(1);
} 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
}
pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> {
let mut weg_matrix: Vec<Vec<u8>> = vec![vec![]; adjazenz_matrix.len()];
pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut weg_matrix: Vec<Vec<usize>> = vec![vec![]; adjazenz_matrix.len()];
let mut potenz_matrix = clone(adjazenz_matrix);
for k in 1..(adjazenz_matrix.len() + 1) {
potenz_matrix = matrix::mult(&potenz_matrix, adjazenz_matrix);
for k in 1..=adjazenz_matrix.len() {
potenz_matrix = mult(&potenz_matrix, adjazenz_matrix);
for i in 0..adjazenz_matrix.len() {
for j in 0..adjazenz_matrix.len() {
if k != 1 {
@ -54,15 +56,15 @@ pub fn calculate_weg_matrix(adjazenz_matrix: &Vec<Vec<u8>>) -> Vec<Vec<u8>> {
weg_matrix
}
pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<u8>>) -> Vec<u8> {
let mut exzentrizitaeten: Vec<u8> = vec![];
let mut exzentrizitaet: u8;
pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<usize>>) -> Vec<usize> {
let mut exzentrizitaeten = vec![];
let mut exzentrizitaet: usize;
for vector in distanz_matrix {
exzentrizitaet = 0;
for value in vector {
if value == u8::MAX {
if value == usize::MAX {
continue;
}
exzentrizitaet = exzentrizitaet.max(value);
@ -72,23 +74,23 @@ pub fn calculate_exzentrizitaeten(distanz_matrix: Vec<Vec<u8>>) -> Vec<u8> {
exzentrizitaeten
}
pub fn calculate_properties(exzentrizitaeten: &[u8]) -> (u8, u8, Vec<u8>, bool) {
let mut radius = u8::MAX;
let mut diameter: u8 = 0;
let mut centre: Vec<u8> = vec![];
let mut connected: bool = true;
pub fn calculate_properties(exzentrizitaeten: &[usize]) -> (usize, usize, Vec<usize>, bool) {
let mut radius = usize::MAX;
let mut diameter = 0;
let mut centre = vec![];
let mut connected = true;
for (index, value) in exzentrizitaeten.iter().enumerate() {
if value > &diameter {
diameter = *value;
}
if value == &radius {
centre.push(u8::try_from(index + 1).unwrap());
centre.push(index + 1);
}
if value < &radius {
radius = *value;
centre.clear();
centre.push(u8::try_from(index + 1).unwrap());
centre.push(index + 1);
}
if value == &0 {
connected = false;
@ -97,15 +99,15 @@ pub fn calculate_properties(exzentrizitaeten: &[u8]) -> (u8, u8, Vec<u8>, bool)
(radius, diameter, centre, connected)
}
pub fn find_components(weg_matrix: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
let mut components: Vec<Vec<u8>> = vec![];
let mut component: Vec<u8>;
pub fn find_components(weg_matrix: Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut components: Vec<Vec<usize>> = vec![];
let mut component: Vec<usize>;
for array in weg_matrix {
component = vec![];
for (index, value) in array.iter().enumerate() {
if value == &1 {
component.push(u8::try_from(index + 1).unwrap());
component.push(index + 1);
}
}
if !components.contains(&component) {
@ -115,46 +117,56 @@ pub fn find_components(weg_matrix: Vec<Vec<u8>>) -> Vec<Vec<u8>> {
components
}
pub fn find_articulations_and_bridges(
adjazenz_matrix: &mut Vec<Vec<u8>>,
components: &Vec<Vec<u8>>,
) -> (Vec<u8>, Vec<Vec<u8>>) {
let mut bridges: Vec<Vec<u8>> = vec![];
let mut articulations: Vec<u8> = vec![];
let mut temp_matrix = adjazenz_matrix.clone();
pub fn find_bridges(adjazenz_matrix: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let size = adjazenz_matrix.len();
let mut bridges: Vec<Vec<usize>> = vec![];
let mut visited = vec![false; size];
let mut discovery_time = vec![0; size];
let mut low_time = vec![0; size];
let time = 0;
for n in 0..temp_matrix.len() {
for i in 0..temp_matrix.len() {
for j in 0..temp_matrix.len() {
temp_matrix[i][n] = 0;
temp_matrix[n][j] = 0;
if n != 0 {
continue;
}
let bridge = vec![
u8::try_from(usize::min(i + 1, j + 1)).unwrap(),
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;
}
for i in 0..size {
if !visited[i] {
dfs_bridges(
&mut bridges,
adjazenz_matrix,
&mut visited,
&mut discovery_time,
&mut low_time,
time,
i,
usize::MAX,
);
}
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 {
matrix.push(vec![]);
for j in 0..size {
if i == j {
matrix[i].push(0);
continue;
}
matrix[i].push(fastrand::u8(0..2));
random_value = fastrand::usize(0..=1);
matrix[i][j] = random_value;
matrix[j][i] = random_value;
matrix[i][i] = 0;
}
}
matrix
}
pub fn mult(matrix1: &Vec<Vec<usize>>, matrix2: &Vec<Vec<u8>>) -> Vec<Vec<usize>> {
let mut product: Vec<Vec<usize>> = vec![vec![]; matrix2.len()];
pub fn mult(matrix1: &Vec<Vec<usize>>, matrix2: &Vec<Vec<usize>>) -> Vec<Vec<usize>> {
let mut product = vec![vec![]; matrix2.len()];
let mut vector: Vec<usize>;
for (index, k) in (0..matrix1.len()).enumerate() {
vector = vec![];
for array in matrix2 {
vector.push(array[index].into());
vector.push(array[index]);
}
for array in matrix1 {
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
}
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![];
for i in 0..matrix.len() {
new_matrix.push(vec![]);
for j in 0..matrix.len() {
new_matrix[i].push(matrix[i][j].into());
new_matrix[i].push(matrix[i][j]);
}
}
new_matrix
}
pub fn show(matrix: &Vec<Vec<u8>>) {
pub fn show(matrix: &Vec<Vec<usize>>) {
for vector in matrix {
for value in vector {
print!("{value} ");
@ -58,10 +146,10 @@ pub fn show(matrix: &Vec<Vec<u8>>) {
}
}
pub fn read_csv(file_name: &str) -> Vec<Vec<u8>> {
let mut matrix: Vec<Vec<u8>> = vec![];
pub fn read_csv(file_name: &str) -> Vec<Vec<usize>> {
let mut matrix: Vec<Vec<usize>> = vec![];
let dir: String = "/home/rene/projects/Java/graphprogram/csv/".into();
let mut csv = ReaderBuilder::new()
let mut csv = csv::ReaderBuilder::new()
.has_headers(false)
.delimiter(b';')
.from_path(dir + file_name)

View File

@ -6,7 +6,7 @@ mod tests {
#[test]
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 weg_matrix = calculate_weg_matrix(&adjazenz_matrix);
@ -44,7 +44,8 @@ mod tests {
let exzentrizitaeten = calculate_exzentrizitaeten(distanz_matrix);
let properties = calculate_properties(&exzentrizitaeten);
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!(properties.0, 1);
@ -52,8 +53,8 @@ mod tests {
assert_eq!(properties.2, vec![4]);
assert_eq!(properties.3, true);
assert_eq!(components, vec![vec![1, 2, 3, 4, 5]]);
assert_eq!(result.1, vec![vec![4, 5]]);
assert_eq!(result.0, vec![4]);
assert_eq!(bridges, vec![vec![4, 5]]);
assert_eq!(articulations, vec![4]);
}
#[test]

View File

@ -7,13 +7,13 @@ use crate::graph::{
pub mod graph;
pub fn main() {
//let file_name = "50n.csv";
//let mut 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 file_name = "24n.csv";
let adjazenz_matrix = read_csv(file_name);
//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 weg_matrix = calculate_weg_matrix(&adjazenz_matrix);
println!("adjazen matrix:");
println!("adjazenz matrix:");
show(&adjazenz_matrix);
println!("\ndistanz matrix:");
show(&distanz_matrix);
@ -37,7 +37,6 @@ pub fn main() {
let components = find_components(weg_matrix);
println!("components: {components:?}");
let result = find_articulations_and_bridges(&mut adjazenz_matrix, &components);
println!("bridges: {:?}", result.1);
println!("articulations: {:?}", result.0);
println!("bridges: {:?}", find_bridges(&adjazenz_matrix));
println!("articulations: {:?}", find_articulations(&adjazenz_matrix));
}