From c88fd5412a9c31e9093f881497a2654bfe6f9ac0 Mon Sep 17 00:00:00 2001 From: AustrianToast Date: Fri, 11 Oct 2024 23:45:55 +0200 Subject: [PATCH] rewrite into c++ --- graph.c | 481 --------------------------------------------------- graph.cpp | 498 +++++++++++++++++++++++++++++++++++++++++++++++++++++ graph.h | 71 -------- graph.hpp | 33 ++++ main.c | 280 ------------------------------ main.cpp | 247 ++++++++++++++++++++++++++ matrix.c | 71 -------- matrix.cpp | 70 ++++++++ matrix.h | 28 --- matrix.hpp | 15 ++ 10 files changed, 863 insertions(+), 931 deletions(-) delete mode 100644 graph.c create mode 100644 graph.cpp delete mode 100644 graph.h create mode 100644 graph.hpp delete mode 100644 main.c create mode 100644 main.cpp delete mode 100644 matrix.c create mode 100644 matrix.cpp delete mode 100644 matrix.h create mode 100644 matrix.hpp diff --git a/graph.c b/graph.c deleted file mode 100644 index 6110d04..0000000 --- a/graph.c +++ /dev/null @@ -1,481 +0,0 @@ -#include "graph.h" -#include -#include -#include -#include -#include -#include "matrix.h" - -void random_adjacency(const uint64_t vertex_count, uint64_t matrix[vertex_count][vertex_count]) { - srand(time(NULL)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (column_index == row_index) { - matrix[row_index][column_index] = 0; - } else { - matrix[row_index][column_index] = rand() % 2; - } - } - } -} - -void calculate_distance_matrix(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], uint64_t distance_matrix[vertex_count][vertex_count]) { - uint64_t power_matrix[vertex_count][vertex_count]; - uint64_t temp_power_matrix[vertex_count][vertex_count]; - memcpy(power_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (row_index == column_index) { - distance_matrix[row_index][column_index] = 0; - } else if (adjacency_matrix[row_index][column_index] == 1) { - distance_matrix[row_index][column_index] = 1; - } else { - distance_matrix[row_index][column_index] = UINT64_MAX; - } - } - } - - for(uint64_t k = 2; k <= vertex_count; k++) { - memcpy(temp_power_matrix, power_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - gemm_basic(vertex_count, vertex_count, adjacency_matrix, vertex_count, vertex_count, temp_power_matrix, power_matrix); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (power_matrix[row_index][column_index] != 0 && distance_matrix[row_index][column_index] == UINT64_MAX) { - distance_matrix[row_index][column_index] = k; - } - } - } - } -} - -int get_eccentricities(const uint64_t vertex_count, const uint64_t distance_matrix[vertex_count][vertex_count], uint64_t eccentricities[vertex_count]) { - uint64_t eccentricity; - - // set all eccentricities to infinity in case this is a disconnected graph - for (uint64_t index = 0; index < vertex_count; index++) { - eccentricities[index] = UINT64_MAX; - } - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - eccentricity = 0; - - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (distance_matrix[row_index][column_index] > eccentricity) { - eccentricity = distance_matrix[row_index][column_index]; - } - } - // in case of a disconnected graph - if (eccentricity == 0) { - return 1; - } - eccentricities[row_index] = eccentricity; - } - - return 0; -} - -uint64_t get_radius(const uint64_t vertex_count, const uint64_t eccentricities[vertex_count]) { - uint64_t radius = UINT64_MAX; - - for (uint64_t index = 0; index < vertex_count; index++) { - if (eccentricities[index] < radius) { - radius = eccentricities[index]; - } - } - - return radius; -} - -uint64_t get_diameter(const uint64_t vertex_count, const uint64_t eccentricities[vertex_count]) { - uint64_t diamter = 0; - - for (uint64_t index = 0; index < vertex_count; index++) { - if (eccentricities[index] > diamter) { - diamter = eccentricities[index]; - } - } - - return diamter; -} - -void get_centre(const uint64_t vertex_count, const uint64_t eccentricities[vertex_count], const uint64_t radius, uint64_t centre[vertex_count]) { - memset(centre, 0, vertex_count * sizeof(uint64_t)); - - for (uint64_t index = 0; index < vertex_count; index++) { - if (eccentricities[index] == radius) { - centre[index] = 1; - } - } -} - -void calculate_path_matrix(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], uint64_t path_matrix[vertex_count][vertex_count]) { - uint64_t power_matrix[vertex_count][vertex_count]; - uint64_t temp_power_matrix[vertex_count][vertex_count]; - memcpy(power_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (row_index == column_index || adjacency_matrix[row_index][column_index] == 1) { - path_matrix[row_index][column_index] = 1; - } else { - path_matrix[row_index][column_index] = 0; - } - } - } - - for(uint64_t k = 2; k <= vertex_count; k++) { - memcpy(temp_power_matrix, power_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - gemm_basic(vertex_count, vertex_count, adjacency_matrix, vertex_count, vertex_count, temp_power_matrix, power_matrix); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (power_matrix[row_index][column_index] != 0) { - path_matrix[row_index][column_index] = 1; - } - } - } - } -} - -void find_components_basic(const uint64_t vertex_count, const uint64_t path_matrix[vertex_count][vertex_count], uint64_t components[vertex_count][vertex_count]) { - uint64_t component[vertex_count]; - int contains_component; - - memset(components, 0, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - memset(component, 0, vertex_count * sizeof(uint64_t)); - contains_component = 0; - - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (path_matrix[row_index][column_index] == 1) { - component[column_index] = column_index + 1; - } - } - - for (uint64_t index = 0; index < vertex_count; index++) { - if (memcmp(components[index], component, vertex_count * sizeof(uint64_t)) == 0) { - contains_component = 1; - } - } - - if (!contains_component) { - for (uint64_t index = 0; index < vertex_count; index++) { - components[row_index][index] = component[index]; - } - } - } -} - -void dfs(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], const uint64_t vertex, uint64_t visited[vertex_count]) { - visited[vertex] = 1; - - for (uint64_t neighbor_vertex = 0; neighbor_vertex < vertex_count; neighbor_vertex++) { - if (adjacency_matrix[vertex][neighbor_vertex] != 1) { - continue; - } - if (visited[neighbor_vertex]) { - continue; - } - dfs(vertex_count, adjacency_matrix, neighbor_vertex, visited); - } -} - -void find_components_dfs(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], uint64_t components[vertex_count][vertex_count]) { - uint64_t component[vertex_count]; - int contains_component = 0; - - memset(components, 0, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { - memset(component, 0, vertex_count * sizeof(uint64_t)); - contains_component = 0; - - dfs(vertex_count, adjacency_matrix, vertex, component); - - for (uint64_t index = 0; index < vertex_count; index++) { - if (memcmp(components[index], component, vertex_count * sizeof(uint64_t)) == 0) { - contains_component = 1; - } - } - - if (!contains_component) { - for (uint64_t index = 0; index < vertex_count; index++) { - components[vertex][index] = component[index]; - } - } - } -} - -uint64_t amount_of_components(const uint64_t vertex_count, const uint64_t components[vertex_count][vertex_count]) { - uint64_t amount_of_components = 0; - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (components[row_index][column_index] != 0) { - amount_of_components++; - break; - } - } - } - - return amount_of_components; -} - -int contains_bridge(const uint64_t vertex_count, const uint64_t bridges[vertex_count][2], const uint64_t bridge[2]) { - for (uint64_t index = 0; index < vertex_count; index++) { - if (memcmp(bridges[index], bridge, 2 * sizeof(uint64_t)) == 0) { - return 1; - } - } - - return 0; -} - -void find_bridges_basic(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t bridges[vertex_count][2]) { - uint64_t path_matrix[vertex_count][vertex_count]; - uint64_t temp_adjacency_matrix[vertex_count][vertex_count]; - uint64_t temp_components[vertex_count][vertex_count]; - uint64_t bridge[2]; - - memset(bridges, 0, vertex_count * 2 * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (row_index == column_index) { - continue; - } - - if (column_index < row_index) { - bridge[0] = column_index + 1; - bridge[1] = row_index + 1; - } else { - bridge[0] = row_index + 1; - bridge[1] = column_index + 1; - } - - memcpy(temp_adjacency_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - temp_adjacency_matrix[row_index][column_index] = 0; - temp_adjacency_matrix[column_index][row_index] = 0; - - calculate_path_matrix(vertex_count, temp_adjacency_matrix, path_matrix); - find_components_basic(vertex_count, path_matrix, temp_components); - - if (amount_of_components(vertex_count, temp_components) > amount_of_components(vertex_count, components) && !contains_bridge(vertex_count, bridges, bridge)) { - bridges[row_index][0] = bridge[0]; - bridges[row_index][1] = bridge[1]; - } - } - } - print_matrix(vertex_count, 2, bridges); -} - -void find_bridges_dfs_v1(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t bridges[vertex_count][2]) { - uint64_t temp_adjacency_matrix[vertex_count][vertex_count]; - uint64_t temp_components[vertex_count][vertex_count]; - uint64_t bridge[2]; - - memset(bridges, 0, vertex_count * 2 * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (row_index == column_index) { - continue; - } - - if (column_index < row_index) { - bridge[0] = column_index + 1; - bridge[1] = row_index + 1; - } else { - bridge[0] = row_index + 1; - bridge[1] = column_index + 1; - } - - memcpy(temp_adjacency_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - temp_adjacency_matrix[row_index][column_index] = 0; - temp_adjacency_matrix[column_index][row_index] = 0; - - find_components_dfs(vertex_count, temp_adjacency_matrix, temp_components); - - if (amount_of_components(vertex_count, temp_components) > amount_of_components(vertex_count, components) && !contains_bridge(vertex_count, bridges, bridge)) { - bridges[row_index][0] = bridge[0]; - bridges[row_index][1] = bridge[1]; - } - } - } -} - -void dfs_bridges(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], const uint64_t vertex, const uint64_t parent_vertex, uint64_t visited[vertex_count], - uint64_t current_time, uint64_t discovery_time[vertex_count], uint64_t lowest_time[vertex_count], uint64_t bridges[vertex_count][2]) { - current_time++; - visited[vertex] = 1; - discovery_time[vertex] = current_time; - lowest_time[vertex] = current_time; - - for (uint64_t neighbor_vertex = 0; neighbor_vertex < vertex_count; neighbor_vertex++) { - if (adjacency_matrix[vertex][neighbor_vertex] != 1) { - continue; - } - if (parent_vertex != neighbor_vertex && visited[neighbor_vertex]) { - if (lowest_time[vertex] > discovery_time[neighbor_vertex]) { - lowest_time[vertex] = discovery_time[neighbor_vertex]; - } - continue; - } - if (visited[neighbor_vertex]) { - continue; - } - - dfs_bridges(vertex_count, adjacency_matrix, neighbor_vertex, vertex, visited, current_time, discovery_time, lowest_time, bridges); - - if (lowest_time[vertex] > lowest_time[neighbor_vertex]) { - lowest_time[vertex] = lowest_time[neighbor_vertex]; - } - if (discovery_time[vertex] < lowest_time[neighbor_vertex]) { - bridges[neighbor_vertex][0] = vertex + 1; - bridges[neighbor_vertex][1] = neighbor_vertex + 1; - } - } -} - -void find_bridges_dfs_v2(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t bridges[vertex_count][2]) { - uint64_t visited[vertex_count]; - uint64_t current_time = 0; - uint64_t discovery_time[vertex_count]; - uint64_t lowest_time[vertex_count]; - - memset(bridges, 0, vertex_count * 2 * sizeof(uint64_t)); - memset(visited, 0, vertex_count * sizeof(uint64_t)); - memset(discovery_time, 0, vertex_count * sizeof(uint64_t)); - memset(lowest_time, 0, vertex_count * sizeof(uint64_t)); - - for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { - if (!visited[vertex]) { - dfs_bridges(vertex_count, adjacency_matrix, vertex, UINT64_MAX, visited, current_time, discovery_time, lowest_time, bridges); - } - } -} - -void find_articulations_basic(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t articulations[vertex_count]) { - uint64_t path_matrix[vertex_count][vertex_count]; - uint64_t temp_adjacency_matrix[vertex_count][vertex_count]; - uint64_t temp_components[vertex_count][vertex_count]; - - memset(articulations, 0, vertex_count * sizeof(uint64_t)); - - for (uint64_t i = 0; i < vertex_count; i++) { - memcpy(temp_adjacency_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - temp_adjacency_matrix[row_index][i] = 0; - temp_adjacency_matrix[i][column_index] = 0; - } - } - - calculate_path_matrix(vertex_count, temp_adjacency_matrix, path_matrix); - find_components_basic(vertex_count, path_matrix, temp_components); - - // the + 1 is needed because I am not removing the vertex, I am just removing all of its edges - // removing all of its edges, means it itself becomes a component, which needs to be accounted for - if (amount_of_components(vertex_count, temp_components) > amount_of_components(vertex_count, components) + 1) { - articulations[i] = i + 1; - } - } -} - -void find_articulations_dfs_v1(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t articulations[vertex_count]) { - uint64_t temp_adjacency_matrix[vertex_count][vertex_count]; - uint64_t temp_components[vertex_count][vertex_count]; - - memset(articulations, 0, vertex_count * sizeof(uint64_t)); - - for (uint64_t i = 0; i < vertex_count; i++) { - memcpy(temp_adjacency_matrix, adjacency_matrix, vertex_count * vertex_count * sizeof(uint64_t)); - - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - temp_adjacency_matrix[row_index][i] = 0; - temp_adjacency_matrix[i][column_index] = 0; - } - } - - find_components_dfs(vertex_count, temp_adjacency_matrix, temp_components); - - // the + 1 is needed because I am not removing the vertex, I am just removing all of its edges - // removing all of its edges, means it itself becomes a component, which needs to be accounted for - if (amount_of_components(vertex_count, temp_components) > amount_of_components(vertex_count, components) + 1) { - articulations[i] = i + 1; - } - } -} - -void dfs_articulations(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], const uint64_t vertex, const uint64_t parent_vertex, - uint64_t visited[vertex_count], uint64_t current_time, uint64_t discovery_time[vertex_count], uint64_t lowest_time[vertex_count], - uint64_t articulations[vertex_count]) { - current_time++; - visited[vertex] = 1; - discovery_time[vertex] = current_time; - lowest_time[vertex] = current_time; - uint64_t child_count = 0; - uint64_t is_articulation = 0; - - for (uint64_t neighbor_vertex = 0; neighbor_vertex < vertex_count; neighbor_vertex++) { - if (adjacency_matrix[vertex][neighbor_vertex] != 1) { - continue; - } - if (visited[neighbor_vertex]) { - if (lowest_time[vertex] > discovery_time[neighbor_vertex]) { - lowest_time[vertex] = discovery_time[neighbor_vertex]; - } - continue; - } - - child_count++; - - dfs_articulations(vertex_count, adjacency_matrix, neighbor_vertex, vertex, visited, current_time, discovery_time, lowest_time, articulations); - - if (lowest_time[vertex] > lowest_time[neighbor_vertex]) { - lowest_time[vertex] = lowest_time[neighbor_vertex]; - } - - if (parent_vertex != UINT64_MAX && discovery_time[vertex] <= lowest_time[neighbor_vertex]) { - is_articulation = 1; - } - } - if (parent_vertex == UINT64_MAX && child_count > 1) { - is_articulation = 1; - } - if (is_articulation) { - articulations[vertex] = vertex + 1; - } -} - -void find_articulations_dfs_v2(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], uint64_t articulations[vertex_count]) { - uint64_t visited[vertex_count]; - uint64_t current_time = 0; - uint64_t discovery_time[vertex_count]; - uint64_t lowest_time[vertex_count]; - - memset(articulations, 0, vertex_count * sizeof(uint64_t)); - memset(visited, 0, vertex_count * sizeof(uint64_t)); - memset(discovery_time, 0, vertex_count * sizeof(uint64_t)); - memset(lowest_time, 0, vertex_count * sizeof(uint64_t)); - - for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { - if (!visited[vertex]) { - dfs_articulations(vertex_count, adjacency_matrix, vertex, UINT64_MAX, visited, current_time, discovery_time, lowest_time, articulations); - } - } -} diff --git a/graph.cpp b/graph.cpp new file mode 100644 index 0000000..e2e7629 --- /dev/null +++ b/graph.cpp @@ -0,0 +1,498 @@ +#include "matrix.hpp" +#include +#include +#include +#include +#include +#include +#include + +std::vector> random_adjacency(const uint64_t vertex_count) { + std::vector> adjacency_matrix(vertex_count, std::vector(vertex_count, 0)); + srand(time(NULL)); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (column_index != row_index) { + adjacency_matrix[row_index][column_index] = rand() % 2; + } + } + } + + return adjacency_matrix; +} + +std::vector> calculate_distance_matrix(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> distance_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> power_matrix(vertex_count, std::vector(vertex_count, 0)); + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), power_matrix.begin()); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (row_index == column_index) { + continue; + } else if (adjacency_matrix[row_index][column_index] == 1) { + distance_matrix[row_index][column_index] = 1; + } else { + distance_matrix[row_index][column_index] = UINT64_MAX; + } + } + } + + for(uint64_t k = 2; k <= vertex_count; k++) { + power_matrix = gemm_basic(adjacency_matrix, power_matrix); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (power_matrix[row_index][column_index] != 0 && distance_matrix[row_index][column_index] == UINT64_MAX) { + distance_matrix[row_index][column_index] = k; + } + } + } + } + + return distance_matrix; +} + +std::vector get_eccentricities(const std::vector>& distance_matrix) { + uint64_t vertex_count = distance_matrix.size(); + std::vector eccentricities(vertex_count, UINT64_MAX); + uint64_t eccentricity; + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + eccentricity = 0; + + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (distance_matrix[row_index][column_index] > eccentricity) { + eccentricity = distance_matrix[row_index][column_index]; + } + } + + if (eccentricity == 0) { + break; + } + eccentricities[row_index] = eccentricity; + } + + return eccentricities; +} + +uint64_t get_radius(const std::vector& eccentricities) { + uint64_t radius = UINT64_MAX; + + for (uint64_t index = 0; index < eccentricities.size(); index++) { + if (eccentricities[index] < radius) { + radius = eccentricities[index]; + } + } + + return radius; +} + +uint64_t get_diameter(const std::vector& eccentricities) { + uint64_t diamter = 0; + + for (uint64_t index = 0; index < eccentricities.size(); index++) { + if (eccentricities[index] > diamter) { + diamter = eccentricities[index]; + } + } + + return diamter; +} + +std::vector get_centre(const std::vector& eccentricities) { + std::vector centre; + uint64_t radius = get_radius(eccentricities); + + for (uint64_t index = 0; index < eccentricities.size(); index++) { + if (eccentricities[index] == radius) { + centre.push_back(index + 1); + } + } + + centre.shrink_to_fit(); + return centre; +} + +std::vector> calculate_path_matrix(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> path_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> power_matrix(vertex_count, std::vector(vertex_count, 0)); + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), power_matrix.begin()); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (row_index == column_index || adjacency_matrix[row_index][column_index] == 1) { + path_matrix[row_index][column_index] = 1; + } + } + } + + for(uint64_t k = 2; k <= vertex_count; k++) { + power_matrix = gemm_basic(adjacency_matrix, power_matrix); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (power_matrix[row_index][column_index] != 0) { + path_matrix[row_index][column_index] = 1; + } + } + } + } + + return path_matrix; +} + +std::vector> find_components_basic(const std::vector>& path_matrix) { + uint64_t vertex_count = path_matrix.size(); + std::vector> components; + std::vector component; + components.reserve(0); + component.reserve(vertex_count); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + component.clear(); + + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (path_matrix[row_index][column_index] == 1) { + component.push_back(column_index + 1); + } + } + + component.shrink_to_fit(); + std::sort(component.begin(), component.end()); + + auto iterator = find(components.begin(), components.end(), component); + + if (iterator == components.end()) { + components.push_back(component); + } + } + + components.shrink_to_fit(); + return components; +} + +void dfs(const std::vector>& adjacency_matrix, const uint64_t vertex, std::vector& visited) { + visited[vertex] = true; + + for (uint64_t neighbor_vertex = 0; neighbor_vertex < adjacency_matrix.size(); neighbor_vertex++) { + if (adjacency_matrix[vertex][neighbor_vertex] != 1) { + continue; + } + if (visited[neighbor_vertex]) { + continue; + } + dfs(adjacency_matrix, neighbor_vertex, visited); + } +} + +std::vector> find_components_dfs(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> components; + std::vector component; + std::vector visited(vertex_count, false); + components.reserve(0); + component.reserve(vertex_count); + + for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { + component.clear(); + + dfs(adjacency_matrix, vertex, visited); + + for (uint64_t index = 0; index < vertex_count; index++) { + if (visited[index]) { + component.push_back(index + 1); + } + } + + component.shrink_to_fit(); + std::sort(component.begin(), component.end()); + + auto iterator = find(components.begin(), components.end(), component); + + if (iterator == components.end()) { + components.push_back(component); + } + } + + components.shrink_to_fit(); + return components; +} + +std::vector> find_bridges_basic(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> path_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> temp_adjacency_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> components = find_components_basic(path_matrix); + std::vector> temp_components; + std::vector> bridges; + std::vector bridge(2, 0); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (row_index == column_index) { + continue; + } + + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), temp_adjacency_matrix.begin()); + + temp_adjacency_matrix[row_index][column_index] = 0; + temp_adjacency_matrix[column_index][row_index] = 0; + + path_matrix = calculate_path_matrix(temp_adjacency_matrix); + temp_components = find_components_basic(path_matrix); + + if (temp_components.size() <= components.size()) { + continue; + } + + if (column_index < row_index) { + bridge[0] = column_index + 1; + bridge[1] = row_index + 1; + } else { + bridge[0] = row_index + 1; + bridge[1] = column_index + 1; + } + + auto iterator = find(bridges.begin(), bridges.end(), bridge); + + if (iterator == bridges.end()) { + bridges.push_back(bridge); + } + } + } + + bridges.shrink_to_fit(); + return bridges; +} + +std::vector> find_bridges_dfs_v1(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> temp_adjacency_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> components = find_components_dfs(adjacency_matrix); + std::vector> temp_components; + std::vector> bridges; + std::vector bridge(2, 0); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + if (row_index == column_index) { + continue; + } + + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), temp_adjacency_matrix.begin()); + + temp_adjacency_matrix[row_index][column_index] = 0; + temp_adjacency_matrix[column_index][row_index] = 0; + + temp_components = find_components_dfs(temp_adjacency_matrix); + + if (temp_components.size() <= components.size()) { + continue; + } + + if (column_index < row_index) { + bridge[0] = column_index + 1; + bridge[1] = row_index + 1; + } else { + bridge[0] = row_index + 1; + bridge[1] = column_index + 1; + } + + auto iterator = find(bridges.begin(), bridges.end(), bridge); + + if (iterator == bridges.end()) { + bridges.push_back(bridge); + } + } + } + + bridges.shrink_to_fit(); + return bridges; +} + +void dfs_bridges(const std::vector>& adjacency_matrix, const uint64_t vertex, const uint64_t parent_vertex, std::vector& visited, + uint64_t current_time, std::vector& discovery_time, std::vector& lowest_time, std::vector>& bridges) { + current_time++; + visited[vertex] = true; + discovery_time[vertex] = current_time; + lowest_time[vertex] = current_time; + std::vector bridge(2, 0); + + for (uint64_t neighbor_vertex = 0; neighbor_vertex < adjacency_matrix.size(); neighbor_vertex++) { + if (adjacency_matrix[vertex][neighbor_vertex] != 1) { + continue; + } + if (parent_vertex != neighbor_vertex && visited[neighbor_vertex]) { + if (lowest_time[vertex] > discovery_time[neighbor_vertex]) { + lowest_time[vertex] = discovery_time[neighbor_vertex]; + } + continue; + } + if (visited[neighbor_vertex]) { + continue; + } + + dfs_bridges(adjacency_matrix, neighbor_vertex, vertex, visited, current_time, discovery_time, lowest_time, bridges); + + if (lowest_time[vertex] > lowest_time[neighbor_vertex]) { + lowest_time[vertex] = lowest_time[neighbor_vertex]; + } + if (discovery_time[vertex] >= lowest_time[neighbor_vertex]) { + continue; + } + bridge[0] = vertex + 1; + bridge[1] = neighbor_vertex + 1; + + auto iterator = find(bridges.begin(), bridges.end(), bridge); + + if (iterator == bridges.end()) { + bridges.push_back(bridge); + } + } +} + +std::vector> find_bridges_dfs_v2(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector visited(vertex_count, false); + uint64_t current_time = 0; + std::vector discovery_time(vertex_count, 0); + std::vector lowest_time(vertex_count, 0); + std::vector> bridges; + + for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { + if (!visited[vertex]) { + dfs_bridges(adjacency_matrix, vertex, UINT64_MAX, visited, current_time, discovery_time, lowest_time, bridges); + } + } + + bridges.shrink_to_fit(); + return bridges; +} + +std::vector find_articulations_basic(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> path_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> temp_adjacency_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> components = find_components_basic(path_matrix); + std::vector> temp_components; + std::vector articulations; + + for (uint64_t i = 0; i < vertex_count; i++) { + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), temp_adjacency_matrix.begin()); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + temp_adjacency_matrix[row_index][i] = 0; + temp_adjacency_matrix[i][column_index] = 0; + } + } + + path_matrix = calculate_path_matrix(temp_adjacency_matrix); + temp_components = find_components_basic(path_matrix); + + // the + 1 is needed because I am not removing the vertex, I am just removing all of its edges + // removing all of its edges, means it itself becomes a component, which needs to be accounted for + if (temp_components.size() > components.size() + 1) { + articulations.push_back(i + 1); + } + } + + articulations.shrink_to_fit(); + std::sort(articulations.begin(), articulations.end()); + return articulations; +} + +std::vector find_articulations_dfs_v1(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector> path_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> temp_adjacency_matrix(vertex_count, std::vector(vertex_count, 0)); + std::vector> components = find_components_dfs(adjacency_matrix); + std::vector> temp_components; + std::vector articulations; + + for (uint64_t i = 0; i < vertex_count; i++) { + std::copy(adjacency_matrix.begin(), adjacency_matrix.end(), temp_adjacency_matrix.begin()); + + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { + temp_adjacency_matrix[row_index][i] = 0; + temp_adjacency_matrix[i][column_index] = 0; + } + } + + temp_components = find_components_dfs(temp_adjacency_matrix); + + // the + 1 is needed because I am not removing the vertex, I am just removing all of its edges + // removing all of its edges, means it itself becomes a component, which needs to be accounted for + if (temp_components.size() > components.size() + 1) { + articulations.push_back(i + 1); + } + } + + articulations.shrink_to_fit(); + std::sort(articulations.begin(), articulations.end()); + return articulations; +} + +void dfs_articulations(const std::vector>& adjacency_matrix, const uint64_t vertex, const uint64_t parent_vertex, std::vector& visited, + uint64_t current_time, std::vector& discovery_time, std::vector& lowest_time, std::vector& articulations) { + current_time++; + visited[vertex] = true; + discovery_time[vertex] = current_time; + lowest_time[vertex] = current_time; + uint64_t child_count = 0; + bool is_articulation = false; + + for (uint64_t neighbor_vertex = 0; neighbor_vertex < adjacency_matrix.size(); neighbor_vertex++) { + if (adjacency_matrix[vertex][neighbor_vertex] != 1) { + continue; + } + if (visited[neighbor_vertex]) { + if (lowest_time[vertex] > discovery_time[neighbor_vertex]) { + lowest_time[vertex] = discovery_time[neighbor_vertex]; + } + continue; + } + + child_count++; + + dfs_articulations(adjacency_matrix, neighbor_vertex, vertex, visited, current_time, discovery_time, lowest_time, articulations); + + if (lowest_time[vertex] > lowest_time[neighbor_vertex]) { + lowest_time[vertex] = lowest_time[neighbor_vertex]; + } + + if (parent_vertex != UINT64_MAX && discovery_time[vertex] <= lowest_time[neighbor_vertex]) { + is_articulation = true; + } + } + if (parent_vertex == UINT64_MAX && child_count > 1) { + is_articulation = true; + } + if (is_articulation) { + articulations.push_back(vertex + 1); + } +} + +std::vector find_articulations_dfs_v2(const std::vector>& adjacency_matrix) { + uint64_t vertex_count = adjacency_matrix.size(); + std::vector visited(vertex_count, false); + uint64_t current_time = 0; + std::vector discovery_time(vertex_count, 0); + std::vector lowest_time(vertex_count, 0); + std::vector articulations; + + for (uint64_t vertex = 0; vertex < vertex_count; vertex++) { + if (!visited[vertex]) { + dfs_articulations(adjacency_matrix, vertex, UINT64_MAX, visited, current_time, discovery_time, lowest_time, articulations); + } + } + + articulations.shrink_to_fit(); + std::sort(articulations.begin(), articulations.end()); + return articulations; +} diff --git a/graph.h b/graph.h deleted file mode 100644 index a88aa53..0000000 --- a/graph.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef GRAPH_H -#define GRAPH_H - -#include - -void random_adjacency(const uint64_t vertex_count, - uint64_t matrix[vertex_count][vertex_count]); - -void calculate_distance_matrix(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - uint64_t distance_matrix[vertex_count][vertex_count]); - -// returns 1 if it is a disconnected graph and sets all values in eccentricities to UINT64_MAX -int get_eccentricities(const uint64_t vertex_count, - const uint64_t distance_matrix[vertex_count][vertex_count], - uint64_t eccentricities[vertex_count]); - -uint64_t get_radius(const uint64_t vertex_count, - const uint64_t eccentricities[vertex_count]); - -uint64_t get_diameter(const uint64_t vertex_count, - const uint64_t eccentricities[vertex_count]); - -void get_centre(const uint64_t vertex_count, - const uint64_t eccentricities[vertex_count], - const uint64_t radius, - uint64_t centre[vertex_count]); - -void calculate_path_matrix(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - uint64_t path_matrix[vertex_count][vertex_count]); - -void find_components_basic(const uint64_t vertex_count, - const uint64_t path_matrix[vertex_count][vertex_count], - uint64_t components[vertex_count][vertex_count]); - -void find_components_dfs(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - uint64_t components[vertex_count][vertex_count]); - -void find_bridges_basic(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t bridges[vertex_count][2]); - -void find_bridges_dfs_v1(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t bridges[vertex_count][2]); - -void find_bridges_dfs_v2(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t bridges[vertex_count][2]); - -void find_articulations_basic(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t articulations[vertex_count]); - -void find_articulations_dfs_v1(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t articulations[vertex_count]); - -void find_articulations_dfs_v2(const uint64_t vertex_count, - const uint64_t adjacency_matrix[vertex_count][vertex_count], - const uint64_t components[vertex_count][vertex_count], - uint64_t articulations[vertex_count]); - -#endif diff --git a/graph.hpp b/graph.hpp new file mode 100644 index 0000000..a618fa2 --- /dev/null +++ b/graph.hpp @@ -0,0 +1,33 @@ +#pragma once +#include +#include + +std::vector> random_adjacency(const uint64_t vertex_count); + +std::vector> calculate_distance_matrix(const std::vector>& adjacency_matrix); + +std::vector get_eccentricities(const std::vector>& distance_matrix); + +uint64_t get_radius(const std::vector& eccentricities); + +uint64_t get_diameter(const std::vector& eccentricities); + +std::vector get_centre(const std::vector& eccentricities); + +std::vector> calculate_path_matrix(const std::vector>& adjacency_matrix); + +std::vector> find_components_basic(const std::vector>& path_matrix); + +std::vector> find_components_dfs(const std::vector>& adjacency_matrix); + +std::vector> find_bridges_basic(const std::vector>& adjacency_matrix); + +std::vector> find_bridges_dfs_v1(const std::vector>& adjacency_matrix); + +std::vector> find_bridges_dfs_v2(const std::vector>& adjacency_matrix); + +std::vector find_articulations_basic(const std::vector>& adjacency_matrix); + +std::vector find_articulations_dfs_v1(const std::vector>& adjacency_matrix); + +std::vector find_articulations_dfs_v2(const std::vector>& adjacency_matrix); diff --git a/main.c b/main.c deleted file mode 100644 index 0c0f8f9..0000000 --- a/main.c +++ /dev/null @@ -1,280 +0,0 @@ -#include "graph.h" -#include "matrix.h" -#include -#include -#include -#include -#include - -void benchmark_gemm() { - const uint64_t vertex_count1 = 1024; - uint64_t (*matrix1)[vertex_count1] = malloc(vertex_count1 * vertex_count1 * sizeof(uint64_t)); - - const uint64_t vertex_count2 = 1024; - uint64_t (*matrix2)[vertex_count2] = malloc(vertex_count2 * vertex_count2 * sizeof(uint64_t)); - - uint64_t (*new_matrix)[vertex_count2] = malloc(vertex_count1 * vertex_count2 * sizeof(uint64_t)); - - double elapsed_time = 0.0; - const uint64_t iterations = 10; - clock_t start_time; - - for (uint64_t i = 0; i < iterations; i++) { - random_adjacency(vertex_count1, matrix1); - random_adjacency(vertex_count2, matrix2); - - start_time = clock(); - - gemm_basic(vertex_count1, vertex_count1, matrix1, - vertex_count2, vertex_count2, matrix2, - new_matrix); - - elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; - } - - printf("%lu iterations of gemm_basic took roughly %f seconds\n", iterations, elapsed_time); - printf("An iteration of gemm_basic took on average roughly %f seconds\n", elapsed_time/iterations); - - free(matrix1); - free(matrix2); - free(new_matrix); -} - -void benchmark_find_components() { - const uint64_t vertex_count = 100; - uint64_t adjacency_matrix[vertex_count][vertex_count]; - uint64_t components[vertex_count][vertex_count]; - uint64_t path_matrix[vertex_count][vertex_count]; - - double elapsed_time = 0.0; - const uint64_t iterations = 100; - clock_t start_time; - - for (uint64_t i = 0; i < iterations; i++) { - random_adjacency(vertex_count, adjacency_matrix); - - start_time = clock(); - - calculate_path_matrix(vertex_count, adjacency_matrix, path_matrix); - find_components_basic(vertex_count, path_matrix, components); - - elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; - } - - printf("%lu iterations of find_components_basic took roughly %f seconds\n", iterations, elapsed_time); - printf("An iteration of find_components_basic took on average roughly %f seconds\n", elapsed_time/iterations); - - elapsed_time = 0.0; - - for (uint64_t i = 0; i < iterations; i++) { - random_adjacency(vertex_count, adjacency_matrix); - - start_time = clock(); - - find_components_dfs(vertex_count, adjacency_matrix, components); - - elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; - } - - printf("%lu iterations of find_components_dfs took roughly %f seconds\n", iterations, elapsed_time); - printf("An iteration of find_components_dfs took on average roughly %f seconds\n", elapsed_time/iterations); -} - -void test_with_basic() { - const uint64_t vertex_count = 24; - uint64_t adjacency_matrix[vertex_count][vertex_count]; - uint64_t distance_matrix[vertex_count][vertex_count]; - uint64_t path_matrix[vertex_count][vertex_count]; - uint64_t eccentricities[vertex_count]; - uint64_t radius, diameter, centre[vertex_count]; - uint64_t components[vertex_count][vertex_count]; - uint64_t bridges[vertex_count][2]; - uint64_t articulations[vertex_count]; - - if (read_csv("csv/24n.csv", vertex_count, vertex_count, adjacency_matrix) == 1) { - return; - } - - calculate_distance_matrix(vertex_count, adjacency_matrix, distance_matrix); - get_eccentricities(vertex_count, distance_matrix, eccentricities); - radius = get_radius(vertex_count, eccentricities); - diameter = get_diameter(vertex_count, eccentricities); - get_centre(vertex_count, eccentricities, radius, centre); - calculate_path_matrix(vertex_count, adjacency_matrix, path_matrix); - find_components_basic(vertex_count, path_matrix, components); - find_bridges_basic(vertex_count, adjacency_matrix, components, bridges); - find_articulations_basic(vertex_count, adjacency_matrix, components, articulations); - - puts("adjacency_matrix:"); - print_matrix(vertex_count, vertex_count, adjacency_matrix); - - puts("\ndistance_matrix:"); - print_matrix(vertex_count, vertex_count, distance_matrix); - - puts("\neccentricities:"); - for (uint64_t index = 0; index < vertex_count; index++) { - printf("\tVertex %lu: %lu\n", index + 1, eccentricities[index]); - } - - printf("\nradius: %lu", radius); - printf("\ndiameter: %lu", diameter); - puts("\ncentre:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (centre[index] == 1) { - printf("\tVertex %lu\n", index + 1); - } - } - - puts("\npath_matrix:"); - print_matrix(vertex_count, vertex_count, path_matrix); - - puts("\ncomponents:"); - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - int empty = 1; - - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (components[row_index][column_index] != 0) { - empty = 0; - } - } - - if (empty) { - continue; - } - - printf("\tComponent %lu: {", row_index + 1); - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (components[row_index][column_index] != 0) { - printf("%lu, ", components[row_index][column_index]); - } - } - puts("}"); - } - - puts("\nbridges:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (bridges[index][0] != 0) { - printf("\tBridge %lu: {%lu, %lu}\n", index + 1, bridges[index][0], bridges[index][1]); - } - } - - puts("\narticulations:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (articulations[index] != 0) { - printf("\tVertex %lu\n", articulations[index]); - } - } -} - -void test_with_dfs() { - const uint64_t vertex_count = 24; - uint64_t adjacency_matrix[vertex_count][vertex_count]; - uint64_t distance_matrix[vertex_count][vertex_count]; - uint64_t eccentricities[vertex_count]; - uint64_t radius, diameter; - uint64_t centre[vertex_count]; - uint64_t components[vertex_count][vertex_count]; - uint64_t bridges[vertex_count][2]; - uint64_t articulations[vertex_count]; - - if (read_csv("csv/24n.csv", vertex_count, vertex_count, adjacency_matrix) == 1) { - return; - } - - /* - const uint64_t vertex_count = 1500; - uint64_t (*adjacency_matrix)[vertex_count] = malloc(vertex_count * vertex_count * sizeof(uint64_t)); - uint64_t (*distance_matrix)[vertex_count] = malloc(vertex_count * vertex_count * sizeof(uint64_t)); - uint64_t *eccentricities = malloc(vertex_count * sizeof(uint64_t)); - uint64_t radius, diameter; - uint64_t *centre = malloc(vertex_count * sizeof(uint64_t)); - uint64_t (*components)[vertex_count] = malloc(vertex_count * vertex_count * sizeof(uint64_t)); - uint64_t (*bridges)[vertex_count] = malloc(vertex_count * 2 * sizeof(uint64_t)); - uint64_t *articulations = malloc(vertex_count * sizeof(uint64_t)); - - random_adjacency(vertex_count, adjacency_matrix); - */ - - calculate_distance_matrix(vertex_count, adjacency_matrix, distance_matrix); - get_eccentricities(vertex_count, distance_matrix, eccentricities); - radius = get_radius(vertex_count, eccentricities); - diameter = get_diameter(vertex_count, eccentricities); - get_centre(vertex_count, eccentricities, radius, centre); - find_components_dfs(vertex_count, adjacency_matrix, components); - find_bridges_dfs_v2(vertex_count, adjacency_matrix, components, bridges); - find_articulations_dfs_v2(vertex_count, adjacency_matrix, components, articulations); - - puts("\nadjacency_matrix:"); - print_matrix(vertex_count, vertex_count, adjacency_matrix); - - puts("\ndistance_matrix:"); - print_matrix(vertex_count, vertex_count, distance_matrix); - - puts("\neccentricities:"); - for (uint64_t index = 0; index < vertex_count; index++) { - printf("\tVertex %lu: %lu\n", index + 1, eccentricities[index]); - } - - printf("\nradius: %lu", radius); - printf("\ndiameter: %lu", diameter); - puts("\ncentre:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (centre[index] == 1) { - printf("\tVertex %lu\n", index + 1); - } - } - - puts("\ncomponents:"); - for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { - int empty = 1; - - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (components[row_index][column_index] != 0) { - empty = 0; - } - } - - if (empty) { - continue; - } - - printf("\tComponent %lu: {", row_index + 1); - for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { - if (components[row_index][column_index] != 0) { - printf("%lu, ", column_index + 1); - } - } - puts("}"); - } - - uint64_t bridge_number = 1; - puts("\nbridges:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (bridges[index][0] != 0) { - printf("\tBridge %lu: {%lu, %lu}\n", bridge_number, bridges[index][0], bridges[index][1]); - bridge_number++; - } - } - - puts("\narticulations:"); - for (uint64_t index = 0; index < vertex_count; index++) { - if (articulations[index] != 0) { - printf("\tVertex %lu\n", articulations[index]); - } - } - - // free(adjacency_matrix); - // free(distance_matrix); - // free(eccentricities); - // free(centre); - // free(components); - // free(bridges); - // free(articulations); -} - -int main(void) { - // test_with_basic(); - test_with_dfs(); - // benchmark_gemm(); - // benchmark_find_components(); -} diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..4bdeee4 --- /dev/null +++ b/main.cpp @@ -0,0 +1,247 @@ +#include "graph.hpp" +#include "matrix.hpp" +#include +#include +#include +#include +#include +#include + + +void benchmark_gemm() { + const uint64_t vertex_count1 = 1024; + std::vector> matrix1; + + const uint64_t vertex_count2 = 1024; + std::vector> matrix2; + + std::vector> new_matrix; + + const uint64_t iterations = 10; + double elapsed_time = 0.0; + // clock_t start_time; + + for (uint64_t i = 0; i < iterations; i++) { + matrix1 = random_adjacency(vertex_count1); + matrix2 = random_adjacency(vertex_count2); + + // start_time = clock(); + + new_matrix = gemm_basic(matrix1, matrix2); + + // elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; + } + + printf("%lu iterations of gemm_basic took roughly %f seconds\n", iterations, elapsed_time); + printf("An iteration of gemm_basic took on average roughly %f seconds\n", elapsed_time/iterations); +} + + + +void benchmark_find_components() { + const uint64_t vertex_count = 100; + std::vector> adjacency_matrix; + std::vector> components; + std::vector> path_matrix; + + const uint64_t iterations = 100; + double elapsed_time = 0.0; + // clock_t start_time; + + for (uint64_t i = 0; i < iterations; i++) { + adjacency_matrix = random_adjacency(vertex_count); + + // start_time = clock(); + + path_matrix = calculate_path_matrix(adjacency_matrix); + components = find_components_basic(path_matrix); + + // elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; + } + + printf("%lu iterations of find_components_basic took roughly %f seconds\n", iterations, elapsed_time); + printf("An iteration of find_components_basic took on average roughly %f seconds\n", elapsed_time/iterations); + + elapsed_time = 0.0; + + for (uint64_t i = 0; i < iterations; i++) { + adjacency_matrix = random_adjacency(vertex_count); + + // start_time = clock(); + + components = find_components_dfs(adjacency_matrix); + + // elapsed_time += (double)(clock() - start_time) / CLOCKS_PER_SEC; + } + + printf("%lu iterations of find_components_dfs took roughly %f seconds\n", iterations, elapsed_time); + printf("An iteration of find_components_dfs took on average roughly %f seconds\n", elapsed_time/iterations); +} + + +void test_with_basic() { + std::vector> adjacency_matrix = read_csv("csv/24n.csv"); + std::vector> distance_matrix = calculate_distance_matrix(adjacency_matrix); + std::vector> path_matrix = calculate_path_matrix(adjacency_matrix); + std::vector eccentricities = get_eccentricities(distance_matrix); + uint64_t radius = get_radius(eccentricities); + uint64_t diameter = get_diameter(eccentricities); + std::vector centre = get_centre(eccentricities); + std::vector> components = find_components_basic(path_matrix); + std::vector> bridges = find_bridges_basic(adjacency_matrix); + std::vector articulations = find_articulations_basic(adjacency_matrix); + + std::cout << "\nadjacency_matrix:\n"; + print_matrix(adjacency_matrix); + + std::cout << "\ndistance_matrix:\n"; + print_matrix(distance_matrix); + + std::cout << "\neccentricities: {"; + for (uint64_t index = 0; index < eccentricities.size(); index++) { + std::cout << eccentricities[index]; + + if (index < eccentricities.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + + std::cout << "\nradius: " << radius; + std::cout << "\ndiameter: " << diameter; + std::cout << "\ncentre: {"; + for (uint64_t index = 0; index < centre.size(); index++) { + std::cout << centre[index]; + + if (index < centre.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + + std::cout << "\ncomponents:"; + for (uint64_t component_index = 0; component_index < components.size(); component_index++) { + std::cout << "\ncomponent " << component_index + 1 << ": {"; + + for (uint64_t index = 0; index < components[component_index].size(); index++) { + std::cout << components[component_index][index]; + + if (index < components[component_index].size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + } + + std::cout << "\nbridges:"; + for (uint64_t bridge_index = 0; bridge_index < bridges.size(); bridge_index++) { + std::cout << "\nbridge " << bridge_index + 1 << ": {"; + + for (uint64_t index = 0; index < bridges[bridge_index].size(); index++) { + std::cout << bridges[bridge_index][index]; + + if (index < bridges[bridge_index].size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + } + + std::cout << "\narticulations: {"; + for (uint64_t index = 0; index < articulations.size(); index++) { + std::cout << articulations[index]; + + if (index < articulations.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}\n"; +} + +void test_with_dfs() { + // const uint64_t vertex_count = 100; + // std::vector> adjacency_matrix = random_adjacency(vertex_count); + std::vector> adjacency_matrix = read_csv("csv/24n.csv"); + std::vector> distance_matrix = calculate_distance_matrix(adjacency_matrix); + std::vector> path_matrix = calculate_path_matrix(adjacency_matrix); + std::vector eccentricities = get_eccentricities(distance_matrix); + uint64_t radius = get_radius(eccentricities); + uint64_t diameter = get_diameter(eccentricities); + std::vector centre = get_centre(eccentricities); + std::vector> components = find_components_dfs(adjacency_matrix); + std::vector> bridges = find_bridges_dfs_v2(adjacency_matrix); + std::vector articulations = find_articulations_dfs_v2(adjacency_matrix); + + std::cout << "\nadjacency_matrix:\n"; + print_matrix(adjacency_matrix); + + std::cout << "\ndistance_matrix:\n"; + print_matrix(distance_matrix); + + std::cout << "\neccentricities: {"; + for (uint64_t index = 0; index < eccentricities.size(); index++) { + std::cout << eccentricities[index]; + + if (index < eccentricities.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + + std::cout << "\nradius: " << radius; + std::cout << "\ndiameter: " << diameter; + std::cout << "\ncentre: {"; + for (uint64_t index = 0; index < centre.size(); index++) { + std::cout << centre[index]; + + if (index < centre.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + + std::cout << "\ncomponents: "; + for (uint64_t component_index = 0; component_index < components.size(); component_index++) { + std::cout << "\n\tcomponent " << component_index + 1 << ": {"; + + for (uint64_t index = 0; index < components[component_index].size(); index++) { + std::cout << components[component_index][index]; + + if (index < components[component_index].size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + } + + std::cout << "\nbridges:"; + for (uint64_t bridge_index = 0; bridge_index < bridges.size(); bridge_index++) { + std::cout << "\n\tbridge " << bridge_index + 1 << ": {"; + + for (uint64_t index = 0; index < bridges[bridge_index].size(); index++) { + std::cout << bridges[bridge_index][index]; + + if (index < bridges[bridge_index].size() - 1) { + std::cout << ", "; + } + } + std::cout << "}"; + } + + std::cout << "\narticulations: {"; + for (uint64_t index = 0; index < articulations.size(); index++) { + std::cout << articulations[index]; + + if (index < articulations.size() - 1) { + std::cout << ", "; + } + } + std::cout << "}\n"; +} + +int main(void) { + // test_with_basic(); + test_with_dfs(); + // benchmark_gemm(); + // benchmark_find_components(); +} diff --git a/matrix.c b/matrix.c deleted file mode 100644 index 3fc459a..0000000 --- a/matrix.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include -#include - -void print_matrix(const uint64_t row_length, const uint64_t column_length, const uint64_t matrix[row_length][column_length]) { - for (uint64_t column_index=0; column_index < column_length; column_index++) { - for (uint64_t row_index=0; row_index < row_length; row_index++) { - printf("%lu ", matrix[row_index][column_index]); - } - puts(""); - } -} - -void gemm_basic(const uint64_t row_length1, const uint64_t column_length1, const uint64_t matrix1[row_length1][column_length1], - const uint64_t row_length2, const uint64_t column_length2, const uint64_t matrix2[row_length2][column_length2], - uint64_t output_matrix[row_length1][column_length2]) { - uint64_t sum; - - for (uint64_t i = 0; i < row_length1; i++) { - for (uint64_t j = 0; j < column_length2; j++) { - sum = 0; - - for (uint64_t k = 0; k < row_length1; k++) { - sum += matrix1[i][k] * matrix2[k][j]; - } - - output_matrix[i][j] = sum; - } - } -} - -int read_csv(const char *file_name, const uint64_t row_length, const uint64_t column_length, uint64_t output_matrix[row_length][column_length]) { - FILE *file_ptr; - uint64_t bufsize = row_length*2+1; // have to account for delimiters - char buffer[bufsize]; - char *value, *file_line; - uint64_t row_index = 0, column_index = 0; - - file_ptr = fopen(file_name, "r"); - if (file_ptr == NULL) { - puts("Unable to open csv"); - return 1; - } - - while ((file_line = fgets(buffer, bufsize, file_ptr)) != NULL) { - // This shit is just needed and I dont know why - file_line[strcspn(file_line, "\n")] = 0; - value = strtok(file_line, ";,"); - - // for some reason there are two NULLs at the end of a line - // and I dont wanna increment the column_index - if (value == NULL) { - continue; - } - - while (value != NULL) { - output_matrix[row_index++][column_index] = strtoul(value, NULL, 0); - value = strtok(NULL, ";,"); - } - - row_index = 0; - column_index++; - } - - fclose(file_ptr); - - return 0; -} diff --git a/matrix.cpp b/matrix.cpp new file mode 100644 index 0000000..eae5414 --- /dev/null +++ b/matrix.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include + +void print_matrix(const std::vector>& matrix) { + for (uint64_t column_index = 0; column_index < matrix[0].size(); column_index++) { + for (uint64_t row_index = 0; row_index < matrix.size(); row_index++) { + std::cout << matrix[row_index][column_index] << " "; + } + std::cout << "\n"; + } +} + +std::vector> gemm_basic(const std::vector>& matrix1, + const std::vector>& matrix2) { + std::vector> output_matrix(matrix1.size(), std::vector(matrix2[0].size(), 0)); + uint64_t sum; + + for (uint64_t i = 0; i < matrix1.size(); i++) { + for (uint64_t j = 0; j < matrix2[0].size(); j++) { + sum = 0; + + for (uint64_t k = 0; k < matrix1.size(); k++) { + sum += matrix1[i][k] * matrix2[k][j]; + } + + output_matrix[i][j] = sum; + } + } + + return output_matrix; +} + +std::vector> read_csv(const std::string file_name) { + std::vector> output_matrix; + std::vector row; + std::string line; + uint64_t column_index = 0; + + std::ifstream input_stream(file_name); + + while (std::getline(input_stream, line)) { + uint64_t vertex_count = (line.length()+1)/2; + output_matrix.resize(vertex_count); + for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { + output_matrix[row_index].push_back(0); + } + + row.clear(); + + std::stringstream ss(line); + std::string token; + char delimiter = ';'; + + while (getline(ss, token, delimiter)) { + row.push_back(strtoul(token.c_str(), NULL, 0)); + } + + for (uint64_t row_index = 0; row_index < row.size(); row_index++) { + output_matrix[row_index][column_index] = row[row_index]; + } + + column_index++; + } + + return output_matrix; +} diff --git a/matrix.h b/matrix.h deleted file mode 100644 index 2666d32..0000000 --- a/matrix.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MATRIX_H -#define MATRIX_H - -#include - -void print_matrix(const uint64_t row_length, - const uint64_t column_length, - const uint64_t matrix[row_length][column_length]); - -/* - First two matrices will be multiplied and - restult will be written to output_matrix. - Matrix size requirements are as specified in the parameters. -*/ -void gemm_basic(const uint64_t row_length1, - const uint64_t column_length1, - const uint64_t matrix1[row_length1][column_length1], - const uint64_t row_length2, - const uint64_t column_length2, - const uint64_t matrix2[row_length2][column_length2], - uint64_t output_matrix[row_length1][column_length2]); - -int read_csv(char *file_name, - uint64_t row_length, - uint64_t column_length, - uint64_t output_matrix[row_length][column_length]); - -#endif diff --git a/matrix.hpp b/matrix.hpp new file mode 100644 index 0000000..91e572e --- /dev/null +++ b/matrix.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include +#include + +void print_matrix(const std::vector>& matrix); + +/* + First two matrices will be multiplied and + restult will be written to output_matrix. +*/ +std::vector> gemm_basic(const std::vector>& matrix1, + const std::vector>& matrix2); + +std::vector> read_csv(const std::string file_name);