#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; continue; } matrix[row_index][column_index] = rand() % 2; } } } void dfs(const uint64_t vertex_count, const uint64_t adjacency_matrix[vertex_count][vertex_count], const uint64_t vertex, int 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 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]) { for (uint64_t index = 0; index < vertex_count; index++) { centre[index] = 0; } 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; } } } } } int contains_component(const uint64_t vertex_count, const uint64_t components[vertex_count][vertex_count], const uint64_t component[vertex_count]) { for (uint64_t index = 0; index < vertex_count; index++) { if (memcmp(components[index], component, sizeof(components[index])) == 0) { return 1; } } return 0; } 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]; for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { components[row_index][column_index] = UINT64_MAX; } } for (uint64_t row_index = 0; row_index < vertex_count; row_index++) { for (uint64_t index = 0; index < vertex_count; index++) { component[index] = UINT64_MAX; } 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; } } if (!contains_component(vertex_count, components, component)) { for (uint64_t column_index = 0; column_index < vertex_count; column_index++) { components[row_index][column_index] = component[column_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] != UINT64_MAX) { 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, sizeof(bridges[index])) == 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]; for (uint64_t index = 0; index < vertex_count; index++) { bridges[index][0] = UINT64_MAX; bridges[index][1] = UINT64_MAX; } 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)) { bridge[0] = UINT64_MAX; bridge[1] = UINT64_MAX; } if (!contains_bridge(vertex_count, bridges, bridge)) { bridges[row_index][0] = bridge[0]; bridges[row_index][1] = bridge[1]; } } } } 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]; for (uint64_t index = 0; index < vertex_count; index++) { articulations[index] = UINT64_MAX; } 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; } } }