implement dfs
This commit is contained in:
parent
cb5561b35b
commit
e5ddece861
296
graph.c
296
graph.c
@ -1,3 +1,4 @@
|
||||
#include "graph.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -12,27 +13,13 @@ void random_adjacency(const uint64_t vertex_count, uint64_t matrix[vertex_count]
|
||||
for (uint64_t column_index = 0; column_index < vertex_count; column_index++) {
|
||||
if (column_index == row_index) {
|
||||
matrix[row_index][column_index] = 0;
|
||||
continue;
|
||||
} else {
|
||||
matrix[row_index][column_index] = rand() % 2;
|
||||
}
|
||||
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];
|
||||
@ -115,9 +102,7 @@ uint64_t get_diameter(const uint64_t vertex_count, const uint64_t eccentricities
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
memset(centre, 0, vertex_count * sizeof(uint64_t));
|
||||
|
||||
for (uint64_t index = 0; index < vertex_count; index++) {
|
||||
if (eccentricities[index] == radius) {
|
||||
@ -155,29 +140,15 @@ void calculate_path_matrix(const uint64_t vertex_count, const uint64_t adjacency
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
@ -185,9 +156,55 @@ void find_components_basic(const uint64_t vertex_count, const uint64_t path_matr
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,7 +215,7 @@ uint64_t amount_of_components(const uint64_t vertex_count, const uint64_t compon
|
||||
|
||||
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) {
|
||||
if (components[row_index][column_index] != 0) {
|
||||
amount_of_components++;
|
||||
break;
|
||||
}
|
||||
@ -210,7 +227,7 @@ uint64_t amount_of_components(const uint64_t vertex_count, const uint64_t compon
|
||||
|
||||
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) {
|
||||
if (memcmp(bridges[index], bridge, 2 * sizeof(uint64_t)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -225,10 +242,7 @@ void find_bridges_basic(const uint64_t vertex_count, const uint64_t adjacency_ma
|
||||
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;
|
||||
}
|
||||
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++) {
|
||||
@ -252,17 +266,102 @@ void find_bridges_basic(const uint64_t vertex_count, const uint64_t adjacency_ma
|
||||
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)) {
|
||||
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],
|
||||
@ -271,9 +370,7 @@ void find_articulations_basic(const uint64_t vertex_count, const uint64_t adjace
|
||||
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;
|
||||
}
|
||||
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));
|
||||
@ -295,3 +392,90 @@ void find_articulations_basic(const uint64_t vertex_count, const uint64_t adjace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
44
graph.h
44
graph.h
@ -6,30 +6,21 @@
|
||||
void random_adjacency(const uint64_t vertex_count,
|
||||
uint64_t matrix[vertex_count][vertex_count]);
|
||||
|
||||
void dfs(const uint64_t vertex_count,
|
||||
const uint64_t adjacency_matrix[vertex_count][vertex_count],
|
||||
const uint64_t vertex,
|
||||
int visited[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]);
|
||||
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 just in case it was on purpose,
|
||||
// all values in eccentricities will be set to UINT64_MAX
|
||||
// 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]);
|
||||
const uint64_t distance_matrix[vertex_count][vertex_count],
|
||||
uint64_t eccentricities[vertex_count]);
|
||||
|
||||
// returns the radius or UINT64_MAX in case of a disconnected graph
|
||||
uint64_t get_radius(const uint64_t vertex_count,
|
||||
const uint64_t eccentricities[vertex_count]);
|
||||
|
||||
// returns the diameter or UINT64_MAX in case of a disconnected graph
|
||||
uint64_t get_diameter(const uint64_t vertex_count,
|
||||
const uint64_t eccentricities[vertex_count]);
|
||||
|
||||
// in case of a disconnected graph, all nodes will be inside centre
|
||||
void get_centre(const uint64_t vertex_count,
|
||||
const uint64_t eccentricities[vertex_count],
|
||||
const uint64_t radius,
|
||||
@ -39,19 +30,42 @@ 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]);
|
||||
|
||||
// please do not use this yet as the output is currently almost unreadable
|
||||
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
|
||||
|
170
main.c
170
main.c
@ -1,11 +1,12 @@
|
||||
#include "graph.h"
|
||||
#include "matrix.h"
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
void benchmark() {
|
||||
void benchmark_gemm() {
|
||||
const uint64_t vertex_count1 = 1024;
|
||||
uint64_t (*matrix1)[vertex_count1] = malloc(vertex_count1 * vertex_count1 * sizeof(uint64_t));
|
||||
|
||||
@ -39,7 +40,47 @@ void benchmark() {
|
||||
free(new_matrix);
|
||||
}
|
||||
|
||||
void test_with_csv() {
|
||||
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];
|
||||
@ -53,6 +94,7 @@ void test_with_csv() {
|
||||
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);
|
||||
@ -91,7 +133,7 @@ void test_with_csv() {
|
||||
int empty = 1;
|
||||
|
||||
for (uint64_t column_index = 0; column_index < vertex_count; column_index++) {
|
||||
if (components[row_index][column_index] != UINT64_MAX) {
|
||||
if (components[row_index][column_index] != 0) {
|
||||
empty = 0;
|
||||
}
|
||||
}
|
||||
@ -102,7 +144,7 @@ void test_with_csv() {
|
||||
|
||||
printf("\tComponent %lu: {", row_index + 1);
|
||||
for (uint64_t column_index = 0; column_index < vertex_count; column_index++) {
|
||||
if (components[row_index][column_index] != UINT64_MAX) {
|
||||
if (components[row_index][column_index] != 0) {
|
||||
printf("%lu, ", components[row_index][column_index]);
|
||||
}
|
||||
}
|
||||
@ -111,44 +153,128 @@ void test_with_csv() {
|
||||
|
||||
puts("\nbridges:");
|
||||
for (uint64_t index = 0; index < vertex_count; index++) {
|
||||
if (bridges[index][0] != UINT64_MAX) {
|
||||
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] != UINT64_MAX) {
|
||||
if (articulations[index] != 0) {
|
||||
printf("\tVertex %lu\n", articulations[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_dfs() {
|
||||
const uint64_t vertex_count = 7;
|
||||
void test_with_dfs() {
|
||||
const uint64_t vertex_count = 24;
|
||||
uint64_t adjacency_matrix[vertex_count][vertex_count];
|
||||
int visited[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/7n.csv", vertex_count, vertex_count, adjacency_matrix) == 1) {
|
||||
if (read_csv("csv/24n.csv", vertex_count, vertex_count, adjacency_matrix) == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint64_t vertex = 0; vertex < vertex_count; vertex++) {
|
||||
for (uint64_t index = 0; index < vertex_count; index++) {
|
||||
visited[index] = 0;
|
||||
}
|
||||
/*
|
||||
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));
|
||||
|
||||
dfs(vertex_count, adjacency_matrix, vertex, visited);
|
||||
random_adjacency(vertex_count, adjacency_matrix);
|
||||
*/
|
||||
|
||||
for (uint64_t index = 0; index < vertex_count; index++) {
|
||||
printf("%d", visited[index]);
|
||||
}
|
||||
printf("\n");
|
||||
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_csv();
|
||||
// test_dfs();
|
||||
// benchmark();
|
||||
// test_with_basic();
|
||||
test_with_dfs();
|
||||
// benchmark_gemm();
|
||||
// benchmark_find_components();
|
||||
}
|
||||
|
8
matrix.c
8
matrix.c
@ -14,13 +14,9 @@ void print_matrix(const uint64_t row_length, const uint64_t column_length, const
|
||||
}
|
||||
}
|
||||
|
||||
int gemm_basic(const uint64_t row_length1, const uint64_t column_length1, const uint64_t matrix1[row_length1][column_length1],
|
||||
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]) {
|
||||
if (row_length1 != column_length2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t sum;
|
||||
|
||||
for (uint64_t i = 0; i < row_length1; i++) {
|
||||
@ -34,8 +30,6 @@ int gemm_basic(const uint64_t row_length1, const uint64_t column_length1, const
|
||||
output_matrix[i][j] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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]) {
|
||||
|
17
matrix.h
17
matrix.h
@ -10,16 +10,15 @@ void print_matrix(const uint64_t row_length,
|
||||
/*
|
||||
First two matrices will be multiplied and
|
||||
restult will be written to output_matrix.
|
||||
Matrix requirements are as specified in the parameters.
|
||||
Function return 0 on success and 1 on failure.
|
||||
Matrix size requirements are as specified in the parameters.
|
||||
*/
|
||||
int 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]);
|
||||
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,
|
||||
|
223
prof_output
Normal file
223
prof_output
Normal file
@ -0,0 +1,223 @@
|
||||
Flat profile:
|
||||
|
||||
Each sample counts as 0.01 seconds.
|
||||
no time accumulated
|
||||
|
||||
% cumulative self self total
|
||||
time seconds seconds calls Ts/call Ts/call name
|
||||
0.00 0.00 0.00 24 0.00 0.00 dfs
|
||||
0.00 0.00 0.00 23 0.00 0.00 gemm_basic
|
||||
0.00 0.00 0.00 2 0.00 0.00 print_matrix
|
||||
0.00 0.00 0.00 1 0.00 0.00 calculate_distance_matrix
|
||||
0.00 0.00 0.00 1 0.00 0.00 dfs_articulations
|
||||
0.00 0.00 0.00 1 0.00 0.00 dfs_bridges
|
||||
0.00 0.00 0.00 1 0.00 0.00 find_articulations_dfs_v2
|
||||
0.00 0.00 0.00 1 0.00 0.00 find_bridges_dfs_v2
|
||||
0.00 0.00 0.00 1 0.00 0.00 find_components_dfs
|
||||
0.00 0.00 0.00 1 0.00 0.00 get_centre
|
||||
0.00 0.00 0.00 1 0.00 0.00 get_diameter
|
||||
0.00 0.00 0.00 1 0.00 0.00 get_eccentricities
|
||||
0.00 0.00 0.00 1 0.00 0.00 get_radius
|
||||
0.00 0.00 0.00 1 0.00 0.00 read_csv
|
||||
0.00 0.00 0.00 1 0.00 0.00 test_with_dfs
|
||||
|
||||
% the percentage of the total running time of the
|
||||
time program used by this function.
|
||||
|
||||
cumulative a running sum of the number of seconds accounted
|
||||
seconds for by this function and those listed above it.
|
||||
|
||||
self the number of seconds accounted for by this
|
||||
seconds function alone. This is the major sort for this
|
||||
listing.
|
||||
|
||||
calls the number of times this function was invoked, if
|
||||
this function is profiled, else blank.
|
||||
|
||||
self the average number of milliseconds spent in this
|
||||
ms/call function per call, if this function is profiled,
|
||||
else blank.
|
||||
|
||||
total the average number of milliseconds spent in this
|
||||
ms/call function and its descendents per call, if this
|
||||
function is profiled, else blank.
|
||||
|
||||
name the name of the function. This is the minor sort
|
||||
for this listing. The index shows the location of
|
||||
the function in the gprof listing. If the index is
|
||||
in parenthesis it shows where it would appear in
|
||||
the gprof listing if it were to be printed.
|
||||
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved.
|
||||
|
||||
Call graph (explanation follows)
|
||||
|
||||
|
||||
granularity: each sample hit covers 2 byte(s) no time propagated
|
||||
|
||||
index % time self children called name
|
||||
552 dfs [1]
|
||||
0.00 0.00 24/24 find_components_dfs [9]
|
||||
[1] 0.0 0.00 0.00 24+552 dfs [1]
|
||||
552 dfs [1]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 23/23 calculate_distance_matrix [4]
|
||||
[2] 0.0 0.00 0.00 23 gemm_basic [2]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 2/2 test_with_dfs [15]
|
||||
[3] 0.0 0.00 0.00 2 print_matrix [3]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[4] 0.0 0.00 0.00 1 calculate_distance_matrix [4]
|
||||
0.00 0.00 23/23 gemm_basic [2]
|
||||
-----------------------------------------------
|
||||
23 dfs_articulations [5]
|
||||
0.00 0.00 1/1 find_articulations_dfs_v2 [7]
|
||||
[5] 0.0 0.00 0.00 1+23 dfs_articulations [5]
|
||||
23 dfs_articulations [5]
|
||||
-----------------------------------------------
|
||||
23 dfs_bridges [6]
|
||||
0.00 0.00 1/1 find_bridges_dfs_v2 [8]
|
||||
[6] 0.0 0.00 0.00 1+23 dfs_bridges [6]
|
||||
23 dfs_bridges [6]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[7] 0.0 0.00 0.00 1 find_articulations_dfs_v2 [7]
|
||||
0.00 0.00 1/1 dfs_articulations [5]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[8] 0.0 0.00 0.00 1 find_bridges_dfs_v2 [8]
|
||||
0.00 0.00 1/1 dfs_bridges [6]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[9] 0.0 0.00 0.00 1 find_components_dfs [9]
|
||||
0.00 0.00 24/24 dfs [1]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[10] 0.0 0.00 0.00 1 get_centre [10]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[11] 0.0 0.00 0.00 1 get_diameter [11]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[12] 0.0 0.00 0.00 1 get_eccentricities [12]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[13] 0.0 0.00 0.00 1 get_radius [13]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 test_with_dfs [15]
|
||||
[14] 0.0 0.00 0.00 1 read_csv [14]
|
||||
-----------------------------------------------
|
||||
0.00 0.00 1/1 main [29]
|
||||
[15] 0.0 0.00 0.00 1 test_with_dfs [15]
|
||||
0.00 0.00 2/2 print_matrix [3]
|
||||
0.00 0.00 1/1 read_csv [14]
|
||||
0.00 0.00 1/1 calculate_distance_matrix [4]
|
||||
0.00 0.00 1/1 get_eccentricities [12]
|
||||
0.00 0.00 1/1 get_radius [13]
|
||||
0.00 0.00 1/1 get_diameter [11]
|
||||
0.00 0.00 1/1 get_centre [10]
|
||||
0.00 0.00 1/1 find_components_dfs [9]
|
||||
0.00 0.00 1/1 find_bridges_dfs_v2 [8]
|
||||
0.00 0.00 1/1 find_articulations_dfs_v2 [7]
|
||||
-----------------------------------------------
|
||||
|
||||
This table describes the call tree of the program, and was sorted by
|
||||
the total amount of time spent in each function and its children.
|
||||
|
||||
Each entry in this table consists of several lines. The line with the
|
||||
index number at the left hand margin lists the current function.
|
||||
The lines above it list the functions that called this function,
|
||||
and the lines below it list the functions this one called.
|
||||
This line lists:
|
||||
index A unique number given to each element of the table.
|
||||
Index numbers are sorted numerically.
|
||||
The index number is printed next to every function name so
|
||||
it is easier to look up where the function is in the table.
|
||||
|
||||
% time This is the percentage of the `total' time that was spent
|
||||
in this function and its children. Note that due to
|
||||
different viewpoints, functions excluded by options, etc,
|
||||
these numbers will NOT add up to 100%.
|
||||
|
||||
self This is the total amount of time spent in this function.
|
||||
|
||||
children This is the total amount of time propagated into this
|
||||
function by its children.
|
||||
|
||||
called This is the number of times the function was called.
|
||||
If the function called itself recursively, the number
|
||||
only includes non-recursive calls, and is followed by
|
||||
a `+' and the number of recursive calls.
|
||||
|
||||
name The name of the current function. The index number is
|
||||
printed after it. If the function is a member of a
|
||||
cycle, the cycle number is printed between the
|
||||
function's name and the index number.
|
||||
|
||||
|
||||
For the function's parents, the fields have the following meanings:
|
||||
|
||||
self This is the amount of time that was propagated directly
|
||||
from the function into this parent.
|
||||
|
||||
children This is the amount of time that was propagated from
|
||||
the function's children into this parent.
|
||||
|
||||
called This is the number of times this parent called the
|
||||
function `/' the total number of times the function
|
||||
was called. Recursive calls to the function are not
|
||||
included in the number after the `/'.
|
||||
|
||||
name This is the name of the parent. The parent's index
|
||||
number is printed after it. If the parent is a
|
||||
member of a cycle, the cycle number is printed between
|
||||
the name and the index number.
|
||||
|
||||
If the parents of the function cannot be determined, the word
|
||||
`<spontaneous>' is printed in the `name' field, and all the other
|
||||
fields are blank.
|
||||
|
||||
For the function's children, the fields have the following meanings:
|
||||
|
||||
self This is the amount of time that was propagated directly
|
||||
from the child into the function.
|
||||
|
||||
children This is the amount of time that was propagated from the
|
||||
child's children to the function.
|
||||
|
||||
called This is the number of times the function called
|
||||
this child `/' the total number of times the child
|
||||
was called. Recursive calls by the child are not
|
||||
listed in the number after the `/'.
|
||||
|
||||
name This is the name of the child. The child's index
|
||||
number is printed after it. If the child is a
|
||||
member of a cycle, the cycle number is printed
|
||||
between the name and the index number.
|
||||
|
||||
If there are any cycles (circles) in the call graph, there is an
|
||||
entry for the cycle-as-a-whole. This entry shows who called the
|
||||
cycle (as parents) and the members of the cycle (as children.)
|
||||
The `+' recursive calls entry shows the number of function calls that
|
||||
were internal to the cycle, and the calls entry for each member shows,
|
||||
for that member, how many times it was called from other members of
|
||||
the cycle.
|
||||
|
||||
Copyright (C) 2012-2024 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved.
|
||||
|
||||
Index by function name
|
||||
|
||||
[4] calculate_distance_matrix [8] find_bridges_dfs_v2 [12] get_eccentricities
|
||||
[1] dfs [9] find_components_dfs [13] get_radius
|
||||
[5] dfs_articulations [2] gemm_basic [3] print_matrix
|
||||
[6] dfs_bridges [10] get_centre [14] read_csv
|
||||
[7] find_articulations_dfs_v2 [11] get_diameter [15] test_with_dfs
|
Loading…
Reference in New Issue
Block a user