Add graph references

This commit is contained in:
Abdelrahman Said
2026-06-28 13:49:01 +01:00
parent 0a9807e448
commit a11edf0c53
2578 changed files with 868045 additions and 0 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,61 @@
/*
igraph library.
Copyright (C) 2013-2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef IGRAPH_BENCH_H
#define IGRAPH_BENCH_H
#include <sys/resource.h> /* getrusage */
#include <sys/time.h> /* gettimeofday */
#include <unistd.h> /* sleep */
static inline void igraph_get_cpu_time(double *data) {
struct rusage self;
struct timeval real;
gettimeofday(&real, NULL);
getrusage(RUSAGE_SELF, &self);
data[0] = (double) real.tv_sec + 1e-6 * real.tv_usec; /* real */
data[1] = (double) self.ru_utime.tv_sec + 1e-6 * self.ru_utime.tv_usec; /* user */
data[2] = (double) self.ru_stime.tv_sec + 1e-6 * self.ru_stime.tv_usec; /* system */
}
#define BENCH_INIT() \
do { \
printf("\n|> Benchmark file: %s\n", IGRAPH_FILE_BASENAME); \
sleep(1); \
} while (0)
#define REPEAT(CODE, N) \
do { \
igraph_int_t rep_i; \
for (rep_i=0; rep_i < N; ++rep_i) { CODE; } \
} while (0)
#define BENCH(NAME, ...) do { \
double start[3], stop[3]; \
double r, u, s; \
igraph_get_cpu_time(start); \
{ __VA_ARGS__; } \
igraph_get_cpu_time(stop); \
r = 1e-3 * round(1e3 * (stop[0] - start[0])); \
u = 1e-3 * round(1e3 * (stop[1] - start[1])); \
s = 1e-3 * round(1e3 * (stop[2] - start[2])); \
printf("| %-80s %5.3gs %5.3gs %5.3gs\n", NAME, r, u, s); \
} while (0)
#endif
@@ -0,0 +1,150 @@
/*
IGraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#include "igraph_spatial.h"
#include <float.h>
void bench_lune(igraph_int_t test_nr, igraph_int_t point_count, igraph_int_t dimensions, igraph_real_t beta) {
igraph_matrix_t points;
igraph_t g;
char msg[200];
igraph_matrix_init(&points, point_count, dimensions);
for (igraph_int_t point = 0; point < point_count; point++) {
for (igraph_int_t dim = 0; dim < dimensions; dim++) {
MATRIX(points, point, dim) = RNG_UNIF01();
}
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%3"IGRAPH_PRId" Lune based beta skeleton in %dD, beta=%.3f, n=%6" IGRAPH_PRId,
test_nr, (int) dimensions, beta, point_count);
BENCH(msg, igraph_lune_beta_skeleton(&g, &points, beta));
igraph_destroy(&g);
igraph_matrix_destroy(&points);
}
void bench_circle(igraph_int_t test_nr, igraph_int_t point_count, igraph_int_t dimensions, igraph_real_t beta) {
igraph_matrix_t points;
igraph_t g;
char msg[200];
igraph_matrix_init(&points, point_count, dimensions);
for (igraph_int_t point = 0; point < point_count; point++) {
for (igraph_int_t dim = 0; dim < dimensions; dim++) {
MATRIX(points, point, dim) = RNG_UNIF01();
}
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%3"IGRAPH_PRId" Circle based beta skeleton in %dD, beta=%3f, n=%6" IGRAPH_PRId,
test_nr, (int) dimensions, beta, point_count);
BENCH(msg, igraph_circle_beta_skeleton(&g, &points, beta));
igraph_destroy(&g);
igraph_matrix_destroy(&points);
}
void bench_gabriel(igraph_int_t test_nr, igraph_int_t point_count, igraph_int_t dimensions, igraph_real_t beta_cutoff) {
igraph_matrix_t points;
igraph_vector_t edge_weights;
igraph_t g;
char msg[200];
igraph_matrix_init(&points, point_count, dimensions);
igraph_vector_init(&edge_weights, 0);
for (igraph_int_t point = 0; point < point_count; point++) {
for (igraph_int_t dim = 0; dim < dimensions; dim++) {
MATRIX(points, point, dim) = RNG_UNIF01();
}
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%3"IGRAPH_PRId" Beta weighted gabriel graph in %dD, cutoff=%3f, n=%6" IGRAPH_PRId,
test_nr, (int) dimensions, beta_cutoff, point_count);
BENCH(msg, igraph_beta_weighted_gabriel_graph(&g, &edge_weights, &points, beta_cutoff));
igraph_vector_destroy(&edge_weights);
igraph_destroy(&g);
igraph_matrix_destroy(&points);
}
int main(void) {
igraph_int_t test_nr = 0;
bench_lune(++test_nr, 100, 2, 2);
bench_lune(++test_nr, 1000, 2, 2);
bench_lune(++test_nr, 10000, 2, 2);
bench_lune(++test_nr, 100000, 2, 2);
bench_lune(++test_nr, 100, 3, 2);
bench_lune(++test_nr, 1000, 3, 2);
bench_lune(++test_nr, 10000, 3, 2);
bench_lune(++test_nr, 100000, 3, 2);
bench_lune(++test_nr, 1000, 4, 2);
bench_lune(++test_nr, 10000, 2, 1);
bench_lune(++test_nr, 10000, 2, 2);
bench_lune(++test_nr, 10000, 2, 4);
bench_lune(++test_nr, 10000, 2, 8);
bench_lune(++test_nr, 10000, 2, 16);
bench_lune(++test_nr, 10000, 2, 32);
bench_lune(++test_nr, 10000, 2, 64);
bench_lune(++test_nr, 10000, 2, 128);
bench_lune(++test_nr, 10000, 2, 256);
bench_lune(++test_nr, 10000, 2, 512);
bench_lune(++test_nr, 10000, 2, 1024);
bench_lune(++test_nr, 1000, 2, 0.9);
bench_lune(++test_nr, 1000, 2, 0.5);
bench_lune(++test_nr, 1000, 2, 0.1);
bench_circle(++test_nr, 100, 2, 2);
bench_circle(++test_nr, 1000, 2, 2);
bench_circle(++test_nr, 10000, 2, 2);
bench_circle(++test_nr, 100000, 2, 2);
bench_circle(++test_nr, 10000, 2, 2);
bench_circle(++test_nr, 10000, 2, 3);
bench_circle(++test_nr, 10000, 2, 5);
bench_circle(++test_nr, 10000, 2, 15);
bench_circle(++test_nr, 10000, 2, 50);
bench_gabriel(++test_nr, 100, 2, 2);
bench_gabriel(++test_nr, 1000, 2, 2);
bench_gabriel(++test_nr, 10000, 2, 2);
bench_gabriel(++test_nr, 100000, 2, 2);
bench_gabriel(++test_nr, 100, 3, 2);
bench_gabriel(++test_nr, 1000, 3, 2);
bench_gabriel(++test_nr, 10000, 3, 2);
bench_gabriel(++test_nr, 100000, 3, 2);
return 0;
}
@@ -0,0 +1,56 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_vector_int_t colors;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
igraph_vector_int_init(&colors, 0);
igraph_erdos_renyi_game_gnm(&g, 50000, 1000000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 1 COLORED_NEIGHBORS, random graph with 50,000 vertices and 2,000,000 edges",
igraph_vertex_coloring_greedy(&g, &colors, IGRAPH_COLORING_GREEDY_COLORED_NEIGHBORS)
);
BENCH(" 2 DSATUR, random graph with 50,000 vertices and 2,000,000 edges",
igraph_vertex_coloring_greedy(&g, &colors, IGRAPH_COLORING_GREEDY_DSATUR)
);
igraph_destroy(&g);
printf("\n");
igraph_barabasi_game(&g, 100000, 1, 15, NULL, 0, 0, 0, IGRAPH_BARABASI_PSUMTREE, NULL);
BENCH(" 1 COLORED_NEIGHBORS, pref. attach. graph n=100,000 m=15",
igraph_vertex_coloring_greedy(&g, &colors, IGRAPH_COLORING_GREEDY_COLORED_NEIGHBORS)
);
BENCH(" 2 DSATUR, pref. attach. graph n=100,000 m=15",
igraph_vertex_coloring_greedy(&g, &colors, IGRAPH_COLORING_GREEDY_DSATUR)
);
igraph_destroy(&g);
igraph_vector_int_destroy(&colors);
return 0;
}
@@ -0,0 +1,109 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void run_bench(const igraph_t *graph, const igraph_vector_t *weights,
const char *name, int rep) {
igraph_vector_int_t membership;
igraph_vector_t vertex_weight;
igraph_int_t vcount = igraph_vcount(graph);
igraph_int_t ecount = igraph_ecount(graph);
char msg[256], msg2[128];
igraph_vector_int_init(&membership, vcount);
igraph_vector_init(&vertex_weight, vcount);
igraph_strength(graph, &vertex_weight, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, weights);
snprintf(msg2, sizeof(msg2) / sizeof(msg2[0]),
"%s, vcount=%" IGRAPH_PRId ", ecount=%" IGRAPH_PRId ", %s, %dx",
name, vcount, ecount, weights == NULL ? "unweighted" : "weighted",
rep);
snprintf(msg, sizeof(msg) / sizeof(msg[0]), "1 Louvain, %s", msg2);
BENCH(msg, REPEAT(igraph_community_multilevel(graph, weights, 1.0, &membership, NULL, NULL), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]), "2 Leiden , %s", msg2);
BENCH(msg, REPEAT(igraph_community_leiden(graph, weights, &vertex_weight, NULL, 1.0 / igraph_vector_sum(weights), 0.01, false, 1, &membership, NULL, NULL), rep));
printf("\n");
igraph_vector_destroy(&vertex_weight);
igraph_vector_int_destroy(&membership);
}
void rand_weights(const igraph_t *graph, igraph_vector_t *weights) {
igraph_int_t ecount = igraph_ecount(graph);
igraph_vector_resize(weights, ecount);
for (igraph_int_t i=0; i < ecount; i++) {
VECTOR(*weights)[i] = RNG_UNIF01();
}
}
int main(void) {
igraph_t graph;
igraph_vector_t weights;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_init(&weights, 0);
igraph_erdos_renyi_game_gnm(&graph, 100, 500, false, false, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "G(n,m)", 1000);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 1000, 5000, false, false, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "G(n,m)", 100);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 1000, 50000, false, false, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "G(n,m)", 10);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 10000, 50000, false, false, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "G(n,m)", 10);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100000, 500000, false, false, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "G(n,m)", 1);
igraph_destroy(&graph);
igraph_forest_fire_game(&graph, 1000, 0.2, 1, 2, false);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "forest fire", 100);
igraph_destroy(&graph);
igraph_barabasi_game(&graph, 1000, 1, 5, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&graph, &weights);
run_bench(&graph, &weights, "PA", 100);
igraph_destroy(&graph);
igraph_vector_destroy(&weights);
return 0;
}
@@ -0,0 +1,110 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
/* Benchmarks related to biconnected components. */
void run_bench(igraph_int_t vcount, igraph_real_t meandeg, igraph_int_t rep) {
igraph_t g;
igraph_bool_t b;
igraph_vector_int_t ivec;
char msg[128];
igraph_erdos_renyi_game_gnm(&g, vcount, round(meandeg * vcount / 2), IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_int_init(&ivec, igraph_vcount(&g));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 1 Weakly connected? vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, 10*rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_is_connected(&g, &b, IGRAPH_WEAK), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 2 Weak components. vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_connected_components(&g, &ivec, NULL, NULL, IGRAPH_WEAK), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 3 Strongly connected? vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, 10*rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_is_connected(&g, &b, IGRAPH_STRONG), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 4 Strong components. vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_connected_components(&g, &ivec, NULL, NULL, IGRAPH_STRONG), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 5 Biconnected? vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_is_biconnected(&g, &b), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 6 Bridges. vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_bridges(&g, &ivec), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 7 Articulation pts. vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_invalidate_cache(&g);
BENCH(msg, REPEAT(igraph_articulation_points(&g, &ivec), rep));
igraph_vector_int_destroy(&ivec);
igraph_destroy(&g);
printf("\n");
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
// Note that whether these random graphs end up being connected
// with high probability depends not only on their mean degree,
// but also their vertex count.
run_bench(10000, 0.5, 100); // no giant component
run_bench(10000, 3, 100); // not weakly connected
run_bench(10000, 10, 100); // not strongly connected
run_bench(10000, 20, 100); // strongly connnected
run_bench(100000, 0.5, 100); // no giant component
run_bench(100000, 3, 100); // not weakly connected
run_bench(100000, 10, 100); // not strongly connected
run_bench(100000, 20, 100); // strongly connnected
return 0;
}
@@ -0,0 +1,136 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void gnp(igraph_int_t n, igraph_real_t p, igraph_bool_t directed, igraph_edge_type_sw_t allowed_edge_types) {
igraph_t g;
igraph_erdos_renyi_game_gnp(&g, n, p, directed, allowed_edge_types, IGRAPH_EDGE_UNLABELED);
igraph_destroy(&g);
}
void gnm(igraph_int_t n, igraph_real_t meandeg, igraph_bool_t directed, igraph_edge_type_sw_t allowed_edge_types) {
igraph_t g;
igraph_erdos_renyi_game_gnm(&g, n, round(directed ? n * meandeg : 0.5 * n * meandeg), directed, allowed_edge_types, IGRAPH_EDGE_UNLABELED);
igraph_destroy(&g);
}
void chung_lu(const igraph_vector_t *outdeg, const igraph_vector_t *indeg, igraph_bool_t loops) {
igraph_t g;
igraph_chung_lu_game(&g, outdeg, indeg, loops, IGRAPH_CHUNG_LU_ORIGINAL);
igraph_destroy(&g);
}
void run_bench(igraph_int_t vcount, igraph_real_t meandeg, igraph_int_t rep) {
igraph_t g;
igraph_real_t p = meandeg / vcount;
igraph_vector_t outdeg, indeg;
char msg[128], msg2[80];
snprintf(msg2, sizeof(msg2) / sizeof(msg2[0]),
"vcount=%" IGRAPH_PRId ", meandeg=%g, %" IGRAPH_PRId "x",
vcount, meandeg, rep);
igraph_vector_init(&outdeg, 0);
igraph_vector_init(&indeg, 0);
igraph_erdos_renyi_game_gnp(&g, vcount, p, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_strength(&g, &outdeg, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, NULL);
igraph_destroy(&g);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 1 G(n,p) undirected, no loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnp(vcount, p, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 2 G(n,m) undirected, no loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnm(vcount, meandeg, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 3 Chung-Lu undirected, no loops, %s", msg2);
BENCH(msg, REPEAT(chung_lu(&outdeg, NULL, IGRAPH_NO_LOOPS), rep));
printf("\n");
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 4 G(n,p) undirected, loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnp(vcount, p, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 5 G(n,m) undirected, loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnm(vcount, meandeg, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 6 Chung-Lu undirected, loops, %s", msg2);
BENCH(msg, REPEAT(chung_lu(&outdeg, NULL, IGRAPH_LOOPS), rep));
printf("\n");
igraph_erdos_renyi_game_gnp(&g, vcount, p, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_strength(&g, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, NULL);
igraph_strength(&g, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, NULL);
igraph_destroy(&g);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 7 G(n,p) directed, no loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnp(vcount, p, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 8 G(n,m) directed, no loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnm(vcount, meandeg, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 9 Chung-Lu directed, no loops, %s", msg2);
BENCH(msg, REPEAT(chung_lu(&outdeg, &indeg, IGRAPH_NO_LOOPS), rep));
printf("\n");
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"10 G(n,p) directed, loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnp(vcount, p, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"11 G(n,m) directed, loops / no multi, %s", msg2);
BENCH(msg, REPEAT(gnm(vcount, meandeg, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"12 Chung-Lu directed, loops, %s", msg2);
BENCH(msg, REPEAT(chung_lu(&outdeg, &indeg, IGRAPH_LOOPS), rep));
printf("\n\n");
igraph_vector_destroy(&indeg);
igraph_vector_destroy(&outdeg);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
run_bench(100, 3, 10000);
run_bench(10000, 3, 100);
run_bench(1000000, 3, 1);
run_bench(10000, 1, 1000);
run_bench(10000, 100, 10);
return 0;
}
@@ -0,0 +1,144 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
#define BENCH_UNDIR(N, REP) \
do { \
igraph_barabasi_game(&graph, N, 1, 3, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL); \
igraph_degree(&graph, &deg, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS); \
igraph_destroy(&graph); \
\
BENCH("Undirected simple, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_SIMPLE_SW, &graphical), REP); \
); \
\
BENCH("Undirected loops, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
BENCH("Undirected multi, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_MULTI_SW, &graphical), REP); \
); \
\
BENCH("Undirected multi, loops, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_MULTI_SW | IGRAPH_LOOPS_SW, &graphical), 100); \
); \
\
igraph_erdos_renyi_game_gnp(&graph, N, 12.0/N, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED); \
igraph_degree(&graph, &deg, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS); \
igraph_destroy(&graph); \
\
BENCH("Undirected simple, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_SIMPLE_SW, &graphical), REP); \
); \
\
BENCH("Undirected loops, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
BENCH("Undirected multi, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_MULTI_SW, &graphical), REP); \
); \
\
BENCH("Undirected multi, loops, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&deg, NULL, IGRAPH_MULTI_SW | IGRAPH_LOOPS_SW, &graphical), 100); \
); \
\
} while (0)
#define BENCH_DIR(N, REP) \
do { \
igraph_barabasi_game(&graph, N, 1, 3, NULL, true, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL); \
igraph_degree(&graph, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS); \
igraph_degree(&graph, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS); \
igraph_destroy(&graph); \
\
BENCH("Directed simple, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_SIMPLE_SW, &graphical), REP); \
); \
\
BENCH("Directed loops, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
BENCH("Directed multi, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_MULTI_SW, &graphical), REP); \
); \
\
BENCH("Directed multi, loops, PA, n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_MULTI_SW | IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
igraph_erdos_renyi_game_gnp(&graph, N, 12.0/N, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED); \
igraph_degree(&graph, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS); \
igraph_degree(&graph, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS); \
igraph_destroy(&graph); \
\
BENCH("Directed simple, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_SIMPLE_SW, &graphical), REP); \
); \
\
BENCH("Directed loops, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
BENCH("Directed multi, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_MULTI_SW, &graphical), REP); \
); \
\
BENCH("Directed multi, loops, G(n,p), n = " TOSTR(N) ", " TOSTR(REP) "x", \
REPEAT(igraph_is_graphical(&outdeg, &indeg, IGRAPH_MULTI_SW | IGRAPH_LOOPS_SW, &graphical), REP); \
); \
\
} while (0)
int main(void) {
igraph_t graph;
igraph_vector_int_t deg, outdeg, indeg;
igraph_bool_t graphical;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&deg, 0);
igraph_vector_int_init(&outdeg, 0);
igraph_vector_int_init(&indeg, 0);
BENCH_UNDIR(50, 2000000);
BENCH_DIR(50, 2000000);
printf("\n");
BENCH_UNDIR(1000, 100000);
BENCH_DIR(1000, 100000);
printf("\n");
BENCH_UNDIR(1000000, 100);
BENCH_DIR(1000000, 100);
igraph_vector_int_destroy(&deg);
igraph_vector_int_destroy(&outdeg);
igraph_vector_int_destroy(&indeg);
return 0;
}
@@ -0,0 +1,100 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
/*
* Benchmark creating graphs from dense adjacency matrices.
*
* When there are a small number of non-zero elements (low mean degree),
* iterating through the matrix dominates the timing. When there are
* many non-zero elements, creating the graphfrom its edge list dominates.
*/
void adjacency(const igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, igraph_loops_t loops) {
igraph_t g;
igraph_adjacency(&g, adjmatrix, mode, loops);
igraph_destroy(&g);
}
void weighted_adjacency(const igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, igraph_vector_t *weights, igraph_loops_t loops) {
igraph_t g;
igraph_weighted_adjacency(&g, adjmatrix, mode, weights, loops);
igraph_destroy(&g);
}
void run_bench(igraph_int_t vcount, igraph_int_t meandeg, igraph_int_t rep) {
igraph_t g;
igraph_matrix_t mat;
igraph_vector_t weights;
char msg[128];
igraph_adjacency_t types[] = {
IGRAPH_ADJ_DIRECTED,
IGRAPH_ADJ_MAX,
IGRAPH_ADJ_PLUS,
IGRAPH_ADJ_UPPER /* similar to DIRECTED when unweighted, similar to MAX when weighted */
};
const char *names[] = { "DIRECTED", "MAX", "PLUS", "UPPER" };
igraph_matrix_init(&mat, 0, 0);
igraph_erdos_renyi_game_gnm(&g, vcount, meandeg * vcount / 2, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW,
false);
igraph_get_adjacency(&g, &mat, IGRAPH_GET_ADJACENCY_BOTH, NULL, IGRAPH_LOOPS_ONCE);
igraph_vector_init(&weights, igraph_ecount(&g));
igraph_destroy(&g);
for (size_t i=0; i < sizeof(types) / sizeof(types[0]); i++) {
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%2d vcount=%" IGRAPH_PRId ", meandeg=%3" IGRAPH_PRId ", %8s, unweighted, %" IGRAPH_PRId "x",
(int) i+1, vcount, meandeg, names[i], rep);
BENCH(msg, REPEAT(adjacency(&mat, types[i], IGRAPH_LOOPS_ONCE), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%2d vcount=%" IGRAPH_PRId ", meandeg=%3" IGRAPH_PRId ", %8s, weighted, %" IGRAPH_PRId "x",
(int) i+1, vcount, meandeg, names[i], rep);
BENCH(msg, REPEAT(weighted_adjacency(&mat, types[i], &weights, IGRAPH_LOOPS_ONCE), rep));
}
printf("\n");
igraph_vector_destroy(&weights);
igraph_matrix_destroy(&mat);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
run_bench(100, 5, 10000);
run_bench(100, 50, 10000);
run_bench(1000, 5, 100);
run_bench(1000, 50, 100);
run_bench(1000, 500, 100);
run_bench(10000, 5, 1);
run_bench(10000, 50, 1);
run_bench(10000, 500, 1);
return 0;
}
@@ -0,0 +1,95 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t graph;
igraph_real_t avglen;
igraph_matrix_t mat;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_matrix_init(&mat, 0, 0);
igraph_kautz(&graph, 4, 5);
igraph_matrix_resize(&mat, igraph_vcount(&graph), igraph_vcount(&graph)); /* preallocate matrix */
BENCH(" 1 Kautz(4, 5) average_path_length directed",
igraph_average_path_length(&graph, NULL, &avglen, NULL, IGRAPH_DIRECTED, 1);
);
BENCH(" 2 Kautz(4, 5) distances directed",
igraph_distances(&graph, NULL, &mat, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
);
BENCH(" 3 Kautz(4, 5) average_path_length undirected",
igraph_average_path_length(&graph, NULL, &avglen, NULL, IGRAPH_UNDIRECTED, 1);
);
BENCH(" 4 Kautz(4, 5) distances undirected",
igraph_distances(&graph, NULL, &mat, igraph_vss_all(), igraph_vss_all(), IGRAPH_ALL);
);
igraph_destroy(&graph);
{
igraph_vector_int_t dims;
igraph_vector_bool_t periodic;
igraph_vector_int_init_int(&dims, 3, 15, 15, 15);
igraph_vector_bool_init_int(&periodic, 3, 1, 1, 1);
igraph_square_lattice(&graph, &dims, 1, IGRAPH_UNDIRECTED, 0, &periodic);
igraph_vector_int_destroy(&dims);
igraph_vector_bool_destroy(&periodic);
igraph_rewire(&graph, 100, IGRAPH_SIMPLE_SW, NULL);
igraph_matrix_resize(&mat, igraph_vcount(&graph), igraph_vcount(&graph)); /* preallocate matrix */
}
BENCH(" 5 Rewired 15x15x15 lattice average_path_length",
igraph_average_path_length(&graph, NULL, &avglen, NULL, IGRAPH_UNDIRECTED, 1);
);
BENCH(" 6 Rewired 15x15x15 lattice distances undirected",
igraph_distances(&graph, NULL, &mat, igraph_vss_all(), igraph_vss_all(), IGRAPH_ALL);
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 10000, 12000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
igraph_matrix_resize(&mat, igraph_vcount(&graph), igraph_vcount(&graph)); /* preallocate matrix */
BENCH(" 7 Erdos-Renyi n=10000 m=12000 average_path_length directed",
igraph_average_path_length(&graph, NULL, &avglen, NULL, IGRAPH_DIRECTED, 1);
);
BENCH(" 8 Erdos-Renyi n=10000 m=12000 distances directed",
igraph_distances(&graph, NULL, &mat, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT);
);
/* The undirected computation will be much slower on this graph, as the largest weakly connected
* component is much larger. */
BENCH(" 9 Erdos-Renyi n=10000 m=12000 average_path_length undirected",
igraph_average_path_length(&graph, NULL, &avglen, NULL, IGRAPH_UNDIRECTED, 1);
);
BENCH("10 Erdos-Renyi n=10000 m=12000 distances undirected",
igraph_distances(&graph, NULL, &mat, igraph_vss_all(), igraph_vss_all(), IGRAPH_ALL);
);
igraph_destroy(&graph);
igraph_matrix_destroy(&mat);
return 0;
}
@@ -0,0 +1,84 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t graph;
igraph_vector_t betweenness;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_init(&betweenness, 0);
/* Kautz and De Bruijn graphs are connected, therefore there should not be a dramatic difference
* in the performance of the directed and undirected calculations. */
igraph_kautz(&graph, 4, 5);
BENCH(" 1 Betweenness, Kautz(4,5), directed",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false));
BENCH(" 2 Betweenness, Kautz(4,5), undirected",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false));
igraph_destroy(&graph);
igraph_de_bruijn(&graph, 6, 5);
BENCH(" 3 Betweenness, DeBruijn(6,5), directed",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false));
igraph_destroy(&graph);
{
igraph_vector_int_t dims;
igraph_vector_int_init_int_end(&dims, -1, 8, 8, 8, 8, -1);
igraph_square_lattice(&graph, &dims, 1, IGRAPH_UNDIRECTED, /* mutual */ 0, /* periodic */ 0);
BENCH(" 4 Betweenness, Grid(8,8,8,8), undirected",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false));
igraph_destroy(&graph);
igraph_vector_int_destroy(&dims);
igraph_vector_int_init_int_end(&dims, -1, 10, 10, 10, 10, -1);
igraph_square_lattice(&graph, &dims, 1, IGRAPH_UNDIRECTED, /* mutual */ 0, /* periodic */ 0);
BENCH(" 5 Betweenness, Grid(10,10,10,10), cutoff 5",
igraph_betweenness_cutoff(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false, 5));
BENCH(" 6 Betweenness, Grid(10,10,10,10), cutoff 8",
igraph_betweenness_cutoff(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false, 8));
igraph_destroy(&graph);
igraph_vector_int_destroy(&dims);
}
igraph_barabasi_game(&graph, 8000, 1, 1, NULL, 1, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
BENCH(" 7 Betweenness, Barabasi n=8000 m=1, undirected",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false));
BENCH(" 8 Betweenness, Barabasi n=8000 m=1, undirected, cutoff 6",
igraph_betweenness_cutoff(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false, 6));
igraph_destroy(&graph);
igraph_barabasi_game(&graph, 30000, 1, 5, NULL, 1, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
BENCH(" 9 Betweenness, Barabasi n=30000 m=5, directed",
igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false));
BENCH("10 Betweenness, Barabasi n=30000 m=5, directed, cutoff 5",
igraph_betweenness_cutoff(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false, 5));
igraph_destroy(&graph);
igraph_vector_destroy(&betweenness);
return 0;
}
@@ -0,0 +1,164 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void rand_weight_vec(igraph_vector_t *vec, const igraph_t *graph) {
const igraph_int_t n = igraph_ecount(graph);
igraph_vector_resize(vec, n);
for (igraph_int_t i=0; i < n; ++i) {
VECTOR(*vec)[i] = RNG_UNIF(1, 10);
}
}
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
int main(void) {
igraph_t graph;
igraph_vector_t betweenness, weight;
/* These betweenness benchmarks are identical to the weighted closeness ones. */
/* This benchmark compares directed/undirected and weighted/unweighted calculations
* on the same graphs. */
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_init(&betweenness, 0);
igraph_vector_init(&weight, 0);
igraph_kautz(&graph, 4, 3);
/* Kautz and De Bruijn graphs are connected, therefore there should not be a dramatic difference
* in the performance of the directed and undirected calculations. */
#define NAME "Kautz(4,3)"
#define REP 100
BENCH(" 1 Betweenness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH(" 2 Betweenness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
rand_weight_vec(&weight, &graph);
BENCH(" 3 Betweenness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH(" 4 Betweenness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
#define NAME "DeBruijn(5,5)"
#define REP 1
igraph_de_bruijn(&graph, 5, 5);
BENCH(" 5 Betweenness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH(" 6 Betweenness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
rand_weight_vec(&weight, &graph);
BENCH(" 7 Betweenness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH(" 8 Betweenness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
/* Choose the parameters of the Erdős-Rényi model so that the graph will have a large strongly connected
* giant component. With 3000 vertices and 10000 edges, it is likely to contain over 90% of vertices.
* If the graph does not have a giant component, then the directed betweenness calculation will be very
* fast, and not directly comparable to the undirected one. */
#define NAME "GNM(3000,10000)"
#define REP 1
igraph_erdos_renyi_game_gnm(&graph, 3000, 10000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 9 Betweenness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH("10 Betweenness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
rand_weight_vec(&weight, &graph);
BENCH("11 Betweenness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH("12 Betweenness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
/* Benchmark a much denser Erdős-Rényi graph as well. */
#define NAME "GNM(3000,30000)"
#define REP 1
igraph_erdos_renyi_game_gnm(&graph, 3000, 30000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH("13 Betweenness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH("14 Betweenness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, NULL, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
rand_weight_vec(&weight, &graph);
BENCH("15 Betweenness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_DIRECTED, false), REP)
);
BENCH("16 Betweenness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_betweenness(&graph, &weight, &betweenness, igraph_vss_all(), IGRAPH_UNDIRECTED, false), REP)
);
igraph_destroy(&graph);
igraph_vector_destroy(&weight);
igraph_vector_destroy(&betweenness);
return 0;
}
@@ -0,0 +1,54 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_vector_int_list_t res;
igraph_int_t res_int;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
igraph_vector_int_list_init(&res, 0);
igraph_erdos_renyi_game_gnm(&g, 100, 3000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 1 Cliques in random graph with 100 vertices and 3000 edges",
igraph_cliques(&g, &res, /* min_size= */ 0, /* max_size= */ 0, -1);
);
igraph_destroy(&g);
igraph_vector_int_list_clear(&res);
igraph_erdos_renyi_game_gnm(&g, 200, 10000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 2 Cliques in random graph with 200 vertices and 10000 edges, up to size 5",
igraph_cliques(&g, &res, /* min_size= */ 0, /* max_size= */ 5, -1);
);
igraph_vector_int_list_clear(&res);
BENCH(" 3 Clique number of the same graph with 200 vertices and 10000 edges",
igraph_clique_number(&g, &res_int);
);
igraph_vector_int_list_clear(&res);
igraph_destroy(&g);
igraph_vector_int_list_destroy(&res);
return 0;
}
@@ -0,0 +1,164 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void rand_weight_vec(igraph_vector_t *vec, const igraph_t *graph) {
const igraph_int_t n = igraph_ecount(graph);
igraph_vector_resize(vec, n);
for (igraph_int_t i=0; i < n; ++i) {
VECTOR(*vec)[i] = RNG_UNIF(1, 10);
}
}
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
int main(void) {
igraph_t graph;
igraph_vector_t closeness, weight;
/* These closeness benchmarks are identical to the weighted betweenness ones. */
/* This benchmark compares directed/undirected and weighted/unweighted calculations
* on the same graphs. */
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_init(&closeness, 0);
igraph_vector_init(&weight, 0);
igraph_kautz(&graph, 4, 3);
/* Kautz and De Bruijn graphs are connected, therefore there should not be a dramatic difference
* in the performance of the directed and undirected calculations. */
#define NAME "Kautz(4,3)"
#define REP 100
BENCH(" 1 Closeness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, NULL, 1), REP)
);
BENCH(" 2 Closeness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, NULL, 1), REP)
);
rand_weight_vec(&weight, &graph);
BENCH(" 3 Closeness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, &weight, 1), REP)
);
BENCH(" 4 Closeness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, &weight, 1), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
#define NAME "DeBruijn(5,5)"
#define REP 1
igraph_de_bruijn(&graph, 5, 5);
BENCH(" 5 Closeness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, NULL, 1), REP)
);
BENCH(" 6 Closeness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, NULL, 1), REP)
);
rand_weight_vec(&weight, &graph);
BENCH(" 7 Closeness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, &weight, 1), REP)
);
BENCH(" 8 Closeness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, &weight, 1), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
/* Choose the parameters of the Erdős-Rényi model so that the graph will have a large strongly connected
* giant component. With 3000 vertices and 10000 edges, it is likely to contain over 90% of vertices.
* If the graph does not have a giant component, then the directed betweenness calculation will be very
* fast, and not directly comparable to the undirected one. */
#define NAME "GNM(3000,10000)"
#define REP 1
igraph_erdos_renyi_game_gnm(&graph, 3000, 10000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 9 Closeness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, NULL, 1), REP)
);
BENCH("10 Closeness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, NULL, 1), REP)
);
rand_weight_vec(&weight, &graph);
BENCH("11 Closeness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, &weight, 1), REP)
);
BENCH("12 Closeness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, &weight, 1), REP)
);
igraph_destroy(&graph);
#undef NAME
#undef REP
/* Benchmark a much denser Erdős-Rényi graph as well. */
#define NAME "GNM(3000,30000)"
#define REP 1
igraph_erdos_renyi_game_gnm(&graph, 3000, 30000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH("13 Closeness, unweighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, NULL, 1), REP)
);
BENCH("14 Closeness, unweighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, NULL, 1), REP)
);
rand_weight_vec(&weight, &graph);
BENCH("15 Closeness, weighted, " NAME ", directed, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_OUT, &weight, 1), REP)
);
BENCH("16 Closeness, weighted, " NAME ", undirected, " TOSTR(REP) "x",
REPEAT(igraph_closeness(&graph, &closeness, NULL, NULL, igraph_vss_all(), IGRAPH_ALL, &weight, 1), REP)
);
igraph_destroy(&graph);
igraph_vector_destroy(&weight);
igraph_vector_destroy(&closeness);
return 0;
}
@@ -0,0 +1,56 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_graph_list_t res;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
igraph_graph_list_init(&res, 0);
igraph_empty(&g, 1000, IGRAPH_UNDIRECTED);
BENCH(" 1 Decompose graph with 1000 isolated vertices",
igraph_decompose(&g, &res, IGRAPH_WEAK, -1, -1);
);
igraph_destroy(&g);
igraph_graph_list_clear(&res);
igraph_empty(&g, 10000, IGRAPH_UNDIRECTED);
BENCH(" 2 Decompose graph with 10000 isolated vertices",
igraph_decompose(&g, &res, IGRAPH_WEAK, -1, -1);
);
igraph_destroy(&g);
igraph_graph_list_clear(&res);
igraph_empty(&g, 100000, IGRAPH_UNDIRECTED);
BENCH(" 3 Decompose graph with 100000 isolated vertices",
igraph_decompose(&g, &res, IGRAPH_WEAK, -1, -1);
);
igraph_destroy(&g);
igraph_graph_list_clear(&res);
igraph_graph_list_destroy(&res);
return 0;
}
@@ -0,0 +1,142 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
/* Calls igraph_degree_1() separately for each vertex. */
void deg1(const igraph_t *g, igraph_vector_int_t *res, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t n = igraph_vcount(g);
igraph_vector_int_resize(res, n);
for (igraph_int_t i=0; i < n; i++) {
igraph_degree_1(g, &VECTOR(*res)[i], i, mode, loops);
}
}
/* Calls igraph_degree() separately for each vertex, pre-allocates work vector. */
void degv(const igraph_t *g, igraph_vector_int_t *res, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t n = igraph_vcount(g);
igraph_vector_int_t work;
igraph_vector_int_resize(res, n);
igraph_vector_int_init(&work, 1);
for (igraph_int_t i=0; i < n; i++) {
igraph_degree(g, &work, igraph_vss_1(i), mode, loops);
}
igraph_vector_int_destroy(&work);
}
/* Calls igraph_degree() separately for each vertex, allocates a new work vector each time. */
void degv2(const igraph_t *g, igraph_vector_int_t *res, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t n = igraph_vcount(g);
for (igraph_int_t i=0; i < n; i++) {
igraph_vector_int_t work;
igraph_vector_int_init(&work, 1);
igraph_degree(g, &work, igraph_vss_1(i), mode, loops);
igraph_vector_int_destroy(&work);
}
}
int main(void) {
igraph_t g;
igraph_vector_int_t degs;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_barabasi_game(&g, 100000, 1, 10, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
igraph_vector_int_init(&degs, igraph_vcount(&g));
#define REP 1000
printf("Count loops twice, O(1) per degree, fast methods only.\n");
BENCH(" 1 igraph_degree(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(igraph_degree(&g, &degs, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 2 deg1(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(deg1(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
#undef REP
#define REP 100
printf("\nCount loops twice, O(1) per degree.\n");
BENCH(" 1 igraph_degree(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(igraph_degree(&g, &degs, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 2 deg1(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(deg1(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 3 degv(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 4 degv2(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv2(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
#undef REP
#define REP 100
printf("\nCount loops twice, O(1) per degree.\n");
BENCH(" 1 igraph_degree(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(igraph_degree(&g, &degs, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 2 deg1(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(deg1(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 3 degv(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
BENCH(" 4 degv2(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv2(&g, &degs, IGRAPH_ALL, IGRAPH_LOOPS), REP);
);
#undef REP
#define REP 100
printf("\nDo not count loops, O(d) per degree.\n");
BENCH(" 1 igraph_degree(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(igraph_degree(&g, &degs, igraph_vss_all(), IGRAPH_ALL, IGRAPH_NO_LOOPS), REP);
);
BENCH(" 2 deg1(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(deg1(&g, &degs, IGRAPH_ALL, IGRAPH_NO_LOOPS), REP);
);
BENCH(" 3 degv(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv(&g, &degs, IGRAPH_ALL, IGRAPH_NO_LOOPS), REP);
);
BENCH(" 4 degv2(), preferential attachment n=100000, m=10, " TOSTR(REP) "x",
REPEAT(degv2(&g, &degs, IGRAPH_ALL, IGRAPH_NO_LOOPS), REP);
);
igraph_vector_int_destroy(&degs);
igraph_destroy(&g);
return 0;
}
@@ -0,0 +1,120 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g, template;
igraph_vector_int_t degrees, outdeg, indeg;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
/* This benchmark indirectly tests the performance of igraph_set_t at the
* moment because igraph_degree_sequence_game() (especially the
* IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE mode) heavily relies on sets.
* This might change in future versions so the name of the benchmark
* reflects the name of the function that is tested directly */
igraph_vector_int_init(&degrees, 1000);
igraph_vector_int_fill(&degrees, 7);
BENCH(" 1 Degseq of undirected k-regular, N=1000, k=7, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &degrees, /* indeg = */ NULL, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_vector_int_destroy(&degrees);
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&degrees, 0);
igraph_barabasi_game(&template, 1000, /* power = */ 1, /* m = */ 1,
/* outseq = */ NULL, /* outpref = */ true, /* A = */ 0,
IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE, /* start_from = */ NULL
);
igraph_degree(&template, &degrees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
BENCH(" 2 Degseq of undirected BA, N=1000, m=1, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &degrees, /* indeg = */ NULL, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_destroy(&template);
igraph_vector_int_destroy(&degrees);
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&degrees, 0);
igraph_erdos_renyi_game_gnm(&template, 200, 600, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_degree(&template, &degrees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
BENCH(" 3 Degseq of undirected G(n,m), N=150, m=450, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &degrees, /* indeg = */ NULL, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_destroy(&template);
igraph_vector_int_destroy(&degrees);
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&degrees, 0);
igraph_grg_game(&template, 10000, 0.013, /* torus = */ false, /* x = */ NULL, /* y = */ NULL);
igraph_degree(&template, &degrees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
BENCH(" 4 Degseq of GRG, N=10000, r=0.013, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &degrees, /* indeg = */ NULL, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_destroy(&template);
igraph_vector_int_destroy(&degrees);
igraph_vector_int_init(&degrees, 1000);
igraph_vector_int_fill(&degrees, 5);
BENCH(" 5 Degseq of directed k-regular, N=1000, k=5, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &degrees, &degrees, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_vector_int_destroy(&degrees);
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&outdeg, 0);
igraph_vector_int_init(&indeg, 0);
igraph_barabasi_game(&template, 5000, /* power = */ 1, /* m = */ 2,
/* outseq = */ NULL, /* outpref = */ true, /* A = */ 0,
IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, /* start_from = */ NULL
);
igraph_degree(&template, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS);
igraph_degree(&template, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS);
BENCH(" 6 Degseq of directed BA, N=500, m=2, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &outdeg, &indeg, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_destroy(&template);
igraph_vector_int_destroy(&indeg);
igraph_vector_int_destroy(&outdeg);
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&outdeg, 0);
igraph_vector_int_init(&indeg, 0);
igraph_erdos_renyi_game_gnm(&template, 15000, 45000, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_degree(&template, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS);
igraph_degree(&template, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS);
BENCH(" 7 Degseq of directed G(n,m), N=15000, m=45000, CONFIGURATION_SIMPLE",
igraph_degree_sequence_game(&g, &outdeg, &indeg, IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE)
);
igraph_destroy(&g);
igraph_destroy(&template);
igraph_vector_int_destroy(&indeg);
igraph_vector_int_destroy(&outdeg);
return 0;
}
@@ -0,0 +1,64 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void bench_delaunay(const char *message, igraph_int_t point_count, igraph_int_t dimensions) {
igraph_matrix_t points;
igraph_t g;
char msg[200];
igraph_matrix_init(&points, point_count, dimensions);
for (igraph_int_t point = 0; point < point_count; point++) {
for (igraph_int_t dim = 0; dim < dimensions; dim++) {
MATRIX(points, point, dim) = RNG_UNIF01();
}
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s Delaunay triangulation in %dD, n=%6" IGRAPH_PRId,
message, (int) dimensions, point_count);
BENCH(msg, igraph_delaunay_graph(&g, &points));
igraph_destroy(&g);
igraph_matrix_destroy(&points);
}
int main(void) {
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 20250814);
bench_delaunay(" 1", 1000000, 1);
bench_delaunay(" 2", 100000, 2);
bench_delaunay(" 3", 10000, 2);
bench_delaunay(" 4", 1000, 2);
bench_delaunay(" 5", 100, 2);
bench_delaunay(" 6", 10000, 3);
bench_delaunay(" 7", 1000, 3);
bench_delaunay(" 8", 100, 3);
bench_delaunay(" 9", 2000, 4);
bench_delaunay("10", 500, 5);
bench_delaunay("11", 200, 6);
return 0;
}
@@ -0,0 +1,168 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void bench_gnp(igraph_int_t n, igraph_real_t p, igraph_bool_t directed, igraph_real_t negloop, int rep) {
igraph_t g;
igraph_matrix_t res;
igraph_vector_t weights;
char msg[200];
igraph_matrix_init(&res, 0, 0);
igraph_vector_init(&weights, 0);
/* IGRAPH_NO_LOOPS, as loops are not allowed with negative weights. */
igraph_erdos_renyi_game_gnp(&g, n, p, directed, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
igraph_matrix_resize(&res, igraph_vcount(&g), igraph_vcount(&g));
igraph_vector_resize(&weights, igraph_ecount(&g));
for (igraph_int_t i=0; i < igraph_ecount(&g); i++) {
VECTOR(weights)[i] = RNG_EXP(1);
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 1 n=%d, p=%g, %s, Unweighted, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances(&g, NULL, &res, igraph_vss_all(), igraph_vss_all(), IGRAPH_OUT), rep);
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 2 n=%d, p=%g, %s, Dijkstra, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_dijkstra(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 3 n=%d, p=%g, %s, Unweighted Floyd-Warshall, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), NULL, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_ORIGINAL), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 4 n=%d, p=%g, %s, Unweighted Floyd-Warshall-tree-speedup, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), NULL, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_TREE), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 5 n=%d, p=%g, %s, Floyd-Warshall, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_ORIGINAL), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 6 n=%d, p=%g, %s, Floyd-Warshall-tree-speedup, %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_TREE), rep)
);
/* Negative weights, only for directed graphs. */
if (! directed) {
return;
}
/* Add a small number of negative weights, rely on luck, as well as tuning 'negloop',
* to avoid negative loops. */
for (igraph_int_t i=0; i < trunc(negloop * igraph_ecount(&g)); i++) {
/* For reproducibility, do not write two RNG_...() calls within the same statement,
* as the C language does not guarantee any evaluation order between them. */
igraph_real_t w = RNG_UNIF(-negloop, 0);
VECTOR(weights)[RNG_INTEGER(0, igraph_ecount(&g)-1)] = w;
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 7 n=%d, p=%g, %s, Bellman-Ford (negative), %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_bellman_ford(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 8 n=%d, p=%g, %s, Johnson (negative), %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_johnson(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
" 9 n=%d, p=%g, %s, Floyd-Warshall (negative), %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_ORIGINAL), rep)
);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"10 n=%d, p=%g, %s, Floyd-Warshall-tree-speedup (negative), %dx",
(int) n, p, directed ? " directed" : "undirected", rep);
BENCH(msg,
REPEAT(igraph_distances_floyd_warshall(&g, &res, igraph_vss_all(), igraph_vss_all(), &weights, IGRAPH_OUT, IGRAPH_FLOYD_WARSHALL_TREE), rep)
);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
/*
bench_gnp(100, 0.5, IGRAPH_DIRECTED, 0.01, 200); printf("\n");
bench_gnp(100, 0.5, IGRAPH_UNDIRECTED, 0.01, 200); printf("\n");
bench_gnp(30, 0.5, IGRAPH_DIRECTED, 0.01, 2000); printf("\n");
bench_gnp(30, 0.5, IGRAPH_UNDIRECTED, 0.01, 2000); printf("\n");
bench_gnp(100, 0.1, IGRAPH_DIRECTED, 0.01, 1000); printf("\n");
bench_gnp(100, 0.1, IGRAPH_UNDIRECTED, 0.01, 1000); printf("\n");
bench_gnp(500, 0.1, IGRAPH_DIRECTED, 0.005, 10); printf("\n");
bench_gnp(500, 0.1, IGRAPH_UNDIRECTED, 0.005, 10); printf("\n");
bench_gnp(1500, 0.02, IGRAPH_DIRECTED, 0.01, 1); printf("\n");
bench_gnp(1500, 0.02, IGRAPH_UNDIRECTED, 0.01, 1); printf("\n");
*/
bench_gnp(1000, 0.1, IGRAPH_DIRECTED, 0.002, 1); printf("\n");
bench_gnp(300, 0.1, IGRAPH_DIRECTED, 0.005, 50); printf("\n");
bench_gnp(100, 0.1, IGRAPH_DIRECTED, 0.01, 500); printf("\n");
bench_gnp(50, 0.1, IGRAPH_DIRECTED, 0.01, 10000); printf("\n");
bench_gnp(30, 0.1, IGRAPH_DIRECTED, 0.01, 20000); printf("\n");
bench_gnp(20, 0.2, IGRAPH_DIRECTED, 0.01, 40000); printf("\n");
bench_gnp(10, 0.2, IGRAPH_DIRECTED, 0.01, 100000); printf("\n");
bench_gnp(1500, 0.01, IGRAPH_DIRECTED, 0.01, 1); printf("\n");
bench_gnp(100, 0.5, IGRAPH_DIRECTED, 0.01, 1000); printf("\n");
return 0;
}
@@ -0,0 +1,175 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
#define BENCH_BLOCK() \
BENCH(" 1 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=3, all, " TOSTR(REP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_all(IGRAPH_EDGEORDER_ID), 3, false, true), REP); \
); \
BENCH(" 2 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=3, subset: all, " TOSTR(REP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_range(0, igraph_ecount(&g)), 3, false, true), REP); \
); \
\
igraph_random_sample(&eids, 0, igraph_ecount(&g)-1, SS); \
\
BENCH(" 3 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=3, subset: " TOSTR(SS) ", " TOSTR(SREP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_vector(&eids), 3, false, true), SREP); \
); \
\
BENCH(" 4 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=4, all, " TOSTR(REP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_all(IGRAPH_EDGEORDER_ID), 4, false, true), REP); \
); \
\
BENCH(" 4 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=4, subset: all, " TOSTR(REP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_range(0, igraph_ecount(&g)), 4, false, true), REP); \
); \
BENCH(" 5 vc=" TOSTR(VCOUNT) ", ec=" TOSTR(ECOUNT) ", k=4, subset: " TOSTR(SS) ", " TOSTR(SREP) "x", \
REPEAT(igraph_ecc(&g, &ecc, igraph_ess_vector(&eids), 4, false, true), SREP); \
);
int main(void) {
igraph_t g;
igraph_vector_t ecc;
igraph_vector_int_t eids;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_init(&ecc, 0);
igraph_vector_int_init(&eids, 0);
printf("Erdos-Renyi GNM:\n\n");
#define VCOUNT 100
#define ECOUNT 5000
#define REP 100
#define SS 100
#define SREP 1000
igraph_erdos_renyi_game_gnm(&g, VCOUNT, ECOUNT, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&ecc, igraph_ecount(&g));
BENCH_BLOCK()
igraph_destroy(&g);
#undef VCOUNT
#undef ECOUNT
#undef REP
#undef SS
#undef SREP
printf("\n");
#define VCOUNT 1000
#define ECOUNT 5000
#define REP 100
#define SS 100
#define SREP 1000
igraph_erdos_renyi_game_gnm(&g, VCOUNT, ECOUNT, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&ecc, igraph_ecount(&g));
BENCH_BLOCK()
igraph_destroy(&g);
#undef VCOUNT
#undef ECOUNT
#undef REP
#undef SS
#undef SREP
printf("\n");
#define VCOUNT 10000
#define ECOUNT 10000
#define REP 100
#define SS 100
#define SREP 1000
igraph_erdos_renyi_game_gnm(&g, VCOUNT, ECOUNT, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&ecc, igraph_ecount(&g));
BENCH_BLOCK()
igraph_destroy(&g);
#undef VCOUNT
#undef ECOUNT
#undef REP
#undef SS
#undef SREP
printf("\n");
#define VCOUNT 10000
#define ECOUNT 50000
#define REP 100
#define SS 100
#define SREP 1000
igraph_erdos_renyi_game_gnm(&g, VCOUNT, ECOUNT, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&ecc, igraph_ecount(&g));
BENCH_BLOCK()
igraph_destroy(&g);
#undef VCOUNT
#undef ECOUNT
#undef REP
#undef SS
#undef SREP
printf("\n");
#define VCOUNT 10000
#define ECOUNT 50000
#define REP 100
#define SS 100
#define SREP 1000
printf("Barabasi:\n\n");
igraph_barabasi_game(&g,
VCOUNT, 1, ECOUNT / VCOUNT, NULL, true, 0,
IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
igraph_vector_resize(&ecc, igraph_ecount(&g));
BENCH_BLOCK()
igraph_destroy(&g);
#undef VCOUNT
#undef ECOUNT
#undef REP
#undef SS
#undef SREP
igraph_vector_int_destroy(&eids);
igraph_vector_destroy(&ecc);
return 0;
}
@@ -0,0 +1,125 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
// Function to generate random vertex indices for subgraph extraction
void generate_random_vertices(igraph_vector_int_t *vertices,
igraph_int_t graph_size,
igraph_int_t subset_size) {
igraph_vector_int_init(vertices, 0);
igraph_vector_int_resize(vertices, subset_size);
// Create a vector to track used vertices
igraph_vector_int_t used_vertices;
igraph_vector_int_init(&used_vertices, graph_size);
for (igraph_int_t i = 0; i < graph_size; i++) {
VECTOR(used_vertices)[i] = i;
}
// Randomly select subset_size unique vertices
for (igraph_int_t i = 0; i < subset_size; i++) {
igraph_int_t index = RNG_INTEGER(0, graph_size - i - 1);
VECTOR(*vertices)[i] = VECTOR(used_vertices)[index];
// Remove the selected vertex from used_vertices
VECTOR(used_vertices)[index] = VECTOR(used_vertices)[graph_size - i - 1];
}
// Sort the vertices to simulate real-world scenarios
igraph_vector_int_sort(vertices);
igraph_vector_int_destroy(&used_vertices);
}
// Benchmark function
void bench_induced_subgraph(igraph_t *graph, igraph_vector_int_t *vertices,
igraph_subgraph_implementation_t impl) {
igraph_t subgraph;
igraph_vs_t vs;
igraph_vs_vector(&vs, vertices);
igraph_induced_subgraph(graph, &subgraph, vs, impl);
igraph_vs_destroy(&vs);
igraph_destroy(&subgraph);
}
void run_bench(int i, int n, int m, int subset_percentage) {
igraph_t graph;
igraph_vector_int_t vertices;
// Calculate subset size based on percentage
igraph_int_t subset_size = (n * subset_percentage) / 100;
// Prepare random graph and vertices
igraph_erdos_renyi_game_gnm(&graph, n, m, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
generate_random_vertices(&vertices, n, subset_size);
char msg[255];
int rep = 300000000 / (n * subset_percentage);
// Benchmark method 1 (COPY_AND_DELETE)
snprintf(msg, sizeof(msg),
"Method 1 (COPY_AND_DELETE): n=%5d, subset=%3d%%, %dx", n,
subset_percentage, rep);
BENCH(msg, REPEAT(bench_induced_subgraph(&graph, &vertices,
IGRAPH_SUBGRAPH_COPY_AND_DELETE),
rep));
// Benchmark method 2 (CREATE_FROM_SCRATCH)
snprintf(msg, sizeof(msg),
"Method 2 (CREATE_FROM_SCRATCH): n=%5d, subset=%3d%%, %dx", n,
subset_percentage, rep);
BENCH(msg, REPEAT(bench_induced_subgraph(&graph, &vertices,
IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH),
rep));
// Cleanup
igraph_vector_int_destroy(&vertices);
igraph_destroy(&graph);
}
int main(void) {
int i = 0;
// Initialize random number generator
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
// Macro to run benchmarks for different graph sizes and subset percentages
#define BENCHSET(n, m) \
run_bench(++i, n, m, 20); /* 20% subset */ \
run_bench(++i, n, m, 25); /* 25% subset */ \
run_bench(++i, n, m, 30); /* 30% subset */ \
run_bench(++i, n, m, 35); /* 35% subset */ \
run_bench(++i, n, m, 40); /* 40% subset */ \
run_bench(++i, n, m, 45); /* 45% subset */ \
run_bench(++i, n, m, 50); /* 50% subset */ \
run_bench(++i, n, m, 55); /* 55% subset */ \
printf("\n");
// Benchmark different graph sizes
BENCHSET(100, 500);
BENCHSET(1000, 5000);
BENCHSET(10000, 50000);
BENCHSET(100000, 500000);
return 0;
}
@@ -0,0 +1,100 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
#define BARABASI_GRAPH_VERTEX_COUNT 100000
void unit_test_subgraph_edges(
const igraph_t *graph, igraph_vector_int_t *vertices,
igraph_int_t induced_subgraph_vertice_count, igraph_int_t benchmark_count,
const char* bench_message
) {
igraph_vector_int_t edges;
igraph_vector_int_init(&edges, 0);
IGRAPH_UNUSED(vertices);
BENCH(bench_message,
REPEAT(
igraph_induced_subgraph_edges(graph, igraph_vss_range(0, induced_subgraph_vertice_count), &edges),
benchmark_count
)
);
igraph_vector_int_destroy(&edges);
}
void bench_induced_subgraph_edges(void) {
igraph_t g;
igraph_vector_int_t vertices;
igraph_vector_int_init_range(&vertices, 0, BARABASI_GRAPH_VERTEX_COUNT);
igraph_vector_int_shuffle(&vertices);
igraph_barabasi_game(&g, BARABASI_GRAPH_VERTEX_COUNT, 1, 100, NULL, true, 0,
IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
printf("induced_subgraph_edges() for BA graph\n");
#define REP 10
#define INDUCED_SUBGRAPH_VERTEX_COUNT 100
unit_test_subgraph_edges(&g, &vertices, INDUCED_SUBGRAPH_VERTEX_COUNT, REP,
"n=" TOSTR(BARABASI_GRAPH_VERTEX_COUNT) ", "
"m=100, "
"e=" TOSTR(INDUCED_SUBGRAPH_VERTEX_COUNT) ", "
TOSTR(REP) " x"
);
#undef INDUCED_SUBGRAPH_VERTEX_COUNT
#define INDUCED_SUBGRAPH_VERTEX_COUNT 1000
unit_test_subgraph_edges(&g, &vertices, INDUCED_SUBGRAPH_VERTEX_COUNT, REP,
"n=" TOSTR(BARABASI_GRAPH_VERTEX_COUNT) ", "
"m=100, "
"e=" TOSTR(INDUCED_SUBGRAPH_VERTEX_COUNT) ", "
TOSTR(REP) " x"
);
#undef INDUCED_SUBGRAPH_VERTEX_COUNT
#define INDUCED_SUBGRAPH_VERTEX_COUNT 10000
unit_test_subgraph_edges(&g, &vertices, INDUCED_SUBGRAPH_VERTEX_COUNT, REP,
"n=" TOSTR(BARABASI_GRAPH_VERTEX_COUNT) ", "
"m=100, "
"e=" TOSTR(INDUCED_SUBGRAPH_VERTEX_COUNT) ", "
TOSTR(REP) " x"
);
#undef INDUCED_SUBGRAPH_VERTEX_COUNT
#undef REP
igraph_destroy(&g);
igraph_vector_int_destroy(&vertices);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
bench_induced_subgraph_edges();
return 0;
}
@@ -0,0 +1,85 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
int main(void) {
igraph_t graph;
igraph_vector_t distances;
igraph_matrix_t layout;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
igraph_matrix_init(&layout, 0, 0);
igraph_small(&graph, 12, IGRAPH_UNDIRECTED,
0,1, 0,2, 0,3, 1,2, 1,3, 2,3,
3,4, 4,5, 5,6,
6,7, 7,8, 6,8, 7,9, 6,9, 8,9, 7,10, 8,10, 9,10, 10,11, 9,11, 8,11, 7,11,
-1);
igraph_vector_init_real(&distances,
igraph_ecount(&graph),
0.1, 0.09, 0.12, 0.09, 0.1, 0.1,
0.9, 0.9, 0.9,
0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.08, 0.05, 0.1, 0.08, 0.12, 0.09, 0.11
);
#define EPOCHS 5000
#define REP 40
BENCH("Small graph, epochs: " TOSTR(EPOCHS) ", repetitions: " TOSTR(REP), REPEAT(igraph_layout_umap(&graph, &layout, 0, &distances, 0.01, EPOCHS, 0), REP);
);
#undef EPOCHS
#undef REP
#define EPOCHS 500
#define REP 400
BENCH("Small graph, epochs: " TOSTR(EPOCHS) ", repetitions: " TOSTR(REP), REPEAT(igraph_layout_umap(&graph, &layout, 0, &distances, 0.01, EPOCHS, 0) , REP);
);
#undef EPOCHS
#undef REP
#define EPOCHS 60
#define REP 1
#define VCOUNT 10000
#define DENS 0.001
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnp(&graph, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&distances, igraph_ecount(&graph));
for (igraph_int_t i=0; i < igraph_ecount(&graph); i++) {
VECTOR(distances)[i] = RNG_UNIF(0.05, 0.15);
}
BENCH("Larger graph, epochs: " TOSTR(EPOCHS) ", repetitions: " TOSTR(REP), REPEAT(igraph_layout_umap(&graph, &layout, 0, &distances, 0.01, EPOCHS, 0) , REP);
);
igraph_matrix_destroy(&layout);
igraph_destroy(&graph);
igraph_vector_destroy(&distances);
return 0;
}
@@ -0,0 +1,57 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
void bench(int m, int n, int rep) {
igraph_matrix_t mat;
igraph_matrix_init(&mat, m, n);
for (igraph_int_t j=0; j < n; j++) {
for (igraph_int_t i=0; i < m; i++) {
MATRIX(mat, i, j) = RNG_UNIF(-1, 1);
}
}
char name[200];
sprintf(name, "Transpose %5d x %5d, %dx", m, n, rep);
BENCH( name, REPEAT(igraph_matrix_transpose(&mat), rep) );
igraph_matrix_destroy(&mat);
}
int main(void) {
BENCH_INIT();
bench(30, 30, 100000);
bench(100, 100, 10000);
bench(1000, 1000, 100);
bench(1024, 1024, 100); /* naive implementation has bad cache behaviour with power of 2 sizes */
bench(1023, 1025, 100); /* non-symmetric */
bench(3000, 3000, 10);
/* skinny non-symmetric: */
bench(100, 10000, 100);
bench(10000, 100, 100);
return 0;
}
@@ -0,0 +1,54 @@
/*
igraph library.
Copyright (C) 2013-2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_int_t toremovev[] = {
2609, 2098, 14517, 7540, 19560, 8855,
5939, 14947, 441, 16976, 19642, 4188,
15447, 11837, 2333, 7309, 18539, 14099,
14264, 9240
};
const igraph_vector_int_t toremove =
igraph_vector_int_view(toremovev, sizeof(toremovev) / sizeof(toremovev[0]));;
igraph_vector_int_list_t res;
BENCH_INIT();
igraph_full(&g, 200, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_delete_edges(&g, igraph_ess_vector(&toremove));
igraph_vector_int_list_init(&res, 0);
BENCH(" 1 Maximal cliques of almost complete graph",
igraph_maximal_cliques(&g, &res,
/* min_size= */ IGRAPH_UNLIMITED, /* max_size= */ IGRAPH_UNLIMITED,
/* max_results= */ IGRAPH_UNLIMITED);
);
igraph_destroy(&g);
igraph_vector_int_list_destroy(&res);
return 0;
}
@@ -0,0 +1,77 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void bench_pointcloud(const char *message, igraph_metric_t metric, igraph_int_t point_count, igraph_int_t dimensions, igraph_int_t neighbors, igraph_real_t cutoff) {
igraph_matrix_t points;
igraph_t g;
char msg[200];
const char *metricname;
igraph_matrix_init(&points, point_count, dimensions);
for (igraph_int_t point = 0; point < point_count; point++) {
for (igraph_int_t dim = 0; dim < dimensions; dim++) {
MATRIX(points, point, dim) = RNG_UNIF01();
}
}
switch (metric) {
case IGRAPH_METRIC_L2: metricname = "L2"; break;
case IGRAPH_METRIC_L1: metricname = "L1"; break;
}
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s RKNN with %s, %dD, n=%6" IGRAPH_PRId ", k=%2d, r=%g",
message, metricname, (int) dimensions, point_count, (int) neighbors, cutoff);
BENCH(msg, igraph_nearest_neighbor_graph(&g, &points, metric, neighbors, cutoff, false));
igraph_destroy(&g);
igraph_matrix_destroy(&points);
}
int main(void) {
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 20250728);
bench_pointcloud(" 1", IGRAPH_METRIC_L2, 100000, 1, 10, 0.1);
bench_pointcloud(" 2", IGRAPH_METRIC_L2, 100000, 2, 10, 0.1);
bench_pointcloud(" 3", IGRAPH_METRIC_L2, 100000, 3, 10, 0.1);
bench_pointcloud(" 4", IGRAPH_METRIC_L2, 100000, 4, 10, 0.1);
bench_pointcloud(" 5", IGRAPH_METRIC_L2, 10000, 1, -1, 0.001);
bench_pointcloud(" 6", IGRAPH_METRIC_L2, 10000, 2, -1, 0.01);
bench_pointcloud(" 7", IGRAPH_METRIC_L2, 10000, 3, -1, 0.01);
bench_pointcloud(" 8", IGRAPH_METRIC_L2, 10000, 4, -1, 0.1);
bench_pointcloud(" 9", IGRAPH_METRIC_L2, 1000, 1, -1, -1);
bench_pointcloud("10", IGRAPH_METRIC_L2, 1000, 2, -1, -1);
bench_pointcloud("11", IGRAPH_METRIC_L2, 1000, 3, -1, -1);
bench_pointcloud("12", IGRAPH_METRIC_L2, 1000, 4, -1, -1);
bench_pointcloud("13", IGRAPH_METRIC_L2, 100000, 1, 10, -1);
bench_pointcloud("14", IGRAPH_METRIC_L2, 100000, 2, 10, -1);
bench_pointcloud("15", IGRAPH_METRIC_L2, 100000, 3, 10, -1);
bench_pointcloud("16", IGRAPH_METRIC_L2, 100000, 4, 10, -1);
return 0;
}
@@ -0,0 +1,473 @@
/*
igraph library.
Copyright (C) 2021-2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
typedef struct igraph_lazy_adjlist2_t {
const igraph_t *graph;
igraph_int_t length;
igraph_int_t data_length;
igraph_vector_int_t *adjs;
igraph_int_t *data;
igraph_int_t next_data;
igraph_neimode_t mode;
igraph_loops_t loops;
igraph_bool_t multiple;
} igraph_lazy_adjlist2_t;
igraph_error_t igraph_lazy_adjlist2_init(const igraph_t *graph,
igraph_lazy_adjlist2_t *al,
igraph_neimode_t mode,
igraph_loops_t loops,
igraph_bool_t multiple) {
if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
IGRAPH_ERROR("Cannor create lazy adjacency list view", IGRAPH_EINVMODE);
}
if (!igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
al->mode = mode;
al->loops = loops;
al->multiple = multiple;
al->graph = graph;
al->length = igraph_vcount(graph);
al->data_length = igraph_ecount(graph) * 2;
al->adjs = IGRAPH_CALLOC(al->length, igraph_vector_int_t);
al->data = IGRAPH_CALLOC(al->data_length, igraph_int_t);
al->next_data = 0;
if (al->adjs == NULL || al->data == NULL) {
IGRAPH_ERROR("Cannot create lazy adjacency list view", IGRAPH_ENOMEM);
}
return IGRAPH_SUCCESS;
}
void igraph_lazy_adjlist2_destroy(igraph_lazy_adjlist2_t *al) {
IGRAPH_FREE(al->adjs);
IGRAPH_FREE(al->data);
}
igraph_vector_int_t *igraph_i_lazy_adjlist2_get_real(
igraph_lazy_adjlist2_t *al, igraph_int_t pno
) {
igraph_int_t no = pno;
igraph_error_t ret;
if (al->adjs[no].stor_begin == NULL) {
al->adjs[no] = igraph_vector_int_view(al->data + al->next_data, al->data_length - al->next_data);
/* igraph_neighbors calls a resize. Since we're handling our own
* vectors, we can't have our stor_begin be realloced. A realloc should only
* happen when the vector is too small to handle the neighbors, which
* should never happen, because the stor_end is set to one past the
* end of the latest integer.
*/
ret = igraph_neighbors(al->graph, &al->adjs[no], no, al->mode, al->loops, al->multiple);
if (ret != IGRAPH_SUCCESS) {
igraph_error("", IGRAPH_FILE_BASENAME, __LINE__, ret);
return NULL;
}
al->next_data += igraph_vector_int_size(&(al->adjs[no]));
}
return &al->adjs[no];
}
igraph_error_t igraph_neighborhood_adjl2(const igraph_t *graph, igraph_vector_int_list_t *res,
igraph_vs_t vids, igraph_int_t order,
igraph_neimode_t mode, igraph_int_t mindist) {
igraph_int_t no_of_nodes = igraph_vcount(graph);
igraph_dqueue_int_t q;
igraph_vit_t vit;
igraph_int_t i, j;
igraph_int_t *added;
igraph_vector_int_t *neis;
igraph_vector_int_t tmp;
igraph_lazy_adjlist2_t adjlist2;
if (order < 0) {
IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
}
if (mindist < 0 || mindist > order) {
IGRAPH_ERROR("Minimum distance should be between zero and order",
IGRAPH_EINVAL);
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t);
if (added == 0) {
IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, added);
IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100);
IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
IGRAPH_FINALLY(igraph_vit_destroy, &vit);
IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0);
IGRAPH_CHECK(igraph_vector_int_list_reserve(res, IGRAPH_VIT_SIZE(vit)));
igraph_vector_int_list_clear(res);
if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) {
IGRAPH_CHECK(igraph_lazy_adjlist2_init(graph, &adjlist2, mode, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE));
} else {
IGRAPH_CHECK(igraph_lazy_adjlist2_init(graph, &adjlist2, mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE));
}
IGRAPH_FINALLY(igraph_lazy_adjlist2_destroy, &adjlist2);
for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
igraph_int_t node = IGRAPH_VIT_GET(vit);
added[node] = i + 1;
igraph_vector_int_clear(&tmp);
if (mindist == 0) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, node));
}
if (order > 0) {
IGRAPH_CHECK(igraph_dqueue_int_push(&q, node));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0));
}
while (!igraph_dqueue_int_empty(&q)) {
igraph_int_t actnode = igraph_dqueue_int_pop(&q);
igraph_int_t actdist = igraph_dqueue_int_pop(&q);
igraph_int_t n;
neis = igraph_i_lazy_adjlist2_get_real(&adjlist2, actnode);
n = igraph_vector_int_size(neis);
if (actdist < order - 1) {
/* we add them to the q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, actdist + 1));
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
} else {
/* we just count them but don't add them to q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
}
} /* while q not empty */
IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &tmp));
}
igraph_lazy_adjlist2_destroy(&adjlist2);
igraph_vector_int_destroy(&tmp);
igraph_vit_destroy(&vit);
igraph_dqueue_int_destroy(&q);
IGRAPH_FREE(added);
IGRAPH_FINALLY_CLEAN(5);
return IGRAPH_SUCCESS;
}
igraph_error_t igraph_neighborhood_adjl(const igraph_t *graph, igraph_vector_int_list_t *res,
igraph_vs_t vids, igraph_int_t order,
igraph_neimode_t mode, igraph_int_t mindist) {
igraph_int_t no_of_nodes = igraph_vcount(graph);
igraph_dqueue_int_t q;
igraph_vit_t vit;
igraph_int_t i, j;
igraph_int_t *added;
igraph_vector_int_t *neis;
igraph_vector_int_t tmp;
igraph_lazy_adjlist_t adjlist;
if (order < 0) {
IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
}
if (mindist < 0 || mindist > order) {
IGRAPH_ERROR("Minimum distance should be between zero and order",
IGRAPH_EINVAL);
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t);
if (added == 0) {
IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, added);
IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100);
IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
IGRAPH_FINALLY(igraph_vit_destroy, &vit);
IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0);
IGRAPH_CHECK(igraph_vector_int_list_reserve(res, IGRAPH_VIT_SIZE(vit)));
igraph_vector_int_list_clear(res);
if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) {
IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE));
} else {
IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE));
}
IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist);
for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
igraph_int_t node = IGRAPH_VIT_GET(vit);
added[node] = i + 1;
igraph_vector_int_clear(&tmp);
if (mindist == 0) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, node));
}
if (order > 0) {
IGRAPH_CHECK(igraph_dqueue_int_push(&q, node));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0));
}
while (!igraph_dqueue_int_empty(&q)) {
igraph_int_t actnode = igraph_dqueue_int_pop(&q);
igraph_int_t actdist = igraph_dqueue_int_pop(&q);
igraph_int_t n;
neis = igraph_lazy_adjlist_get(&adjlist, actnode);
n = igraph_vector_int_size(neis);
if (actdist < order - 1) {
/* we add them to the q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, actdist + 1));
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
} else {
/* we just count them but don't add them to q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
}
} /* while q not empty */
IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &tmp));
}
igraph_lazy_adjlist_destroy(&adjlist);
igraph_vector_int_destroy(&tmp);
igraph_vit_destroy(&vit);
igraph_dqueue_int_destroy(&q);
IGRAPH_FREE(added);
IGRAPH_FINALLY_CLEAN(5);
return IGRAPH_SUCCESS;
}
igraph_error_t igraph_neighborhood_adj(const igraph_t *graph, igraph_vector_int_list_t *res,
igraph_vs_t vids, igraph_int_t order,
igraph_neimode_t mode, igraph_int_t mindist) {
igraph_int_t no_of_nodes = igraph_vcount(graph);
igraph_dqueue_int_t q;
igraph_vit_t vit;
igraph_int_t i, j;
igraph_int_t *added;
igraph_vector_int_t *neis;
igraph_vector_int_t tmp;
igraph_adjlist_t adjlist;
if (order < 0) {
IGRAPH_ERROR("Negative order in neighborhood size", IGRAPH_EINVAL);
}
if (mindist < 0 || mindist > order) {
IGRAPH_ERROR("Minimum distance should be between zero and order",
IGRAPH_EINVAL);
}
added = IGRAPH_CALLOC(no_of_nodes, igraph_int_t);
if (added == 0) {
IGRAPH_ERROR("Cannot calculate neighborhood size", IGRAPH_ENOMEM);
}
IGRAPH_FINALLY(igraph_free, added);
IGRAPH_DQUEUE_INT_INIT_FINALLY(&q, 100);
IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
IGRAPH_FINALLY(igraph_vit_destroy, &vit);
IGRAPH_VECTOR_INT_INIT_FINALLY(&tmp, 0);
IGRAPH_CHECK(igraph_vector_int_list_reserve(res, IGRAPH_VIT_SIZE(vit)));
igraph_vector_int_list_clear(res);
if (!igraph_is_directed(graph) || mode == IGRAPH_ALL) {
IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE));
} else {
IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, mode, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE));
}
IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
for (i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
igraph_int_t node = IGRAPH_VIT_GET(vit);
added[node] = i + 1;
igraph_vector_int_clear(&tmp);
if (mindist == 0) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, node));
}
if (order > 0) {
IGRAPH_CHECK(igraph_dqueue_int_push(&q, node));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, 0));
}
while (!igraph_dqueue_int_empty(&q)) {
igraph_int_t actnode = igraph_dqueue_int_pop(&q);
igraph_int_t actdist = igraph_dqueue_int_pop(&q);
igraph_int_t n;
neis = igraph_adjlist_get(&adjlist, actnode);
n = igraph_vector_int_size(neis);
if (actdist < order - 1) {
/* we add them to the q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
IGRAPH_CHECK(igraph_dqueue_int_push(&q, nei));
IGRAPH_CHECK(igraph_dqueue_int_push(&q, actdist + 1));
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
} else {
/* we just count them but don't add them to q */
for (j = 0; j < n; j++) {
igraph_int_t nei = VECTOR(*neis)[j];
if (added[nei] != i + 1) {
added[nei] = i + 1;
if (actdist + 1 >= mindist) {
IGRAPH_CHECK(igraph_vector_int_push_back(&tmp, nei));
}
}
}
}
} /* while q not empty */
IGRAPH_CHECK(igraph_vector_int_list_push_back_copy(res, &tmp));
}
igraph_adjlist_destroy(&adjlist);
igraph_vector_int_destroy(&tmp);
igraph_vit_destroy(&vit);
igraph_dqueue_int_destroy(&q);
IGRAPH_FREE(added);
IGRAPH_FINALLY_CLEAN(5);
return IGRAPH_SUCCESS;
}
void do_benchmark(igraph_t *g, igraph_vs_t vids, igraph_int_t repeat)
{
igraph_vector_int_list_t result_orig;
igraph_vector_int_list_t result_adj;
igraph_vector_int_list_t result_adjl;
igraph_vector_int_list_t result_adjl2;
igraph_vector_int_list_init(&result_orig, 0);
igraph_vector_int_list_init(&result_adj, 0);
igraph_vector_int_list_init(&result_adjl, 0);
igraph_vector_int_list_init(&result_adjl2, 0);
for (igraph_int_t order = 1; order <= 3; order++) {
printf("order %" IGRAPH_PRId ":\n", order);
BENCH("Original function:",
REPEAT(igraph_neighborhood(g, &result_orig, vids, order,
/*mode*/ IGRAPH_ALL, /*mindist*/ 0), repeat));
BENCH("Using a lazy adjlist:",
REPEAT(igraph_neighborhood_adjl(g, &result_adjl, vids, order,
/*mode*/ IGRAPH_ALL, /*mindist*/ 0), repeat));
BENCH("Using lazy adjlist 2:",
REPEAT(igraph_neighborhood_adjl2(g, &result_adjl2, vids, order,
/*mode*/ IGRAPH_ALL, /*mindist*/ 0), repeat));
BENCH("Using adjlist:",
REPEAT(igraph_neighborhood_adj(g, &result_adj, vids, order,
/*mode*/ IGRAPH_ALL, /*mindist*/ 0), repeat));
for (igraph_int_t i = 0; i <= order; i++) {
IGRAPH_ASSERT(!igraph_vector_int_lex_cmp(&VECTOR(result_orig)[i], &VECTOR(result_adj)[i]));
IGRAPH_ASSERT(!igraph_vector_int_lex_cmp(&VECTOR(result_adj)[i], &VECTOR(result_adjl)[i]));
IGRAPH_ASSERT(!igraph_vector_int_lex_cmp(&VECTOR(result_adjl)[i], &VECTOR(result_adjl2)[i]));
}
}
igraph_vector_int_list_destroy(&result_orig);
igraph_vector_int_list_destroy(&result_adj);
igraph_vector_int_list_destroy(&result_adjl);
igraph_vector_int_list_destroy(&result_adjl2);
}
int main(void) {
igraph_t g_full, g_ring, g_er;
igraph_vs_t vids_all, vids_50, vids_5000, vids_200;
igraph_vs_all(&vids_all);
igraph_vs_range(&vids_50, 0, 50);
igraph_vs_range(&vids_5000, 0, 5000);
igraph_vs_range(&vids_200, 0, 200);
igraph_full(&g_full, 500, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_ring(&g_ring, 50000, IGRAPH_UNDIRECTED, /* mutual */ 0, /*circular*/ 0);
igraph_erdos_renyi_game_gnm(&g_er, 2000, 20000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
printf("Select all vertices:\n\n");
printf("Full graph:\n");
do_benchmark(&g_full, vids_all, 10);
printf("\nRing graph:\n");
do_benchmark(&g_ring, vids_all, 40);
printf("\nRandom graph:\n");
do_benchmark(&g_er, vids_all, 15);
printf("\n\nSelect 10%% of vertices:\n\n");
printf("Full graph:\n");
do_benchmark(&g_full, vids_50, 100);
printf("\nRing graph:\n");
do_benchmark(&g_ring, vids_5000, 400);
printf("\nRandom graph:\n");
do_benchmark(&g_er, vids_200, 150);
igraph_destroy(&g_full);
igraph_destroy(&g_ring);
igraph_destroy(&g_er);
igraph_vs_destroy(&vids_all);
igraph_vs_destroy(&vids_50);
igraph_vs_destroy(&vids_5000);
igraph_vs_destroy(&vids_200);
}
@@ -0,0 +1,137 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t graph;
igraph_vector_t res;
igraph_arpack_options_t arpack_opts;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_arpack_options_init(&arpack_opts);
igraph_vector_init(&res, 0);
igraph_barabasi_game(&graph, 100000, 1, 4, NULL, 1, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
BENCH(" 1 PageRank, Barabasi n=100000 m=4, PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH(" 2 PageRank, Barabasi n=100000 m=4, ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_barabasi_game(&graph, 100000, 1, 10, NULL, 1, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
BENCH(" 3 PageRank, Barabasi n=100000 m=10, PRPACK, 5x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 5)
);
BENCH(" 4 PageRank, Barabasi n=100000 m=10, ARPACK, 5x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 5)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100, 1000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 5 PageRank, GNM(100,1000), PRPACK, 1000x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1000)
);
BENCH(" 6 PageRank, GNM(100,1000), ARPACK, 1000x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1000)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 200, 4000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 7 PageRank, GNM(200,4000), PRPACK, 1000x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1000)
);
BENCH(" 8 PageRank, GNM(200,4000), ARPACK, 1000x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1000)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 10000, 20000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH(" 9 PageRank, GNM(10000,20000), PRPACK, 100x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 100)
);
BENCH("10 PageRank, GNM(10000,20000), ARPACK, 100x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 100)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100000, 100000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH("11 PageRank, GNM(100000,100000), PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH("12 PageRank, GNM(100000,100000), ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100000, 500000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
BENCH("13 PageRank, GNM(100000,500000), PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH("14 PageRank, GNM(100000,500000), ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_kautz(&graph, 6, 6);
BENCH("13 PageRank, Kautz(6,6), PRPACK, 1x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1)
);
BENCH("14 PageRank, Kautz(6,6), ARPACK, 1x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1)
);
igraph_destroy(&graph);
igraph_de_bruijn(&graph, 7, 7);
BENCH("13 PageRank, DeBruijn(7,7), PRPACK, 1x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1)
);
BENCH("14 PageRank, DeBruijn(7,7), ARPACK, 1x",
REPEAT(igraph_pagerank(&graph, NULL, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1)
);
igraph_destroy(&graph);
igraph_vector_destroy(&res);
return 0;
}
@@ -0,0 +1,156 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void rand_weight_vec(igraph_vector_t *vec, const igraph_t *graph) {
igraph_int_t i, n = igraph_ecount(graph);
igraph_vector_resize(vec, n);
for (i=0; i < n; ++i) {
VECTOR(*vec)[i] = RNG_UNIF(1, 10);
}
}
int main(void) {
igraph_t graph;
igraph_vector_t res, weights;
igraph_arpack_options_t arpack_opts;
BENCH_INIT();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_arpack_options_init(&arpack_opts);
igraph_vector_init(&res, 0);
igraph_vector_init(&weights, 0);
igraph_barabasi_game(&graph, 100000, 1, 4, NULL, 1, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weight_vec(&weights, &graph);
BENCH(" 1 PageRank weighted, Barabasi n=100000 m=4, PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH(" 2 PageRank weighted, Barabasi n=100000 m=4, ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_barabasi_game(&graph, 100000, 1, 10, NULL, 1, 0, IGRAPH_DIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weight_vec(&weights, &graph);
BENCH(" 3 PageRank weighted, Barabasi n=100000 m=10, PRPACK, 5x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 5)
);
BENCH(" 4 PageRank weighted, Barabasi n=100000 m=10, ARPACK, 5x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 5)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100, 1000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
rand_weight_vec(&weights, &graph);
BENCH(" 5 PageRank weighted, GNM(100,1000), PRPACK, 1000x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1000)
);
BENCH(" 6 PageRank weighted, GNM(100,1000), ARPACK, 1000x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1000)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 200, 4000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
rand_weight_vec(&weights, &graph);
BENCH(" 7 PageRank weighted, GNM(200,4000), PRPACK, 1000x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1000)
);
BENCH(" 8 PageRank weighted, GNM(200,4000), ARPACK, 1000x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1000)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 10000, 20000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
rand_weight_vec(&weights, &graph);
BENCH(" 9 PageRank weighted, GNM(10000,20000), PRPACK, 100x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 100)
);
BENCH("10 PageRank weighted, GNM(10000,20000), ARPACK, 100x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 100)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100000, 100000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
rand_weight_vec(&weights, &graph);
BENCH("11 PageRank weighted, GNM(100000,100000), PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH("12 PageRank weighted, GNM(100000,100000), ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnm(&graph, 100000, 500000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
rand_weight_vec(&weights, &graph);
BENCH("13 PageRank weighted, GNM(100000,500000), PRPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 10)
);
BENCH("14 PageRank weighted, GNM(100000,500000), ARPACK, 10x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 10)
);
igraph_destroy(&graph);
igraph_kautz(&graph, 6, 6);
rand_weight_vec(&weights, &graph);
BENCH("13 PageRank weighted, Kautz(6,6), PRPACK, 1x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1)
);
BENCH("14 PageRank weighted, Kautz(6,6), ARPACK, 1x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1)
);
igraph_destroy(&graph);
igraph_de_bruijn(&graph, 7, 7);
rand_weight_vec(&weights, &graph);
BENCH("13 PageRank weighted, DeBruijn(7,7), PRPACK, 1x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_PRPACK, NULL), 1)
);
BENCH("14 PageRank weighted, DeBruijn(7,7), ARPACK, 1x",
REPEAT(igraph_pagerank(&graph, &weights, &res, NULL, 0.85, IGRAPH_DIRECTED, igraph_vss_all(),
IGRAPH_PAGERANK_ALGO_ARPACK, &arpack_opts), 1)
);
igraph_destroy(&graph);
igraph_vector_destroy(&weights);
igraph_vector_destroy(&res);
return 0;
}
@@ -0,0 +1,168 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <plfit_sampling.h>
#include "bench.h"
igraph_vector_t data;
double rpareto(double xmin, double alpha) {
/* 1-u is used in the base here because we want to avoid the case of
* sampling zero */
return pow(1 - RNG_UNIF01(), -1.0 / alpha) * xmin;
}
double rzeta(igraph_int_t xmin, double alpha) {
double u, v, t;
igraph_int_t x;
double alpha_minus_1 = alpha-1;
double minus_1_over_alpha_minus_1 = -1.0 / (alpha-1);
double b;
double one_over_b_minus_1;
xmin = (igraph_int_t) round(xmin);
/* Rejection sampling for the win. We use Y=floor(U^{-1/alpha} * xmin) as the
* envelope distribution, similarly to Chapter X.6 of Luc Devroye's book
* (where xmin is assumed to be 1): http://luc.devroye.org/chapter_ten.pdf
*
* Some notes that should help me recover what I was doing:
*
* p_i = 1/zeta(alpha, xmin) * i^-alpha
* q_i = (xmin/i)^{alpha-1} - (xmin/(i+1))^{alpha-1}
* = (i/xmin)^{1-alpha} - ((i+1)/xmin)^{1-alpha}
* = [i^{1-alpha} - (i+1)^{1-alpha}] / xmin^{1-alpha}
*
* p_i / q_i attains its maximum at xmin=i, so the rejection constant is:
*
* c = p_xmin / q_xmin
*
* We have to accept the sample if V <= (p_i / q_i) * (q_xmin / p_xmin) =
* (i/xmin)^-alpha * [xmin^{1-alpha} - (xmin+1)^{1-alpha}] / [i^{1-alpha} - (i+1)^{1-alpha}] =
* [xmin - xmin^alpha / (xmin+1)^{alpha-1}] / [i - i^alpha / (i+1)^{alpha-1}] =
* xmin/i * [1-(xmin/(xmin+1))^{alpha-1}]/[1-(i/(i+1))^{alpha-1}]
*
* In other words (and substituting i with X, which is the same),
*
* V * (X/xmin) <= [1 - (1+1/xmin)^{1-alpha}] / [1 - (1+1/i)^{1-alpha}]
*
* Let b := (1+1/xmin)^{alpha-1} and let T := (1+1/i)^{alpha-1}. Then:
*
* V * (X/xmin) <= [(b-1)/b] / [(T-1)/T]
* V * (X/xmin) * (T-1) / (b-1) <= T / b
*
* which is the same as in Devroye's book, except for the X/xmin term, and
* the definition of b.
*/
b = pow(1 + 1.0/xmin, alpha_minus_1);
one_over_b_minus_1 = 1.0/(b-1);
do {
do {
u = RNG_UNIF01();
v = RNG_UNIF01();
/* 1-u is used in the base here because we want to avoid the case of
* having zero in x */
x = (igraph_int_t) floor(pow(1-u, minus_1_over_alpha_minus_1) * xmin);
} while (x < xmin);
t = pow((x+1.0)/x, alpha_minus_1);
} while (v*x*(t-1)*one_over_b_minus_1*b > t*xmin);
return x;
}
int generate_continuous(double xmin, double alpha, size_t num_samples) {
IGRAPH_CHECK(igraph_vector_resize(&data, num_samples));
for (size_t i = 0; i < num_samples; i++) {
VECTOR(data)[i] = rpareto(xmin, alpha);
}
return IGRAPH_SUCCESS;
}
int generate_discrete(double xmin, double alpha, size_t num_samples) {
IGRAPH_CHECK(igraph_vector_resize(&data, num_samples));
for (size_t i = 0; i < num_samples; i++) {
VECTOR(data)[i] = rzeta(xmin, alpha);
}
return IGRAPH_SUCCESS;
}
int fit_continuous(double known_xmin) {
igraph_plfit_result_t result;
IGRAPH_CHECK(igraph_power_law_fit(&data, &result, known_xmin, /* force_continuous = */ 1));
return IGRAPH_SUCCESS;
}
int fit_discrete(double known_xmin) {
igraph_plfit_result_t result;
IGRAPH_CHECK(igraph_power_law_fit(&data, &result, known_xmin, 0));
return IGRAPH_SUCCESS;
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_init(&data, 0);
BENCH_INIT();
generate_continuous(1, 3, 100000);
BENCH(" 1 Continuous, xmin = 1, alpha = 3, samples = 100K, fitting alpha only", fit_continuous(1));
generate_continuous(1, 3, 200000);
BENCH(" 2 Continuous, xmin = 1, alpha = 3, samples = 200K, fitting alpha only", fit_continuous(1));
generate_continuous(1, 3, 500000);
BENCH(" 3 Continuous, xmin = 1, alpha = 3, samples = 500K, fitting alpha only", fit_continuous(1));
generate_continuous(1, 3, 5000);
BENCH(" 4 Continuous, xmin = 1, alpha = 3, samples = 5K, fitting xmin and alpha", fit_continuous(-1));
generate_continuous(1, 3, 10000);
BENCH(" 5 Continuous, xmin = 1, alpha = 3, samples = 10K, fitting xmin and alpha", fit_continuous(-1));
generate_continuous(1, 3, 15000);
BENCH(" 6 Continuous, xmin = 1, alpha = 3, samples = 15K, fitting xmin and alpha", fit_continuous(-1));
generate_discrete(3, 3, 1000000);
BENCH(" 7 Discrete, xmin = 3, alpha = 3, samples = 1M, fitting alpha only", fit_discrete(3));
generate_discrete(3, 3, 5000000);
BENCH(" 8 Discrete, xmin = 3, alpha = 3, samples = 5M, fitting alpha only", fit_discrete(3));
generate_discrete(3, 3, 10000000);
BENCH(" 9 Discrete, xmin = 3, alpha = 3, samples = 10M, fitting alpha only", fit_discrete(3));
generate_discrete(3, 3, 1000000);
BENCH("10 Discrete, xmin = 3, alpha = 3, samples = 1M, fitting xmin and alpha", fit_discrete(-1));
generate_discrete(3, 3, 5000000);
BENCH("11 Discrete, xmin = 3, alpha = 3, samples = 5M, fitting xmin and alpha", fit_discrete(-1));
generate_discrete(3, 3, 10000000);
BENCH("12 Discrete, xmin = 3, alpha = 3, samples = 10M, fitting xmin and alpha", fit_discrete(-1));
igraph_vector_destroy(&data);
return 0;
}
@@ -0,0 +1,63 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
/* This program benchmarks igraph_qsort() indirectly through vector_sort() */
int main(void) {
igraph_vector_int_t vec;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_int_init(&vec, 0);
#define N 10000000
igraph_vector_int_resize(&vec, N);
for (igraph_int_t i=0; i < N; i++) {
VECTOR(vec)[i] = RNG_INTEGER(0, N-1);
}
BENCH("Sort vector of length " IGRAPH_I_STRINGIFY(N), igraph_vector_int_sort(&vec));
#undef N
#define N 1000000
igraph_vector_int_resize(&vec, N);
for (igraph_int_t i=0; i < N; i++) {
VECTOR(vec)[i] = RNG_INTEGER(0, N-1);
}
BENCH("Sort vector of length " IGRAPH_I_STRINGIFY(N), igraph_vector_int_sort(&vec));
#undef N
#define N 100000
igraph_vector_int_resize(&vec, N);
for (igraph_int_t i=0; i < N; i++) {
VECTOR(vec)[i] = RNG_INTEGER(0, N-1);
}
BENCH("Sort vector of length " IGRAPH_I_STRINGIFY(N), igraph_vector_int_sort(&vec));
igraph_vector_int_destroy(&vec);
return 0;
}
@@ -0,0 +1,201 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t graph;
igraph_vector_int_t vertices;
igraph_vector_int_t edges;
igraph_vector_t weights;
igraph_int_t ec, i;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_int_init(&vertices, 0);
igraph_vector_int_init(&edges, 0);
igraph_vector_init(&weights, 0);
/* create a small graph, and a compatible weight vector */
igraph_de_bruijn(&graph, 3, 2); /* 9 vertices, 27 edges, average degree: 6 */
ec = igraph_ecount(&graph);
igraph_vector_resize(&weights, ec);
for (i = 0; i < ec; ++i) {
VECTOR(weights)[i] = igraph_rng_get_unif01(igraph_rng_default());
}
/* Only edges */
BENCH(" 1 Random edge walk, directed, unweighted, small graph ",
igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 2 Random edge walk, directed, weighted, small graph ",
igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 3 Random edge walk, undirected, unweighted, small graph ",
igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 4 Random edge walk, undirected, weighted, small graph ",
igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
/* Only vertices */
BENCH(" 5 Random vertex walk, directed, unweighted, small graph ",
igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 6 Random vertex walk, directed, weighted, small graph ",
igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 7 Random vertex walk, undirected, unweighted, small graph ",
igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 8 Random vertex walk, undirected, weighted, small graph ",
igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
/* Both edges and vertices */
BENCH(" 9 Random walk, directed, unweighted, small graph ",
igraph_random_walk(&graph, NULL, &vertices, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 10 Random walk, directed, weighted, small graph ",
igraph_random_walk(&graph, &weights, &vertices, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
igraph_destroy(&graph);
/* create a big graph, and a compatible weight vector */
igraph_de_bruijn(&graph, 8, 5); /* 32768 vertices, 262144 edges, average degree: 16 */
ec = igraph_ecount(&graph);
igraph_vector_resize(&weights, ec);
for (i = 0; i < ec; ++i) {
VECTOR(weights)[i] = igraph_rng_get_unif01(igraph_rng_default());
}
/* Only edges */
BENCH(" 11 Random edge walk, directed, unweighted, large graph ",
igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 12 Random edge walk, directed, weighted, large graph ",
igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 13 Random edge walk, undirected, unweighted, large graph ",
igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 14 Random edge walk, undirected, weighted, large graph ",
igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
/* Only vertices */
BENCH(" 15 Random vertex walk, directed, unweighted, large graph ",
igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 16 Random vertex walk, directed, weighted, large graph ",
igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 17 Random vertex walk, undirected, unweighted, large graph ",
igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 18 Random vertex walk, undirected, weighted, large graph ",
igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_ALL, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
/* Both edges and vertices */
BENCH(" 19 Random walk, directed, unweighted, large graph ",
igraph_random_walk(&graph, NULL, &vertices, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
BENCH(" 20 Random walk, directed, weighted, large graph ",
igraph_random_walk(&graph, &weights, &vertices, &edges, 0, IGRAPH_OUT, 50000000, IGRAPH_RANDOM_WALK_STUCK_RETURN)
);
/* Only edges */
BENCH(" 21 Short edge walk, directed, unweighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 22 Short edge walk, directed, weighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 23 Short edge walk, undirected, unweighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, NULL, NULL, &edges, 0, IGRAPH_ALL, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 24 Short edge walk, undirected, weighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, &weights, NULL, &edges, 0, IGRAPH_ALL, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
/* Only vertices */
BENCH(" 25 Short vertex walk, directed, unweighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 26 Short vertex walk, directed, weighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 27 Short vertex walk, undirected, unweighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, NULL, &vertices, NULL, 0, IGRAPH_ALL, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 28 Short vertex walk, undirected, weighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, &weights, &vertices, NULL, 0, IGRAPH_ALL, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
/* Both edges and vertices */
BENCH(" 29 Short random walk, directed, unweighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, NULL, &vertices, &edges, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
BENCH(" 30 Short random walk, directed, weighted, large graph, x 100",
REPEAT(igraph_random_walk(&graph, &weights, &vertices, &edges, 0, IGRAPH_OUT, 10000, IGRAPH_RANDOM_WALK_STUCK_RETURN), 100)
);
igraph_destroy(&graph);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&vertices);
igraph_vector_int_destroy(&edges);
return 0;
}
@@ -0,0 +1,85 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
void bench(const igraph_t *graph, const char *what, int rep) {
const igraph_int_t vcount = igraph_vcount(graph);
const igraph_int_t ecount = igraph_ecount(graph);
igraph_vector_int_t degrees;
igraph_t new_graph;
igraph_vector_int_init(&degrees, 0);
igraph_degree(graph, &degrees, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
char name[200];
sprintf(name, "%s, n=%5" IGRAPH_PRId ", m=%5" IGRAPH_PRId ", LARGEST, %dx", what, vcount, ecount, rep);
BENCH(name, REPEAT(igraph_realize_degree_sequence(&new_graph, &degrees, NULL, IGRAPH_SIMPLE_SW, IGRAPH_REALIZE_DEGSEQ_LARGEST), rep));
igraph_destroy(&new_graph);
sprintf(name, "%s, n=%5" IGRAPH_PRId ", m=%5" IGRAPH_PRId ", SMALLEST, %dx", what, vcount, ecount, rep);
BENCH(name, REPEAT(igraph_realize_degree_sequence(&new_graph, &degrees, NULL, IGRAPH_SIMPLE_SW, IGRAPH_REALIZE_DEGSEQ_SMALLEST), rep));
igraph_destroy(&new_graph);
sprintf(name, "%s, n=%5" IGRAPH_PRId ", m=%5" IGRAPH_PRId ", INDEX, %dx", what, vcount, ecount, rep);
BENCH(name, REPEAT(igraph_realize_degree_sequence(&new_graph, &degrees, NULL, IGRAPH_SIMPLE_SW, IGRAPH_REALIZE_DEGSEQ_INDEX), rep));
igraph_destroy(&new_graph);
printf("\n");
igraph_vector_int_destroy(&degrees);
}
void bench_gnm(igraph_int_t n, igraph_int_t m, int rep) {
igraph_t graph;
igraph_erdos_renyi_game_gnm(&graph, n, m, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
bench(&graph, "G(n,m)", rep);
igraph_destroy(&graph);
}
void bench_ba(igraph_int_t n, igraph_int_t m, int rep) {
igraph_t graph;
igraph_barabasi_game(&graph, n, 1, m, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE, NULL);
bench(&graph, "BA", rep);
igraph_destroy(&graph);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 789);
BENCH_INIT();
bench_gnm(100, 200, 10000);
bench_gnm(100, 1000, 10000);
bench_gnm(10000, 20000, 1);
bench_gnm(10000, 100000, 1);
bench_ba(100, 1, 10000);
bench_ba(100, 10, 10000);
bench_ba(10000, 1, 1);
bench_ba(10000, 10, 1);
return 0;
}
@@ -0,0 +1,77 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void bench(const char *name, igraph_t *graph, int rep) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_int_t ecount = igraph_ecount(graph);
igraph_int_t trials = 10*ecount;
char msg[200];
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s, |V|=%6" IGRAPH_PRId ", |E|=%6" IGRAPH_PRId ", %6" IGRAPH_PRId " swaps, %dx",
name, vcount, ecount, trials, rep);
BENCH(msg, REPEAT(igraph_rewire(graph, trials, IGRAPH_SIMPLE_SW, NULL), rep));
}
void bench_er(igraph_int_t n, igraph_int_t m, int rep) {
igraph_t graph;
igraph_erdos_renyi_game_gnm(&graph, n, m, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
bench("G(n,m)", &graph, rep);
igraph_destroy(&graph);
}
void bench_ba(igraph_int_t n, igraph_int_t m, int rep) {
igraph_t graph;
igraph_barabasi_game(&graph, n, 1, m ,NULL, true, 1, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_BAG, NULL);
bench("BA", &graph, rep);
igraph_destroy(&graph);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
bench_er(100, 3000, 100);
bench_er(300, 3000, 100);
bench_er(1000, 3000, 100);
bench_er(3000, 3000, 100);
bench_er(10000, 3000, 100);
printf("\n");
bench_er(300, 30000, 10);
bench_er(1000, 30000, 10);
bench_er(3000, 30000, 10);
bench_er(10000, 30000, 10);
printf("\n");
bench_ba(1000, 3, 100);
bench_ba(10000, 3, 10);
bench_ba(100000, 3, 1);
return 0;
}
@@ -0,0 +1,145 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
void rand_weight_vec(igraph_vector_t *vec, const igraph_t *graph) {
igraph_int_t i, n = igraph_ecount(graph);
igraph_vector_resize(vec, n);
for (i=0; i < n; ++i) {
VECTOR(*vec)[i] = RNG_UNIF(1, 10);
}
}
int main(void) {
igraph_t g;
igraph_vector_t strength, weights;
igraph_rng_seed(igraph_rng_default(), 54);
BENCH_INIT();
igraph_vector_init(&strength, 0);
igraph_vector_init(&weights, 0);
/* igraph_strength() uses an optimized, cache friendly code path when given
* a vertex selector for which igraph_vs_is_all() returns true (this is
* currently igraph_vs_all()). We pass both igraph_vss_all() and
* igraph_vss_range(0, igraph_vcount(graph)) as vertex selectors
* to compare the performance of the two code paths.
*
* NOTE: While currently igraph_vs_is_all() does not return true for
* a range-type vertex selector, this may change in the future.
* An altrenative is to to use igraph_vs_vector(), with the vector
* initialized to a range.
*/
#define N 1000
#define M 10
#define REP 10000
igraph_barabasi_game(&g, N, 1, M, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
rand_weight_vec(&weights, &g);
BENCH(" 1a igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
BENCH(" 1b igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_range(0, igraph_vcount(&g)), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
printf("\n");
igraph_destroy(&g);
#undef N
#undef M
#undef REP
#define N 10000
#define M 10
#define REP 1000
igraph_barabasi_game(&g, N, 1, M, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
rand_weight_vec(&weights, &g);
BENCH(" 2a igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
BENCH(" 2b igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_range(0, igraph_vcount(&g)), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
printf("\n");
igraph_destroy(&g);
#undef N
#undef M
#undef REP
#define N 100000
#define M 10
#define REP 100
igraph_barabasi_game(&g, N, 1, M, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
rand_weight_vec(&weights, &g);
BENCH(" 3a igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
BENCH(" 3b igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_range(0, igraph_vcount(&g)), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
printf("\n");
igraph_destroy(&g);
#undef N
#undef M
#undef REP
#define N 100000
#define M 100
#define REP 10
igraph_barabasi_game(&g, N, 1, M, NULL, true, 0, IGRAPH_UNDIRECTED, IGRAPH_BARABASI_PSUMTREE_MULTIPLE, NULL);
rand_weight_vec(&weights, &g);
BENCH(" 4a igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
BENCH(" 4b igraph_strength(), preferential attachment n=" TOSTR(N) ", m=" TOSTR(M) ", " TOSTR(REP) "x",
REPEAT(igraph_strength(&g, &strength, igraph_vss_range(0, igraph_vcount(&g)), IGRAPH_ALL, IGRAPH_LOOPS, &weights), REP)
);
printf("\n");
igraph_destroy(&g);
#undef N
#undef M
#undef REP
igraph_vector_destroy(&weights);
igraph_vector_destroy(&strength);
return 0;
}
@@ -0,0 +1,252 @@
/*
igraph library.
Copyright (C) 2013-2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_vector_t trans;
igraph_vs_t all_vertices;
igraph_real_t avg_trans, global_trans, tri_count;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
#define N 6000
#define M 2000000
igraph_erdos_renyi_game_gnm(&g, N, M, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_init(&trans, igraph_vcount(&g));
igraph_vs_range(&all_vertices, 0, igraph_vcount(&g));
BENCH(" 1 Local transitivity, all vertices method, GNM",
igraph_transitivity_local_undirected(&g, &trans, igraph_vss_all(),
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 2 Local transitivity, subset method, GNM",
igraph_transitivity_local_undirected(&g, &trans, all_vertices,
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 3 Average local transitivity GNM",
igraph_transitivity_avglocal_undirected(&g, &avg_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 4 Global transitivity GNM",
igraph_transitivity_undirected(&g, &global_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 5 Count triangles per vertex, all vertices method, GNM",
igraph_count_adjacent_triangles(&g, &trans, igraph_vss_all());
);
BENCH(" 6 Count triangles per vertex, subset method, GNM",
igraph_count_adjacent_triangles(&g, &trans, all_vertices);
);
BENCH(" 7 Count all triangles, GNM",
igraph_count_triangles(&g, &tri_count);
);
igraph_vs_destroy(&all_vertices);
igraph_destroy(&g);
printf("\n");
igraph_barabasi_game(&g, N, /*power=*/ 1, M / N, /*outseq=*/ 0,
/*outpref=*/ 0, /*A=*/ 1, IGRAPH_UNDIRECTED,
IGRAPH_BARABASI_PSUMTREE, /*start_from=*/ 0);
igraph_vector_resize(&trans, igraph_vcount(&g));
igraph_vs_range(&all_vertices, 0, igraph_vcount(&g));
BENCH(" 1 Local transitivity, all vertices method, Barabasi",
igraph_transitivity_local_undirected(&g, &trans, igraph_vss_all(),
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 2 Local transitivity, subset method, Barabasi",
igraph_transitivity_local_undirected(&g, &trans, all_vertices,
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 3 Average local transitivity, Barabasi",
igraph_transitivity_avglocal_undirected(&g, &avg_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 4 Global transitivity, Barabasi",
igraph_transitivity_undirected(&g, &global_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 5 Count triangles per vertex, all vertices method, Barabasi",
igraph_count_adjacent_triangles(&g, &trans, igraph_vss_all());
);
BENCH(" 6 Count triangles per vertex, subset method, Barabasi",
igraph_count_adjacent_triangles(&g, &trans, all_vertices);
);
BENCH(" 7 Count all triangles, Barabasi",
igraph_count_triangles(&g, &tri_count);
);
igraph_vs_destroy(&all_vertices);
igraph_destroy(&g);
printf("\n");
#undef N
#undef M
#define N 1000000
#define M 10000000
igraph_erdos_renyi_game_gnm(&g, N, M, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_init(&trans, igraph_vcount(&g));
igraph_vs_range(&all_vertices, 0, igraph_vcount(&g));
BENCH(" 1 Local transitivity, all vertices method, large GNM",
igraph_transitivity_local_undirected(&g, &trans, igraph_vss_all(),
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 2 Local transitivity, subset method, large GNM",
igraph_transitivity_local_undirected(&g, &trans, all_vertices,
IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 3 Average local transitivity, large GNM",
igraph_transitivity_avglocal_undirected(&g, &avg_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 4 Global transitivity, large GNM",
igraph_transitivity_undirected(&g, &global_trans, IGRAPH_TRANSITIVITY_NAN);
);
BENCH(" 5 Count triangles per vertex, all vertices method, large GNM",
igraph_count_adjacent_triangles(&g, &trans, igraph_vss_all());
);
BENCH(" 6 Count triangles per vertex, subset method, large GNM",
igraph_count_adjacent_triangles(&g, &trans, all_vertices);
);
BENCH(" 7 Count all triangles, large GNM",
igraph_count_triangles(&g, &tri_count);
);
igraph_vs_destroy(&all_vertices);
igraph_destroy(&g);
printf("\n");
igraph_erdos_renyi_game_gnm(&g, 500, 2000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&trans, igraph_vcount(&g));
igraph_vs_range(&all_vertices, 0, igraph_vcount(&g));
#define REPS 1000
BENCH(" 1 Local transitivity, all vertices method, small GNM",
REPEAT(igraph_transitivity_local_undirected(&g, &trans, igraph_vss_all(),
IGRAPH_TRANSITIVITY_NAN), REPS);
);
BENCH(" 2 Local transitivity, subset method, small GNM",
REPEAT(igraph_transitivity_local_undirected(&g, &trans, all_vertices,
IGRAPH_TRANSITIVITY_NAN), REPS);
);
BENCH(" 3 Average local transitivity, small GNM",
REPEAT(igraph_transitivity_avglocal_undirected(&g, &avg_trans, IGRAPH_TRANSITIVITY_NAN),
REPS);
);
BENCH(" 4 Global transitivity, small GNM",
REPEAT(igraph_transitivity_undirected(&g, &global_trans, IGRAPH_TRANSITIVITY_NAN),
REPS);
);
BENCH(" 5 Count triangles per vertex, all vertices method, small GNM",
REPEAT(igraph_count_adjacent_triangles(&g, &trans, igraph_vss_all()), REPS);
);
BENCH(" 6 Count triangles per vertex, subset method, small GNM",
REPEAT(igraph_count_adjacent_triangles(&g, &trans, all_vertices), REPS);
);
BENCH(" 7 Count all triangles, small GNM",
REPEAT(igraph_count_triangles(&g, &tri_count), REPS);
);
igraph_vs_destroy(&all_vertices);
igraph_destroy(&g);
#undef REPS
printf("\n");
igraph_erdos_renyi_game_gnm(&g, 50, 300, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_resize(&trans, igraph_vcount(&g));
igraph_vs_range(&all_vertices, 0, igraph_vcount(&g));
#define REPS 10000
BENCH(" 1 Local transitivity, all vertices method, tiny GNM",
REPEAT(igraph_transitivity_local_undirected(&g, &trans, igraph_vss_all(),
IGRAPH_TRANSITIVITY_NAN), REPS);
);
BENCH(" 2 Local transitivity, subset method, tiny GNM",
REPEAT(igraph_transitivity_local_undirected(&g, &trans, all_vertices,
IGRAPH_TRANSITIVITY_NAN), REPS);
);
BENCH(" 3 Average local transitivity, tiny GNM",
REPEAT(igraph_transitivity_avglocal_undirected(&g, &avg_trans, IGRAPH_TRANSITIVITY_NAN),
REPS);
);
BENCH(" 4 Global transitivity, tiny GNM",
REPEAT(igraph_transitivity_undirected(&g, &global_trans, IGRAPH_TRANSITIVITY_NAN),
REPS);
);
BENCH(" 5 Count triangles per vertex, all vertices method, tiny GNM",
REPEAT(igraph_count_adjacent_triangles(&g, &trans, igraph_vss_all()), REPS);
);
BENCH(" 6 Count triangles per vertex, subset method, tiny GNM",
REPEAT(igraph_count_adjacent_triangles(&g, &trans, all_vertices), REPS);
);
BENCH(" 7 Count all triangles, tiny GNM",
REPEAT(igraph_count_triangles(&g, &tri_count), REPS);
);
igraph_vs_destroy(&all_vertices);
igraph_destroy(&g);
#undef REPS
igraph_vector_destroy(&trans);
return 0;
}
@@ -0,0 +1,104 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
void tree_game(igraph_int_t n, igraph_bool_t directed, igraph_random_tree_t method) {
igraph_t g;
igraph_tree_game(&g, n, directed, method);
igraph_destroy(&g);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
#define VCOUNT 100
#define REP 100000
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", Prufer, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_PRUFER), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", LERW, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_LERW), REP);
);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 1000
#define REP 10000
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", Prufer, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_PRUFER), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", LERW, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_LERW), REP);
);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 10000
#define REP 1000
BENCH(" 3 vcount=" TOSTR(VCOUNT) ", Prufer, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_PRUFER), REP);
);
BENCH(" 4 vcount=" TOSTR(VCOUNT) ", LERW, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_LERW), REP);
);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 100000
#define REP 100
BENCH(" 3 vcount=" TOSTR(VCOUNT) ", Prufer, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_PRUFER), REP);
);
BENCH(" 4 vcount=" TOSTR(VCOUNT) ", LERW, " TOSTR(REP) "x",
REPEAT(tree_game(VCOUNT, IGRAPH_UNDIRECTED, IGRAPH_RANDOM_TREE_LERW), REP);
);
#undef VCOUNT
#undef DENS
#undef REP
return 0;
}
@@ -0,0 +1,56 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
int main(void) {
igraph_t g;
igraph_int_t vconn;
igraph_rng_seed(igraph_rng_default(), 54);
BENCH_INIT();
igraph_grg_game(&g, 100, 0.2, /* torus = */ false, /* x = */ NULL, /* y = */ NULL);
BENCH(" 1 Vertex connectivity of geometric random graph, n=100, r=0.2",
igraph_vertex_connectivity(&g, &vconn, /* checks = */ false);
);
igraph_destroy(&g);
igraph_grg_game(&g, 200, 0.141, /* torus = */ false, /* x = */ NULL, /* y = */ NULL);
BENCH(" 2 Vertex connectivity of geometric random graph, n=200, r=0.141",
igraph_vertex_connectivity(&g, &vconn, /* checks = */ false);
);
igraph_destroy(&g);
igraph_grg_game(&g, 400, 0.1, /* torus = */ false, /* x = */ NULL, /* y = */ NULL);
BENCH(" 3 Vertex connectivity of geometric random graph, n=400, r=0.1",
igraph_vertex_connectivity(&g, &vconn, /* checks = */ false);
);
igraph_destroy(&g);
return 0;
}
@@ -0,0 +1,165 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
#define TOSTR1(x) #x
#define TOSTR(x) TOSTR1(x)
int main(void) {
igraph_t g;
igraph_vector_int_t membership;
igraph_vector_t distances;
igraph_vector_t weights;
igraph_vector_int_t generators;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_int_init(&membership, 0);
igraph_vector_init(&distances, 0);
igraph_vector_init(&weights, 0);
igraph_vector_int_init(&generators, 0);
#define VCOUNT 100
#define DENS 0.5
#define REP 1000
igraph_erdos_renyi_game_gnp(&g, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_int_resize(&membership, igraph_vcount(&g));
igraph_vector_resize(&distances, igraph_vcount(&g));
igraph_vector_resize(&weights, igraph_ecount(&g));
for (igraph_int_t i=0; i < igraph_ecount(&g); i++) {
VECTOR(weights)[i] = RNG_EXP(1);
}
igraph_random_sample(&generators, 0, igraph_vcount(&g)-1, 20);
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Unweighted, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, NULL, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Dijkstra, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, &weights, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
igraph_destroy(&g);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 500
#define DENS 0.1
#define REP 1000
igraph_erdos_renyi_game_gnp(&g, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_int_resize(&membership, igraph_vcount(&g));
igraph_vector_resize(&distances, igraph_vcount(&g));
igraph_vector_resize(&weights, igraph_ecount(&g));
for (igraph_int_t i=0; i < igraph_ecount(&g); i++) {
VECTOR(weights)[i] = RNG_EXP(1);
}
igraph_random_sample(&generators, 0, igraph_vcount(&g)-1, 20);
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Unweighted, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, NULL, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Dijkstra, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, &weights, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
igraph_destroy(&g);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 5000
#define DENS 0.01
#define REP 100
igraph_erdos_renyi_game_gnp(&g, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_int_resize(&membership, igraph_vcount(&g));
igraph_vector_resize(&distances, igraph_vcount(&g));
igraph_vector_resize(&weights, igraph_ecount(&g));
for (igraph_int_t i=0; i < igraph_ecount(&g); i++) {
VECTOR(weights)[i] = RNG_EXP(1);
}
igraph_random_sample(&generators, 0, igraph_vcount(&g)-1, 20);
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Unweighted, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, NULL, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Dijkstra, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, &weights, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
igraph_destroy(&g);
#undef VCOUNT
#undef DENS
#undef REP
printf("\n");
#define VCOUNT 100000
#define DENS 0.0001
#define REP 1
igraph_erdos_renyi_game_gnp(&g, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_vector_int_resize(&membership, igraph_vcount(&g));
igraph_vector_resize(&distances, igraph_vcount(&g));
igraph_vector_resize(&weights, igraph_ecount(&g));
for (igraph_int_t i=0; i < igraph_ecount(&g); i++) {
VECTOR(weights)[i] = RNG_EXP(1);
}
igraph_random_sample(&generators, 0, igraph_vcount(&g)-1, 100);
BENCH(" 1 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Unweighted, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, NULL, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
BENCH(" 2 vcount=" TOSTR(VCOUNT) ", p=" TOSTR(DENS) ", Dijkstra, " TOSTR(REP) "x",
REPEAT(igraph_voronoi(&g, &membership, &distances, &generators, &weights, IGRAPH_OUT, IGRAPH_VORONOI_RANDOM), REP);
);
igraph_destroy(&g);
#undef VCOUNT
#undef DENS
#undef REP
igraph_vector_int_destroy(&generators);
igraph_vector_destroy(&weights);
igraph_vector_destroy(&distances);
igraph_vector_int_destroy(&membership);
return 0;
}
@@ -0,0 +1,456 @@
/*
igraph library.
Copyright (C) 2013-2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
typedef struct igraph_incadjlist_inter_t {
igraph_int_t length;
igraph_vector_int_t *incadjs;
} igraph_incadjlist_inter_t;
#define igraph_incadjlist_inter_get(il,no) (&(il)->incadjs[(igraph_int_t)(no)])
#define igraph_incadjlist_sep_get_inc(il,no) (&(il)->incs[(igraph_int_t)(no)])
#define igraph_incadjlist_sep_get_adj(il,no) (&(il)->adjs[(igraph_int_t)(no)])
void igraph_incadjlist_inter_destroy(igraph_incadjlist_inter_t *il) {
igraph_int_t i;
for (i = 0; i < il->length; i++) {
/* This works if some igraph_vector_int_t's contain NULL,
because igraph_vector_int_destroy can handle this. */
igraph_vector_int_destroy(&il->incadjs[i]);
}
IGRAPH_FREE(il->incadjs);
}
igraph_error_t igraph_incadjlist_inter_init(const igraph_t *graph,
igraph_incadjlist_inter_t *il,
igraph_neimode_t mode) {
igraph_int_t i, j, n;
igraph_vector_int_t tmp;
if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
IGRAPH_ERROR("Cannot create incadjlist.", IGRAPH_EINVMODE);
}
igraph_vector_int_init(&tmp, 0);
IGRAPH_FINALLY(igraph_vector_int_destroy, &tmp);
if (!igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
il->length = igraph_vcount(graph);
il->incadjs = IGRAPH_CALLOC(il->length, igraph_vector_int_t);
if (il->incadjs == 0) {
IGRAPH_ERROR("Cannot create incadjlist.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
}
IGRAPH_FINALLY(igraph_incadjlist_inter_destroy, il);
for (i = 0; i < il->length; i++) {
//IGRAPH_ALLOW_INTERRUPTION();
IGRAPH_CHECK(igraph_incident(graph, &tmp, i, mode, IGRAPH_LOOPS));
n = igraph_vector_int_size(&tmp);
IGRAPH_CHECK(igraph_vector_int_init(&il->incadjs[i], n * 2));
for (j = 0; j < n; j++) {
VECTOR(il->incadjs[i])[j * 2] = VECTOR(tmp)[j];
VECTOR(il->incadjs[i])[j * 2 + 1] =
IGRAPH_OTHER(graph, VECTOR(tmp)[j], i);
}
}
igraph_vector_int_destroy(&tmp);
IGRAPH_FINALLY_CLEAN(2); /* + igraph_incadjlist_inter_destroy */
return IGRAPH_SUCCESS;
}
typedef struct igraph_incadjlist_sep_t {
igraph_int_t length;
igraph_vector_int_t *incs;
igraph_vector_int_t *adjs;
} igraph_incadjlist_sep_t;
void igraph_incadjlist_sep_destroy(igraph_incadjlist_sep_t *il) {
igraph_int_t i;
for (i = 0; i < il->length; i++) {
/* This works if some igraph_vector_int_t's contain NULL,
because igraph_vector_int_destroy can handle this. */
igraph_vector_int_destroy(&il->incs[i]);
igraph_vector_int_destroy(&il->adjs[i]);
}
IGRAPH_FREE(il->incs);
IGRAPH_FREE(il->adjs);
}
igraph_error_t igraph_incadjlist_sep_init(const igraph_t *graph,
igraph_incadjlist_sep_t *il,
igraph_neimode_t mode) {
igraph_int_t i, j, n;
igraph_vector_int_t tmp;
if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
IGRAPH_ERROR("Cannot create incadjlist.", IGRAPH_EINVMODE);
}
igraph_vector_int_init(&tmp, 0);
IGRAPH_FINALLY(igraph_vector_int_destroy, &tmp);
if (!igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
il->length = igraph_vcount(graph);
il->incs = IGRAPH_CALLOC(il->length, igraph_vector_int_t);
if (il->incs == 0) {
IGRAPH_ERROR("Cannot create incadjlist.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
}
il->adjs = IGRAPH_CALLOC(il->length, igraph_vector_int_t);
if (il->adjs == 0) {
IGRAPH_FREE(il->incs);
IGRAPH_ERROR("Cannot create incadjlist.", IGRAPH_ENOMEM); /* LCOV_EXCL_LINE */
}
IGRAPH_FINALLY(igraph_incadjlist_sep_destroy, il);
for (i = 0; i < il->length; i++) {
//IGRAPH_ALLOW_INTERRUPTION();
IGRAPH_CHECK(igraph_incident(graph, &tmp, i, mode, IGRAPH_LOOPS));
n = igraph_vector_int_size(&tmp);
IGRAPH_CHECK(igraph_vector_int_init(&il->incs[i], n));
IGRAPH_CHECK(igraph_vector_int_init(&il->adjs[i], n));
for (j = 0; j < n; j++) {
VECTOR(il->incs[i])[j] = VECTOR(tmp)[j];
VECTOR(il->adjs[i])[j] =
IGRAPH_OTHER(graph, VECTOR(tmp)[j], i);
}
}
igraph_vector_int_destroy(&tmp);
IGRAPH_FINALLY_CLEAN(2); /* + igraph_incadjlist_sep_destroy */
return IGRAPH_SUCCESS;
}
/* In the below tests, the 'dummy' variable is used to prevent the compilers
* from optimizing away the entire side-effects-free function. We use XOR
* instead of e.g. addition in order to prevent triggering undefined behaviour. */
igraph_int_t test_direct(igraph_t *g)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
igraph_int_t ecount = igraph_ecount(g);
igraph_int_t ei = 0;
igraph_int_t eo = 0;
for (igraph_int_t i = 0; i < vcount; i++) {
while (ei < ecount && VECTOR(g->from)[VECTOR(g->oi)[ei]] == i) {
igraph_int_t neighbor = VECTOR(g->to)[VECTOR(g->oi)[ei]];
dummy ^= neighbor ^ VECTOR(g->oi)[ei];
ei++;
}
while (eo < ecount && VECTOR(g->to)[VECTOR(g->ii)[eo]] == i) {
igraph_int_t neighbor = VECTOR(g->from)[VECTOR(g->ii)[eo]];
dummy ^= neighbor ^ VECTOR(g->ii)[eo] ;
eo++;
}
}
return dummy;
}
igraph_int_t test_adj(igraph_t *g, igraph_adjlist_t *adj)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *neis = igraph_adjlist_get(adj, i);
igraph_int_t nneis = igraph_vector_int_size(neis);
for (int j = 0; j < nneis; j++) {
igraph_int_t neighbor = VECTOR(*neis)[j];
dummy ^= neighbor;
}
}
return dummy;
}
igraph_int_t test_inc_adj(igraph_t *g, igraph_inclist_t *inc, igraph_adjlist_t *adj)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *adjs = igraph_adjlist_get(adj, i);
igraph_vector_int_t *incs = igraph_inclist_get(inc, i);
igraph_int_t nneis = igraph_vector_int_size(adjs);
for (int j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*incs)[j];
igraph_int_t neighbor = VECTOR(*adjs)[j];
dummy ^= neighbor ^ edge;
}
}
return dummy;
}
igraph_int_t test_inc_other(igraph_t *g, igraph_inclist_t *inc)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *neis = igraph_inclist_get(inc, i);
igraph_int_t nneis = igraph_vector_int_size(neis);
for (igraph_int_t j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*neis)[j];
igraph_int_t neighbor = IGRAPH_OTHER(g, edge, i);
dummy ^= neighbor ^ edge;
}
}
return dummy;
}
igraph_int_t test_incadj_sep(igraph_t *g, igraph_incadjlist_sep_t *inc)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *incs = igraph_incadjlist_sep_get_inc(inc, i);
igraph_vector_int_t *adjs = igraph_incadjlist_sep_get_adj(inc, i);
igraph_int_t nneis = igraph_vector_int_size(incs);
for (igraph_int_t j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*incs)[j];
igraph_int_t neighbor = VECTOR(*adjs)[j];
dummy ^= neighbor ^ edge;
}
}
return dummy;
}
igraph_int_t test_incadj_inter(igraph_t *g, igraph_incadjlist_inter_t *inc)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *ias = igraph_incadjlist_inter_get(inc, i);
igraph_int_t nneis = igraph_vector_int_size(ias) / 2;
for (igraph_int_t j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*ias)[j * 2];
igraph_int_t neighbor = VECTOR(*ias)[j * 2 + 1];
dummy ^= neighbor ^ edge;
}
}
return dummy;
}
igraph_int_t test_inc_to(igraph_t *g, igraph_inclist_t *inc)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *neis = igraph_inclist_get(inc, i);
igraph_int_t nneis = igraph_vector_int_size(neis);
for (igraph_int_t j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*neis)[j];
igraph_int_t neighbor = IGRAPH_TO(g, edge);
dummy ^= neighbor ^ edge;
}
}
return dummy;
}
igraph_int_t test_inc_nop(igraph_t *g, igraph_inclist_t *inc)
{
igraph_int_t dummy = 0;
igraph_int_t vcount = igraph_vcount(g);
for (igraph_int_t i = 0; i < vcount; i++) {
igraph_vector_int_t *neis = igraph_inclist_get(inc, i);
igraph_int_t nneis = igraph_vector_int_size(neis);
for (igraph_int_t j = 0; j < nneis; j++) {
igraph_int_t edge = VECTOR(*neis)[j];
dummy ^= edge;
}
}
return dummy;
}
/* Used to prevent optimizing away the result.
* This must be a global variable to prevent "variable set but not used"
* warnings from some compilers. */
volatile igraph_int_t result;
void do_benchmarks(char *name, igraph_t *g, int repeat) {
igraph_adjlist_t adj;
igraph_inclist_t inc;
igraph_incadjlist_inter_t incadj_inter;
igraph_incadjlist_sep_t incadj_sep;
/* The init() call is in a REPEAT loop, so we include destroy() as well to avoid a memory leak.
* This is representative of real use cases, where init/destroy should always come in pairs. */
printf("%s", name);
BENCH("1 init/destroy adjlist.",
REPEAT(
do {
igraph_adjlist_init(g, &adj, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
igraph_adjlist_destroy(&adj);
} while (0),
repeat);
);
printf("%s", name);
BENCH("2 init/destroy inclist.",
REPEAT(
do {
igraph_inclist_init(g, &inc, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
igraph_inclist_destroy(&inc);
} while (0),
repeat);
);
printf("%s", name);
BENCH("3 init/destroy adjlist, remove loops and multiple (which aren't present).",
REPEAT(
do {
igraph_adjlist_init(g, &adj, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
igraph_adjlist_destroy(&adj);
} while (0),
repeat);
);
printf("%s", name);
BENCH("4 init/destroy inclist, remove loops (which aren't present).",
REPEAT(
do {
igraph_inclist_init(g, &inc, IGRAPH_ALL, IGRAPH_NO_LOOPS);
igraph_inclist_destroy(&inc);
} while (0),
repeat);
);
/* Initialize adjlist / inclist for the following benchmarks. */
igraph_adjlist_init(g, &adj, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
igraph_inclist_init(g, &inc, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("%s", name);
BENCH("5 go over vertices (multiple times) using adjlist.",
REPEAT(result = test_adj(g, &adj), repeat);
);
printf("%s", name);
BENCH("6 go over vertices (multiple times) using inclist, IGRAPH_OTHER.",
REPEAT(result = test_inc_other(g, &inc), repeat);
);
printf("%s", name);
BENCH("7 go over vertices (multiple times) using inclist, IGRAPH_TO.",
REPEAT(result = test_inc_to(g, &inc), repeat);
);
printf("%s", name);
BENCH("8 go over edges using inclist, don't retrieve vertex.",
REPEAT(result = test_inc_nop(g, &inc), repeat);
);
printf("%s", name);
BENCH("9 go over edges and vertices using adjlist and inclist.",
REPEAT(result = test_inc_adj(g, &inc, &adj), repeat);
);
igraph_adjlist_destroy(&adj);
igraph_inclist_destroy(&inc);
printf("%s", name);
BENCH("10 go over edges and vertices using graph internals directly.",
REPEAT(result = test_direct(g), repeat);
);
printf("%s", name);
BENCH("11 init/destroy interleaved incadjlist.",
REPEAT(
do {
igraph_incadjlist_inter_init(g, &incadj_inter, IGRAPH_ALL);
igraph_incadjlist_inter_destroy(&incadj_inter);
} while (0),
repeat);
);
igraph_incadjlist_inter_init(g, &incadj_inter, IGRAPH_ALL);
printf("%s", name);
BENCH("12 go over edges and vertices using interleaved incadjlist.",
REPEAT(result = test_incadj_inter(g, &incadj_inter), repeat);
);
igraph_incadjlist_inter_destroy(&incadj_inter);
printf("%s", name);
BENCH("13 init/destroy incadjlist with two vectors.",
REPEAT(
do {
igraph_incadjlist_sep_init(g, &incadj_sep, IGRAPH_ALL);
igraph_incadjlist_sep_destroy(&incadj_sep);
} while (0), repeat);
);
igraph_incadjlist_sep_init(g, &incadj_sep, IGRAPH_ALL);
printf("%s", name);
BENCH("14 go over edges and vertices using incadjlist.",
REPEAT(result = test_incadj_sep(g, &incadj_sep), repeat);
);
igraph_incadjlist_sep_destroy(&incadj_sep);
}
int main(void) {
igraph_t g;
igraph_rng_seed(igraph_rng_default(), 42);
BENCH_INIT();
printf("Full graph tests:\n");
igraph_full(&g, 10000, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
do_benchmarks(" fg - ", &g, 1);
igraph_destroy(&g);
printf("\nRandom graph tests:\n");
igraph_erdos_renyi_game_gnm(&g, 10000, 49994999, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
do_benchmarks(" rg - ", &g, 1);
igraph_destroy(&g);
printf("\nSmall graph tests:\n");
igraph_full(&g, 1000, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
do_benchmarks(" sg - ", &g, 100);
igraph_destroy(&g);
return 0;
}
@@ -0,0 +1,87 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void rand_vec(igraph_vector_int_t *v, igraph_int_t n, igraph_int_t k) {
igraph_vector_int_resize(v, n);
for (igraph_int_t i=0; i < n; i++) {
VECTOR(*v)[i] = RNG_INTEGER(0, k);
}
}
void run_bench(int i, int n, int r) {
igraph_vector_int_t a, b;
igraph_int_t na = n, nb = r*n;
int rep = 300000000 / nb;
char msg[255];
igraph_vector_int_init(&a, na);
igraph_vector_int_init(&b, nb);
rand_vec(&a, na, nb);
igraph_vector_int_sort(&a);
rand_vec(&b, nb, nb);
igraph_vector_int_sort(&b);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%2d n = %5d, r = %3d, %dx", i, n, r, rep);
/* 'volatile' is needed to prevent the compiler from optimizing
* away multiple calls to the function with the same parameters within REPEAT.
* This would normally happen due to the use of IGRAPH_FUNCATTR_PURE.
* ATTENTION! 'volatile', when used this way, may not prevent this optimization
* with future compiler versions. */
volatile igraph_int_t res;
BENCH(msg, REPEAT(res = igraph_vector_int_intersection_size_sorted(&a, &b), rep));
(void) res; /* silence unused-but-set-variable warning */
igraph_vector_int_destroy(&a);
igraph_vector_int_destroy(&b);
}
int main(void) {
int i = 0;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
#define BENCHSET(n) \
run_bench(++i, n, 1); \
run_bench(++i, n, 3); \
run_bench(++i, n, 10); \
run_bench(++i, n, 30); \
run_bench(++i, n, 100); \
printf("\n");
BENCHSET(1);
BENCHSET(3);
BENCHSET(10);
BENCHSET(30);
BENCHSET(100);
BENCHSET(300);
BENCHSET(1000);
BENCHSET(3000);
BENCHSET(10000);
BENCHSET(30000);
BENCHSET(100000);
return 0;
}
@@ -0,0 +1,67 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void match(const igraph_t *graph,
const igraph_t patt[], igraph_int_t n,
igraph_vector_int_list_t *maps) {
igraph_vector_int_list_clear(maps);
for (igraph_int_t i=0; i < n; i++) {
igraph_subisomorphic_lad(&patt[i], graph, NULL, NULL, NULL, maps, false);
}
}
#define NP 8
int main(void) {
igraph_t graph;
igraph_t patt[NP];
igraph_vector_int_list_t maps;
BENCH_INIT();
igraph_vector_int_list_init(&maps, 0);
for (igraph_int_t i=0; i < NP; i++) {
igraph_ring(&patt[i], i+1, IGRAPH_DIRECTED, false, true);
}
igraph_kautz(&graph, 3, 3);
BENCH("1 Kautz(3,3) 10x", REPEAT(match(&graph, patt, NP, &maps), 10));
igraph_destroy(&graph);
igraph_kautz(&graph, 3, 4);
BENCH("2 Kautz(3,4) 3x", REPEAT(match(&graph, patt, NP, &maps), 3));
igraph_destroy(&graph);
igraph_kautz(&graph, 4, 3);
BENCH("3 Kautz(4,3) 1x", REPEAT(match(&graph, patt, NP, &maps), 1));
igraph_destroy(&graph);
for (igraph_int_t i=0; i < NP; i++) {
igraph_destroy(&patt[i]);
}
igraph_vector_int_list_destroy(&maps);
return 0;
}
@@ -0,0 +1,71 @@
/*
igraph library.
Copyright (C) 2025 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void run_bench(int n) {
igraph_t graph;
igraph_matrix_t modmat;
int rep;
char msg[255];
rep = 20000 / n;
rep = rep*rep;
igraph_matrix_init(&modmat, n, n);
igraph_erdos_renyi_game_gnm(&graph, n, 10 * n, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"G(n,m), directed, n = %5d, m = %7" IGRAPH_PRId ", %dx", n, igraph_ecount(&graph), rep);
BENCH(msg, REPEAT(igraph_modularity_matrix(&graph, NULL, 1.0, &modmat, IGRAPH_DIRECTED), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"G(n,m), undirected, n = %5d, m = %7" IGRAPH_PRId ", %dx", n, igraph_ecount(&graph), rep);
BENCH(msg, REPEAT(igraph_modularity_matrix(&graph, NULL, 1.0, &modmat, IGRAPH_UNDIRECTED), rep));
igraph_destroy(&graph);
igraph_erdos_renyi_game_gnp(&graph, n, 0.1, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"G(n,p), directed, n = %5d, m = %7" IGRAPH_PRId ", %dx", n, igraph_ecount(&graph), rep);
BENCH(msg, REPEAT(igraph_modularity_matrix(&graph, NULL, 1.0, &modmat, IGRAPH_DIRECTED), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"G(n,p), undirected, n = %5d, m = %7" IGRAPH_PRId ", %dx", n, igraph_ecount(&graph), rep);
BENCH(msg, REPEAT(igraph_modularity_matrix(&graph, NULL, 1.0, &modmat, IGRAPH_UNDIRECTED), rep));
igraph_destroy(&graph);
igraph_matrix_destroy(&modmat);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
run_bench(100);
run_bench(1000);
run_bench(10000);
return 0;
}
@@ -0,0 +1,164 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "bench.h"
void run_bench(const igraph_t *graph, const igraph_vector_t *weights, int rep, const char *name) {
igraph_vector_int_t edges;
igraph_int_t vcount = igraph_vcount(graph);
igraph_int_t ecount = igraph_ecount(graph);
char msg[128];
igraph_vector_int_init(&edges, vcount - 1);
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s, vcount=%" IGRAPH_PRId ", ecount=%" IGRAPH_PRId ", unweigthed, %dx",
name, vcount, ecount, rep);
BENCH(msg, REPEAT(igraph_minimum_spanning_tree(graph, &edges, NULL, IGRAPH_MST_UNWEIGHTED), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s, vcount=%" IGRAPH_PRId ", ecount=%" IGRAPH_PRId ", Prim, %dx",
name, vcount, ecount, rep);
BENCH(msg, REPEAT(igraph_minimum_spanning_tree(graph, &edges, weights, IGRAPH_MST_UNWEIGHTED), rep));
snprintf(msg, sizeof(msg) / sizeof(msg[0]),
"%s, vcount=%" IGRAPH_PRId ", ecount=%" IGRAPH_PRId ", Kruskal, %dx",
name, vcount, ecount, rep);
BENCH(msg, REPEAT(igraph_minimum_spanning_tree(graph, &edges, weights, IGRAPH_MST_UNWEIGHTED), rep));
printf("\n");
igraph_vector_int_destroy(&edges);
}
void rand_weights(const igraph_t *graph, igraph_vector_t *weights) {
igraph_int_t ecount = igraph_ecount(graph);
igraph_vector_resize(weights, ecount);
for (igraph_int_t i=0; i < ecount; i++) {
VECTOR(*weights)[i] = RNG_UNIF01();
}
}
int main(void) {
igraph_t g;
igraph_vector_t weights;
igraph_rng_seed(igraph_rng_default(), 137);
BENCH_INIT();
igraph_vector_init(&weights, 0);
igraph_barabasi_game(&g, 100, 1, 1, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 50000, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 100, 1, 5, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 10000, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 1000, 1, 5, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 1000, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 10000, 1, 5, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 100, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 100, 1, 50, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 1000, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 1000, 1, 50, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 100, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 10000, 1, 50, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 10, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 1000, 1, 500, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 10, "PA");
igraph_destroy(&g);
igraph_barabasi_game(&g, 10000, 1, 500, NULL, true, 0, false, IGRAPH_BARABASI_PSUMTREE, NULL);
rand_weights(&g, &weights);
run_bench(&g, &weights, 1, "PA");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 500, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 60000, "G(n,m)");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 1000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 30000, "G(n,m)");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 3000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 10000, "G(n,m)");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 10000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 3000, "G(n,m)");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 30000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 1000, "G(n,m)");
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1000, 100000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
rand_weights(&g, &weights);
run_bench(&g, &weights, 300, "G(n,m)");
igraph_destroy(&g);
igraph_full(&g, 100, false, false);
rand_weights(&g, &weights);
run_bench(&g, &weights, 10000, "K");
igraph_destroy(&g);
igraph_full(&g, 1000, false, false);
rand_weights(&g, &weights);
run_bench(&g, &weights, 100, "K");
igraph_destroy(&g);
{
igraph_t K;
igraph_full(&K, 100, false, false);
igraph_disjoint_union(&g, &K, &K);
igraph_destroy(&K);
}
rand_weights(&g, &weights);
run_bench(&g, &weights, 10000, "K + K");
igraph_destroy(&g);
return 0;
}
@@ -0,0 +1,43 @@
/*
igraph library.
Copyright (C) 2010-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t graph;
igraph_vector_int_list_t separators;
igraph_small(&graph, 0, /*directed=*/ 0,
0, 1, 0, 2, 1, 3, 1, 4, 2, 3, 2, 5, 3, 4, 3, 5, 4, 6, 5, 6, -1);
igraph_vector_int_list_init(&separators, 0);
igraph_all_minimal_st_separators(&graph, &separators);
print_vector_int_list(&separators);
igraph_vector_int_list_destroy(&separators);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,11 @@
{
0: ( 1 2 )
1: ( 0 3 4 )
2: ( 0 3 5 )
3: ( 4 5 )
4: ( 1 3 6 )
5: ( 2 3 6 )
6: ( 2 3 4 )
7: ( 1 3 5 )
8: ( 0 3 6 )
}
@@ -0,0 +1,47 @@
/*
igraph library.
Copyright (C) 2013 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t graph;
igraph_vector_t mod;
igraph_empty(&graph, 25, IGRAPH_UNDIRECTED);
igraph_vector_init(&mod, 0);
igraph_community_multilevel(&graph, /*weights=*/ 0, /*resolution=*/ 1,
/*membership=*/ 0, /*memberships=*/ 0, &mod);
if (igraph_vector_size(&mod) != 1 ||
!isnan(VECTOR(mod)[0])) {
return 1;
}
igraph_vector_destroy(&mod);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,159 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
/* Regression test for https://github.com/igraph/igraph/issues/1760 */
int test_unweighted(const igraph_t* g, igraph_int_t from, const igraph_vs_t* to) {
igraph_vector_int_list_t vpath, epath;
igraph_int_t num_paths;
igraph_vector_int_t parents;
igraph_vector_int_t inbound_edges;
printf("Unweighted case\n");
printf("---------------\n\n");
IGRAPH_CHECK(igraph_vs_size(g, to, &num_paths));
IGRAPH_CHECK(igraph_vector_int_list_init(&vpath, 0));
IGRAPH_CHECK(igraph_vector_int_list_init(&epath, 0));
IGRAPH_CHECK(igraph_vector_int_init(&parents, 0));
IGRAPH_CHECK(igraph_vector_int_init(&inbound_edges, 0));
IGRAPH_CHECK(igraph_get_shortest_paths(
g, NULL, &vpath, &epath, from, *to, IGRAPH_IN,
&parents, &inbound_edges
));
printf("Vertices:\n");
print_vector_int_list(&vpath);
printf("\n");
printf("Edges:\n");
print_vector_int_list(&epath);
printf("\n");
printf("Parents:\n");
print_vector_int(&parents);
printf("\n");
printf("Inbound edges:\n");
print_vector_int(&inbound_edges);
printf("\n");
igraph_vector_int_destroy(&inbound_edges);
igraph_vector_int_destroy(&parents);
igraph_vector_int_list_destroy(&epath);
igraph_vector_int_list_destroy(&vpath);
return IGRAPH_SUCCESS;
}
int test_weighted(
const igraph_t* g, const igraph_vector_t* weights, igraph_int_t from,
const igraph_vs_t* to, igraph_bool_t use_bellman_ford
) {
igraph_vector_int_list_t vpath, epath;
igraph_int_t num_paths;
igraph_vector_int_t parents;
igraph_vector_int_t inbound_edges;
printf("Weighted case\n");
printf("-------------\n\n");
printf("Algorithm: %s\n\n", use_bellman_ford ? "Bellman-Ford" : "Dijkstra");
IGRAPH_CHECK(igraph_vs_size(g, to, &num_paths));
IGRAPH_CHECK(igraph_vector_int_list_init(&vpath, 0));
IGRAPH_CHECK(igraph_vector_int_list_init(&epath, 0));
IGRAPH_CHECK(igraph_vector_int_init(&parents, 0));
IGRAPH_CHECK(igraph_vector_int_init(&inbound_edges, 0));
if (use_bellman_ford) {
IGRAPH_CHECK(igraph_get_shortest_paths_bellman_ford(
g, &vpath, &epath, from, *to, weights, IGRAPH_IN,
&parents, &inbound_edges
));
} else {
IGRAPH_CHECK(igraph_get_shortest_paths_dijkstra(
g, &vpath, &epath, from, *to, weights, IGRAPH_IN,
&parents, &inbound_edges
));
}
printf("Vertices:\n");
print_vector_int_list(&vpath);
printf("\n");
printf("Edges:\n");
print_vector_int_list(&epath);
printf("\n");
printf("Parents:\n");
print_vector_int(&parents);
printf("\n");
printf("Inbound edges:\n");
print_vector_int(&inbound_edges);
printf("\n");
igraph_vector_int_destroy(&inbound_edges);
igraph_vector_int_destroy(&parents);
igraph_vector_int_list_destroy(&epath);
igraph_vector_int_list_destroy(&vpath);
return IGRAPH_SUCCESS;
}
int main(void) {
igraph_t g;
igraph_vector_t weights;
igraph_vs_t to;
igraph_set_warning_handler(igraph_warning_handler_ignore);
igraph_small(&g, 4, /* directed = */ 1, 0, 1, 1, 2, 1, 3, -1);
igraph_vs_vector_small(&to, 0, 3, -1);
igraph_vector_init(&weights, 3);
VECTOR(weights)[0] = 1;
VECTOR(weights)[1] = 2;
VECTOR(weights)[2] = 2;
/* Test unweighted case */
if (test_unweighted(&g, 2, &to)) {
return 1;
}
/* Test weighted case */
if (test_weighted(&g, &weights, 2, &to, /* use_bellman_ford = */ 0)) {
return 2;
}
if (test_weighted(&g, &weights, 2, &to, /* use_bellman_ford = */ 1)) {
return 3;
}
igraph_vector_destroy(&weights);
igraph_vs_destroy(&to);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,67 @@
Unweighted case
---------------
Vertices:
{
0: ( 2 1 0 )
1: ( )
}
Edges:
{
0: ( 1 0 )
1: ( )
}
Parents:
( 1 2 -1 -2 )
Inbound edges:
( 0 1 -1 -1 )
Weighted case
-------------
Algorithm: Dijkstra
Vertices:
{
0: ( 2 1 0 )
1: ( )
}
Edges:
{
0: ( 1 0 )
1: ( )
}
Parents:
( 1 2 -1 -2 )
Inbound edges:
( 0 1 -1 -1 )
Weighted case
-------------
Algorithm: Bellman-Ford
Vertices:
{
0: ( 2 1 0 )
1: ( )
}
Edges:
{
0: ( 1 0 )
1: ( )
}
Parents:
( 1 2 -1 -2 )
Inbound edges:
( 0 1 -1 -1 )
@@ -0,0 +1,75 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
/* Regression test for https://github.com/igraph/igraph/issues/1814 */
void test_igraph_to_undirected(igraph_to_undirected_t mode) {
igraph_t g;
igraph_attribute_combination_t comb;
igraph_small(&g, 4, IGRAPH_DIRECTED,
0,1, 0,1, 1,0,
1,1, 1,1,
-1);
SETEAN(&g, "weight", 0, 1);
SETEAN(&g, "weight", 1, 2);
SETEAN(&g, "weight", 2, 3);
SETEAN(&g, "weight", 3, 4);
SETEAN(&g, "weight", 4, 2);
igraph_attribute_combination(
&comb, "weight", IGRAPH_ATTRIBUTE_COMBINE_SUM,
IGRAPH_NO_MORE_ATTRIBUTES
);
igraph_to_undirected(&g, mode, &comb);
igraph_attribute_combination_destroy(&comb);
igraph_write_graph_gml(&g, stdout, IGRAPH_WRITE_GML_DEFAULT_SW, 0, "");
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
}
int main(void) {
igraph_set_attribute_table(&igraph_cattribute_table);
printf("to_undirected(COLLAPSE)\n");
printf("=======================\n\n");
test_igraph_to_undirected(IGRAPH_TO_UNDIRECTED_COLLAPSE);
printf("\n");
printf("to_undirected(MUTUAL)\n");
printf("=====================\n\n");
test_igraph_to_undirected(IGRAPH_TO_UNDIRECTED_MUTUAL);
printf("\n");
printf("to_undirected(EACH)\n");
printf("===================\n\n");
test_igraph_to_undirected(IGRAPH_TO_UNDIRECTED_EACH);
printf("\n");
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,135 @@
to_undirected(COLLAPSE)
=======================
Version 1
graph
[
directed 0
node
[
id 0
]
node
[
id 1
]
node
[
id 2
]
node
[
id 3
]
edge
[
source 1
target 0
weight 6
]
edge
[
source 1
target 1
weight 6
]
]
to_undirected(MUTUAL)
=====================
Version 1
graph
[
directed 0
node
[
id 0
]
node
[
id 1
]
node
[
id 2
]
node
[
id 3
]
edge
[
source 1
target 0
weight 5
]
edge
[
source 1
target 1
weight 2
]
edge
[
source 1
target 1
weight 4
]
]
to_undirected(EACH)
===================
Version 1
graph
[
directed 0
node
[
id 0
]
node
[
id 1
]
node
[
id 2
]
node
[
id 3
]
edge
[
source 1
target 0
weight 1
]
edge
[
source 1
target 0
weight 2
]
edge
[
source 1
target 0
weight 3
]
edge
[
source 1
target 1
weight 4
]
edge
[
source 1
target 1
weight 2
]
]
@@ -0,0 +1,44 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
FILE *file;
igraph_t graph;
igraph_error_t err;
igraph_set_attribute_table(&igraph_cattribute_table);
igraph_set_error_handler(igraph_error_handler_printignore);
file = fopen("bug_1970.graphml", "r");
IGRAPH_ASSERT(file != NULL);
err = igraph_read_graph_graphml(&graph, file, 0);
fclose(file);
IGRAPH_ASSERT(err != IGRAPH_SUCCESS);
/* graph creation should have failed, no need to destroy 'graph' */
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1 @@
<graphml><key id="one" for="edge" attr.type="double"/><key id="one" for="edge" attr.type="string"></key><graph></graph></graphml>
@@ -0,0 +1,46 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
/* Regression test for https://github.com/igraph/igraph/issues/2150 */
int main(void) {
igraph_t graph;
igraph_vector_t w;
igraph_vector_int_list_t res;
igraph_full(&graph, 3, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_vector_init_int(&w, 3, 1, 2, 3);
igraph_vector_int_list_init(&res, 0);
igraph_weighted_cliques(&graph, &w, &res, false, 1, 3, IGRAPH_UNLIMITED);
igraph_vector_int_list_destroy(&res);
igraph_vector_destroy(&w);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,48 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
FILE *file;
igraph_t graph;
igraph_set_attribute_table(&igraph_cattribute_table);
igraph_set_error_handler(igraph_error_handler_ignore);
igraph_set_warning_handler(igraph_warning_handler_ignore);
file = fopen("bug_2497.gml", "r");
IGRAPH_ASSERT(file != NULL);
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
IGRAPH_ASSERT(igraph_read_graph_gml(&graph, file) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
fclose(file);
igraph_write_graph_gml(&graph, stdout, IGRAPH_WRITE_GML_DEFAULT_SW, NULL, "");
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,4 @@
graph [
node [ id 2 ]
node [ ]
]
@@ -0,0 +1,13 @@
Version 1
graph
[
directed 0
node
[
id 0
]
node
[
id 1
]
]
@@ -0,0 +1,68 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t g;
igraph_error_t result;
FILE *ifile;
igraph_set_error_handler(igraph_error_handler_ignore);
igraph_set_attribute_table(&igraph_cattribute_table);
ifile = fopen("bug_2506_1.graphml", "r");
IGRAPH_ASSERT(ifile != NULL);
result = igraph_read_graph_graphml(&g, ifile, 0);
fclose(ifile);
if (result == IGRAPH_UNIMPLEMENTED) {
/* maybe it is simply disabled at compile-time */
return 77;
}
IGRAPH_ASSERT(result == IGRAPH_PARSEERROR);
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
ifile = fopen("bug_2506_2.graphml", "r");
IGRAPH_ASSERT(ifile != NULL);
result = igraph_read_graph_graphml(&g, ifile, 0);
fclose(ifile);
IGRAPH_ASSERT(result == IGRAPH_PARSEERROR);
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
ifile = fopen("bug_2506_3.graphml", "r");
IGRAPH_ASSERT(ifile != NULL);
result = igraph_read_graph_graphml(&g, ifile, 0);
fclose(ifile);
IGRAPH_ASSERT(result == IGRAPH_PARSEERROR);
IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,4 @@
<graphml>
<key id="d3" for="" attr.type="s"></key><key id="d3" for="" attr.type=""></key>
<graph></graph>
</graphml>
@@ -0,0 +1 @@
<graphml><key id="" for="graph" attr.type="string"/><key id="" for="graph" attr.type="double"/><graph></graph></graphml>
@@ -0,0 +1 @@
<graphml><key id="e" for="graph" attr.name="" attr.type="string"/><key id="g" for="graph" attr.name="" attr.type="double"/><graph></graph></graphml>
@@ -0,0 +1,44 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_list_t result;
igraph_vector_int_list_init(&result, 0);
igraph_small(&g, 2, IGRAPH_UNDIRECTED, 0, 1, -1);
igraph_all_minimal_st_separators(&g, &result);
print_vector_int_list(&result);
igraph_destroy(&g);
igraph_small(&g, 3, IGRAPH_UNDIRECTED, 0, 1, -1);
igraph_all_minimal_st_separators(&g, &result);
print_vector_int_list(&result);
igraph_destroy(&g);
igraph_vector_int_list_destroy(&result);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,4 @@
{
}
{
}
@@ -0,0 +1,49 @@
/*
igraph library.
Copyright (C) 2007-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_t membership;
/* label propagation is a stochastic method */
igraph_rng_seed(igraph_rng_default(), 765);
igraph_small(&g, 0, /* directed = */ 1,
0, 1, 0, 2, 1, 0, 1, 0, 1, 1, 2, 0, 2, 1, 2, 1, 2, 1, -1);
igraph_vector_int_init(&membership, 0);
igraph_community_label_propagation(&g, &membership, IGRAPH_OUT, NULL, NULL, NULL, IGRAPH_LPA_FAST);
print_vector_int(&membership);
igraph_vector_int_destroy(&membership);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,73 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
void check_attr(igraph_t *graph) {
IGRAPH_ASSERT(igraph_cattribute_has_attr(graph, IGRAPH_ATTRIBUTE_GRAPH, "name"));
IGRAPH_ASSERT(igraph_cattribute_has_attr(graph, IGRAPH_ATTRIBUTE_GRAPH, "type"));
IGRAPH_ASSERT(igraph_cattribute_has_attr(graph, IGRAPH_ATTRIBUTE_GRAPH, "p"));
IGRAPH_ASSERT(igraph_cattribute_has_attr(graph, IGRAPH_ATTRIBUTE_VERTEX, "name"));
IGRAPH_ASSERT(igraph_cattribute_has_attr(graph, IGRAPH_ATTRIBUTE_EDGE, "weight"));
}
int main(void) {
igraph_t graph;
igraph_error_handler_t* oldhandler;
int result;
FILE *ifile = fopen("cattr_bool_bug.graphml", "r");
if (!ifile) {
printf("Cannot open input file\n");
return 1;
}
igraph_set_attribute_table(&igraph_cattribute_table);
oldhandler = igraph_set_error_handler(igraph_error_handler_ignore);
if ((result = igraph_read_graph_graphml(&graph, ifile, 0))) {
/* Maybe it is simply disabled at compile-time. If so, skip test. */
if (result == IGRAPH_UNIMPLEMENTED) {
return 77;
}
printf("Failed to read GraphML file\n");
return 1;
}
igraph_set_error_handler(oldhandler);
fclose(ifile);
printf("Checkng attributes of original graph\n");
check_attr(&graph);
printf("Checkng attributes of directed version\n");
igraph_to_directed(&graph, IGRAPH_TO_DIRECTED_ARBITRARY);
check_attr(&graph);
IGRAPH_ASSERT(! GAB(&graph, "loops"));
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="g_name" for="graph" attr.name="name" attr.type="string"/>
<key id="g_type" for="graph" attr.name="type" attr.type="string"/>
<key id="g_loops" for="graph" attr.name="loops" attr.type="boolean"/>
<key id="g_p" for="graph" attr.name="p" attr.type="double"/>
<key id="v_id" for="node" attr.name="name" attr.type="string"/>
<key id="e_weight" for="edge" attr.name="weight" attr.type="double"/>
<graph id="G" edgedefault="undirected">
<data key="g_name">Erdos renyi (gnp) graph</data>
<data key="g_type">gnp</data>
<data key="g_loops">false</data>
<data key="g_p">0.2</data>
<node id="n0">
<data key="v_id">n0</data>
</node>
<node id="n1">
<data key="v_id">n1</data>
</node>
<node id="n2">
<data key="v_id">n2</data>
</node>
<node id="n3">
<data key="v_id">n3</data>
</node>
<node id="n4">
<data key="v_id">n4</data>
</node>
<node id="n5">
<data key="v_id">n5</data>
</node>
<node id="n6">
<data key="v_id">n6</data>
</node>
<node id="n7">
<data key="v_id">n7</data>
</node>
<node id="n8">
<data key="v_id">n8</data>
</node>
<node id="n9">
<data key="v_id">n9</data>
</node>
<edge source="n0" target="n1">
<data key="e_weight">10</data>
</edge>
<edge source="n0" target="n3">
<data key="e_weight">11</data>
</edge>
<edge source="n4" target="n5">
<data key="e_weight">12</data>
</edge>
<edge source="n0" target="n6">
<data key="e_weight">13</data>
</edge>
<edge source="n5" target="n6">
<data key="e_weight">14</data>
</edge>
<edge source="n4" target="n7">
<data key="e_weight">15</data>
</edge>
<edge source="n5" target="n7">
<data key="e_weight">16</data>
</edge>
<edge source="n5" target="n9">
<data key="e_weight">17</data>
</edge>
<edge source="n7" target="n9">
<data key="e_weight">18</data>
</edge>
</graph>
</graphml>
@@ -0,0 +1,63 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
#define FILENAME "mybool.graphml.xml"
int main(void) {
igraph_t graph;
igraph_error_handler_t* oldhandler;
int result;
FILE* ifile = fopen("cattr_bool_bug2.graphml", "r");
if (!ifile) {
printf("Cannot open input file\n");
return 1;
}
igraph_set_attribute_table(&igraph_cattribute_table);
oldhandler = igraph_set_error_handler(igraph_error_handler_ignore);
if ((result = igraph_read_graph_graphml(&graph, ifile, 0))) {
/* maybe it is simply disabled at compile-time */
if (result == IGRAPH_UNIMPLEMENTED) {
return 77;
}
printf("Failed to read GraphML file\n");
return 1;
}
igraph_set_error_handler(oldhandler);
fclose(ifile);
IGRAPH_ASSERT(igraph_cattribute_has_attr(&graph, IGRAPH_ATTRIBUTE_GRAPH, "mybool"));
/* Boolean attribute value is expected to be true */
IGRAPH_ASSERT(igraph_cattribute_GAB(&graph, "mybool"));
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key attr.name="mybool" attr.type="boolean" for="graph" id="d0" />
<graph edgedefault="undirected">
<data key="d0">True</data>
</graph>
</graphml>
@@ -0,0 +1,66 @@
/*
igraph library.
Copyright (C) 2024 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
void snap_to_zero(igraph_real_t* value) {
if (fabs(*value) < 1e-5) {
*value = 0.0;
}
}
int main(void) {
igraph_t graph;
igraph_matrix_t layout;
igraph_int_t i;
if (igraph_empty(&graph, 2, 0)) {
return 1;
}
if (igraph_add_edge(&graph, 0, 1)) {
return 2;
}
if (igraph_matrix_init(&layout, 0, 0)) {
return 3;
}
if (igraph_layout_kamada_kawai_3d(&graph, &layout, 0, 200, 0, 2, 0, 0, 0, 0, 0, 0, 0)) {
return 4;
}
/* Snap numbers close to zero in the layout; there are false failures on
* MinGW if we don't do so */
for (i = 0; i < 2; i++) {
snap_to_zero(&MATRIX(layout, i, 0));
snap_to_zero(&MATRIX(layout, i, 1));
snap_to_zero(&MATRIX(layout, i, 2));
}
print_matrix_format(&layout, stdout, "%.2f");
igraph_matrix_destroy(&layout);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,2 @@
[ 0.00 0.00 -0.91
0.00 0.00 0.51 ]
@@ -0,0 +1,55 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard st, Cambridge MA, 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "../unit/test_utilities.h"
int main(void) {
igraph_t g;
FILE *f;
igraph_matrix_t coords;
igraph_vector_int_t roots;
igraph_int_t i, n;
f = fopen("igraph_layout_reingold_tilford_bug_879.in", "r");
IGRAPH_ASSERT(f != NULL);
igraph_read_graph_edgelist(&g, f, 0, IGRAPH_UNDIRECTED);
igraph_matrix_init(&coords, 0, 0);
igraph_vector_int_init(&roots, 0);
igraph_vector_int_push_back(&roots, 0);
igraph_layout_reingold_tilford(&g, &coords, IGRAPH_OUT, &roots, 0);
n = igraph_vcount(&g);
for (i = 0; i < n; i++) {
printf("%6.3f %6.3f\n", MATRIX(coords, i, 0), MATRIX(coords, i, 1));
}
igraph_matrix_destroy(&coords);
igraph_vector_int_destroy(&roots);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,15 @@
0 1
0 2
0 3
1 4
2 5
2 6
3 7
4 8
4 9
4 10
4 11
4 12
7 13
7 14
7 15
@@ -0,0 +1,16 @@
0.000 0.000
-1.833 1.000
-0.333 1.000
2.167 1.000
-1.833 2.000
-0.833 2.000
0.167 2.000
2.167 2.000
-3.833 3.000
-2.833 3.000
-1.833 3.000
-0.833 3.000
0.167 3.000
1.167 3.000
2.167 3.000
3.167 3.000
@@ -0,0 +1,74 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
int test_file(const char* fname) {
FILE *ifile;
igraph_t g;
int retval;
ifile = fopen(fname, "r");
if (ifile == 0) {
return 1;
}
retval = igraph_read_graph_gml(&g, ifile);
if (!retval) {
/* input was accepted, this is a bug; attempt to clean up after
* ourselves nevertheless */
igraph_destroy(&g);
fclose(ifile);
return 2;
}
fclose(ifile);
return 0;
}
#undef RUN_TEST
#define RUN_TEST(fname) { \
index++; \
if (test_file(fname)) { \
return index; \
} \
VERIFY_FINALLY_STACK(); \
}
int main(void) {
int index = 0;
/* We do not care about errors; all we care about is that the library
* should not segfault and should not accept invalid input either */
igraph_set_error_handler(igraph_error_handler_ignore);
RUN_TEST("invalid1.gml");
RUN_TEST("invalid2.gml");
/* invalid3.gml was removed, parser now supports it */
RUN_TEST("invalid4.gml");
RUN_TEST("invalid5.gml");
RUN_TEST("invalid6.gml");
return 0;
}
@@ -0,0 +1,81 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdio.h>
#include "../unit/test_utilities.h"
int test_file(const char* fname, igraph_bool_t should_parse) {
FILE *ifile;
igraph_t g;
igraph_error_t retval;
ifile = fopen(fname, "r");
if (ifile == 0) {
printf("Cannot open input file: %s\n", fname);
return 1;
}
retval = igraph_read_graph_graphml(&g, ifile, 0);
if (retval == IGRAPH_SUCCESS) {
/* destroy the graph if we managed to parse it */
igraph_destroy(&g);
}
fclose(ifile);
if (!should_parse && retval == IGRAPH_SUCCESS) {
/* input was accepted but it should not have been, this is a bug */
return 2;
} else {
return 0;
}
}
#undef RUN_TEST
#define RUN_TEST(fname, should_parse) { \
index++; \
if (test_file(fname, should_parse)) { \
return index; \
} \
VERIFY_FINALLY_STACK(); \
}
int main(void) {
int index = 0;
/* We do not care about errors; all we care about is that the library
* should not segfault, should not accept invalid input and should not
* print anything to stdout or stderr while parsing, apart from warnings */
igraph_set_error_handler(igraph_error_handler_ignore);
igraph_set_warning_handler(igraph_warning_handler_ignore);
RUN_TEST("invalid1.graphml", /* should_parse = */ 0);
RUN_TEST("invalid2.graphml", /* should_parse = */ 1);
RUN_TEST("invalid3.graphml", /* should_parse = */ 0);
RUN_TEST("invalid4.graphml", /* should_parse = */ 0);
RUN_TEST("invalid5.graphml", /* should_parse = */ 0);
RUN_TEST("invalid6.graphml", /* should_parse = */ 0);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,70 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdio.h>
int test_file(const char* fname) {
FILE *ifile;
igraph_t g;
int retval;
ifile = fopen(fname, "r");
if (ifile == 0) {
return 1;
}
retval = igraph_read_graph_pajek(&g, ifile);
if (!retval) {
/* input was accepted, this is a bug; attempt to clean up after
* ourselves nevertheless */
igraph_destroy(&g);
fclose(ifile);
return 2;
}
fclose(ifile);
return 0;
}
#define RUN_TEST(fname) { \
index++; \
if (test_file(fname)) { \
return index; \
} \
}
int main(void) {
int index = 0;
/* Turn on attribute handling */
igraph_set_attribute_table(&igraph_cattribute_table);
/* We do not care about errors; all we care about is that the library
* should not segfault and should not accept invalid input either */
igraph_set_error_handler(igraph_error_handler_ignore);
RUN_TEST("invalid_pajek1.net");
RUN_TEST("invalid_pajek2.net");
RUN_TEST("invalid_pajek3.net");
return 0;
}
@@ -0,0 +1,463 @@
Creator "Mark Newman on Fri Jul 21 12:39:27 2006"
graph
[
ntde
[
id 1
]
node
[
id 2
]
node
[
id 3
]
node
[
id 4
]
node
[
id 5
]
node
[
id 6
]
node
[
id 7
]
node
[
id 8
]
node
[
id 9
]
node
[
id 10
]
node
[
id 11
]
node
[
id 12
]
node
[
id 13
]
node
[
id 14
]
node
[
id 15
]
node
[
id 16
]
node
[
id 17
]
node
[
id 18
]
node
[
id 19
]
node
[
id 20
]
node
[
id 21
]
node
[
id 22
]
node
[
id 23
]
node
[
id 24
]
node
[
id 25
]
node
[
id 26
]
node
[
id 27
]
node
[
id 28
]
node
[
id 29
]
node
[
id 30
]
node
[
id 31
]
node
[
id 32
]
node
[
id 33
]
node
[
id 34
]
edge
[
source 2
target 1
]
edge
[
source 3
target 1
]
edge
[
source 3
target 2
]
edge
[
source 4
target 1
]
edge
[
source 4
target 2
]
edge
[
source 4
target 3
]
edge
[
source 5
target 1
]
edge
[
source 2
target 1
]
edge
[
source 7
target 1
]
edge
[
source 7
target 5
]
edge
[
source 7
target 6
]
edge
[
source 8
target 1
]
edge
[
source 8
target 2
]
edge
[
source 8
target 3
]
edge
[
source 8
target 4
]
edge
[
source 9
target 1
]
edge
[
source 9
target 3
]
edge
[
source 10
target 3
]
edge
[
source 11
target 1
source 20
target 1
]
edge
[
source 20
target 2
]
edge
[
source 22
target 1
]
edge
[
source 22
target 2
]
edge
[
source 26
target 24
]
edge
[
source 26
target 25
]
edge
[
source 28
target 3
]
edge
[
source 28
target 24
]
edge
[
source 28
target 25
]
edge
[
source 29
target 3
]
edge
[
source 30
target 24
]
edge
[
source 30
target 27
]
edge
[
source 31
target 2
]
edge
[
source 31
target 9
]
edge
[
source 32
target 1
]
edge
[
source 32
target 25
]
edge
[
source 32
target 26
]
edge
[
source 32
target 29
]
edge
[
source 33
target 3
]
edge
[
source 33
target 9
]
edge
[
source 33
target 15
]
edge
[
source 33
target 16
]
edge
[
source 33
target 19
]
edge
[
source 33
target 21
]
edge
[
source 33
target 23
]
edge
[
source 33
target 24
]
edge
[
source 33
target 30
]
edge
[
source 33
target 31
]
edge
[
source 33
target 32
]
edge
[
source 34
target 9
]
edge
[
source 34
target 10
]
edge
[
source 34
target 14
]
edge
[
source 34
target 15
]
edge
[
source 34
target 16
]
edge
[
source 34
target 19
]
edge
[
source 34
target 20
]
edge
[
source 34
target 21
]
edge
[
source 34
target 23
]
edge
[
source 34
target 24
]
edge
[
source 34
target 27
]
edge
[
source 34
target 28
]
edge
[
source 34
target 29
]
edge
[
source 17
target 30
]
edge
[
source 34
target 31
]
edge
[
source 34
target 32
]
edge
[
source 34
target 33
]
]
@@ -0,0 +1,18 @@
<?xml version="1.5" encoding="UTF-8"?>
<!-- This file was written b JAVA GraphML Library.-->
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlnheuaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="d0" for="nodd" attr.name="color" attr.type="string">
<default>yellow</default>
</key>
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
<key id="d2" for="graph" attr.name="date" attr.type="string"></key>
<key id="d3" for="graph" attr.name="uòused" attr.type="string"></key>
<key id="d4" for="node" attr.name="gender" attr.type="boolean">
, <default>1</default>
</key>
<graph id="G" edgedefault="undirected">
<data key="d2">2006-11-12*</data>
<node idey="d0">blue</data>
</edge>
</graph>
</graphml>
@@ -0,0 +1 @@
d 1
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file wa2s written idJAVA GraphML Library.-->
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w4.org/2001/XM/graphml.graphdrawisd">
<key id="d0" for="node" attr.name="color" attr.type="string">
<default>yellow</default>
</key>
<key id="d1" for="edge" attr.name="weigrt" attr.type="double"/>
<key id="d2" for="graph" attr.ttr.type="string">
@ <default>yellow</default>we </key>
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
"http://graphml.graphdrawingg/2001/XMLrawing.org/xmlns/1.0/graphml.xsd">
<key id="d0" for="node" attr.name="color" attr.type="string">
<default>yellow</default>
</key>
<key id="d1" for="edge" attr.name="weight" attr.type="double"/>
<key id="d2" for="graph" attr.ttr.type="string">
@ <default>yellow</default>we </key>
<key id="d1" for="edge" attr.name="weight" attr.typ="unused" attr.type="string"></key>
<key id="d3" for="node" attr.name="gender" attr.type="boolean">
<default>1</default>
</key>
<graph id="G" edgedefaud="n0">
/edge>
</graph>
</graphml>
@@ -0,0 +1 @@
Version-0
@@ -0,0 +1,4 @@
graph[node[a
r
r P p
r d v]]
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- y.-->
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmxsi="httce"
>
<key id="d0" for="node" attr.name="y" attr.type="string">yellYw</key>
<key id="d1" for="edge" attr.name="wt" attr.type="do"/>
<key id="d2" for="graph" attr.name="date" attr.type="string"></key>
<key id="d3" for="graph" attr.name="ed" attr.type="string"></key>
<key id="d4" for="node" attr.name="gr" attr.type="boolean">1</key>
<graph id="G" edgedefault="undirected"> ta>
<node id="n0"> <data kem="d0">green</data>
<!-- ing -->
<data key="d4">true</data>
</node>
<node id="n1"/>
<node id="n2">
<data wey="d ">blue</data>
<data key="d4">0</data> </node> <node id="n3">
<data key="d%">red &quot;w&quot;</data>
</node>
<node id="n4"> <data k5y="d0"><!-- ey --></data> <data key="d4">false</data>
</node>
<node id="n5">
<data key="d0">t</data>
<data Hey="d4">
i <key id="sing" for="edge" ae="de"/>
<key id="" atype="double"/>
<key id="sinik" forype="double"/>
<key id="si" for="edge" attme="in" e="de"/>
<id="
@@ -0,0 +1 @@
graph[node[id 2]edge[source 2targetrgett 2]]
@@ -0,0 +1 @@
<graphml><key id="" xmlns:xi="http://graphml.graphdrawing.org/xmlns" xi:id=""
@@ -0,0 +1 @@
*Vertices 1 3
@@ -0,0 +1,3 @@
*Network TRALALA
*vertices 4 1
0 "3."
@@ -0,0 +1,2 @@
%foo
*Vertices 1 2 1
+167
View File
@@ -0,0 +1,167 @@
/*
igraph library.
Copyright (C) 2008-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdlib.h>
#include "core/indheap.h"
#include "test_utilities.h"
int main(void) {
igraph_vector_t elems;
igraph_2wheap_t Q;
igraph_int_t i;
igraph_real_t prev = IGRAPH_INFINITY;
igraph_rng_seed(igraph_rng_default(), 42); /* make tests deterministic */
igraph_vector_init(&elems, 100);
for (i = 0; i < igraph_vector_size(&elems); i++) {
VECTOR(elems)[i] = RNG_UNIF01();
}
igraph_2wheap_init(&Q, igraph_vector_size(&elems));
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_2wheap_push_with_index(&Q, i, VECTOR(elems)[i]);
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
if (VECTOR(elems)[i] != igraph_2wheap_get(&Q, i)) {
return 1;
}
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_int_t j;
igraph_real_t tmp = igraph_2wheap_max(&Q);
if (tmp > prev) {
return 2;
}
if (tmp != igraph_2wheap_delete_max_index(&Q, &j)) {
return 3;
}
if (VECTOR(elems)[j] != tmp) {
return 4;
}
prev = tmp;
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_2wheap_push_with_index(&Q, i, VECTOR(elems)[i]);
}
if (igraph_2wheap_size(&Q) != igraph_vector_size(&elems)) {
return 5;
}
for (i = 0; i < igraph_vector_size(&elems); i++) {
VECTOR(elems)[i] = RNG_UNIF01();
igraph_2wheap_modify(&Q, i, VECTOR(elems)[i]);
}
for (i = 0; i < igraph_vector_size(&elems); i++) {
if (VECTOR(elems)[i] != igraph_2wheap_get(&Q, i)) {
return 6;
}
}
prev = IGRAPH_INFINITY;
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_int_t j;
igraph_real_t tmp = igraph_2wheap_max(&Q);
if (tmp > prev) {
return 7;
}
if (tmp != igraph_2wheap_delete_max_index(&Q, &j)) {
return 8;
}
if (VECTOR(elems)[j] != tmp) {
return 9;
}
prev = tmp;
}
if (!igraph_2wheap_empty(&Q)) {
return 10;
}
if (igraph_2wheap_size(&Q) != 0) {
return 11;
}
igraph_2wheap_destroy(&Q);
igraph_vector_destroy(&elems);
/* Hand-made example */
#define MAX do { igraph_2wheap_delete_max(&Q); igraph_2wheap_check(&Q); } while (0)
#define PUSH(i,e) do { igraph_2wheap_push_with_index(&Q, (i), -(e)); igraph_2wheap_check(&Q); } while (0);
#define MOD(i, e) do { igraph_2wheap_modify(&Q, (i), -(e)); igraph_2wheap_check(&Q); } while (0)
igraph_2wheap_init(&Q, 21);
/* 0.00 [ 4] */ PUSH(4, 0);
/* MAX */ MAX;
/* 0.63 [11] */ PUSH(11, 0.63);
/* 0.05 [15] */ PUSH(15, 0.05);
/* MAX */ MAX;
/* 0.4 [12] */ PUSH(12, 0.4);
/* 0.4 [13] */ PUSH(13, 0.4);
/* 0.12 [16] */ PUSH(16, 0.12);
/* MAX */ MAX;
/* 1.1 [ 0] */ PUSH(0, 1.1);
/* 1.1 [14] */ PUSH(14, 1.1);
/* MAX */ MAX;
/* [11]/0.44 */ MOD(11, 0.44);
/* MAX */ MAX;
/* MAX */ MAX;
/* 1.1 [20] */ PUSH(20, 1.1);
/* MAX */ MAX;
/* 1.3 [ 7] */ PUSH(7, 1.3);
/* 1.7 [ 9] */ PUSH(9, 1.7);
/* MAX */ MAX;
/* 1.6 [19] */ PUSH(19, 1.6);
/* MAX */ MAX;
/* 2.1 [17] */ PUSH(17, 2.1);
/* 1.3 [18] */ PUSH(18, 1.3);
/* MAX */ MAX;
/* 2.3 [ 1] */ PUSH(1, 2.3);
/* 2.2 [ 5] */ PUSH(5, 2.2);
/* 2.3 [10] */ PUSH(10, 2.3);
/* MAX */ MAX;
/* [17]/1.5 */ MOD(17, 1.5);
/* MAX */ MAX;
/* 1.8 [ 6] */ PUSH(6, 1.8);
/* MAX */ MAX;
/* 1.3 [ 3] */ PUSH(3, 1.3);
/* [ 6]/1.3 */ MOD(6, 1.3);
/* MAX */ MAX;
/* 1.6 [ 8] */ PUSH(8, 1.6);
/* MAX */ MAX;
igraph_2wheap_destroy(&Q);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,257 @@
/*
igraph library.
Copyright (C) 2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdlib.h>
#include "test_utilities.h"
/* ----------------------------------------------------------- */
/* Vertices/edges with the same parity match */
igraph_bool_t compat_parity(const igraph_t *graph1,
const igraph_t *graph2,
const igraph_int_t g1_num,
const igraph_int_t g2_num,
void *arg) {
IGRAPH_UNUSED(graph1);
IGRAPH_UNUSED(graph2);
IGRAPH_UNUSED(arg);
return (g1_num % 2) == (g2_num % 2);
}
/* Nothing vertex/edge 0 in graph1 */
igraph_bool_t compat_not0(const igraph_t *graph1,
const igraph_t *graph2,
const igraph_int_t g1_num,
const igraph_int_t g2_num,
void *arg) {
IGRAPH_UNUSED(graph1);
IGRAPH_UNUSED(graph2);
IGRAPH_UNUSED(arg);
IGRAPH_UNUSED(g2_num);
return g1_num != 0;
}
int match_rings(void) {
igraph_t r1, r2;
igraph_bool_t iso;
igraph_int_t count;
igraph_ring(&r1, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_ring(&r2, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(1);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_parity, /*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (!iso) {
exit(2);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_not0, /*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (iso) {
exit(3);
}
/* ------- */
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_parity, /*arg=*/ 0);
if (!iso) {
exit(4);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_not0, /*arg=*/ 0);
if (iso) {
exit(5);
}
/* ------- */
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 20) {
exit(6);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_parity, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 10) {
exit(7);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 0) {
exit(8);
}
/* ------- */
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_parity,
/*arg=*/ 0);
if (count != 10) {
exit(9);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (count != 0) {
exit(10);
}
igraph_destroy(&r1);
igraph_destroy(&r2);
return 0;
}
int match_rings_open_closed(void) {
igraph_t ro, rc;
igraph_bool_t iso;
igraph_int_t count;
igraph_ring(&ro, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 0);
igraph_ring(&rc, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(31);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_parity, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(32);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (iso) {
exit(33);
}
/* ------- */
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_parity,
/*arg=*/ 0);
if (!iso) {
exit(34);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (!iso) {
exit(35);
}
/* ------- */
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 20) {
exit(36);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_parity,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 10) {
exit(37);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 0) {
exit(38);
}
/* ------- */
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
compat_parity, /*arg=*/ 0);
if (count != 10) {
exit(39);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (count != 2) {
exit(40);
}
igraph_destroy(&ro);
igraph_destroy(&rc);
return 0;
}
/* ----------------------------------------------------------- */
int main(void) {
match_rings();
match_rings_open_closed();
VERIFY_FINALLY_STACK();
return 0;
}
+305
View File
@@ -0,0 +1,305 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void print_params(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
printf(igraph_is_directed(graph) ? "directed; " : "undirected; ");
switch (mode) {
case IGRAPH_ALL: printf("ALL; "); break;
case IGRAPH_OUT: printf("OUT; "); break;
case IGRAPH_IN : printf("IN; "); break;
}
switch (loops) {
case IGRAPH_NO_LOOPS: printf("NO_LOOPS; "); break;
case IGRAPH_LOOPS_ONCE: printf("LOOPS_ONCE; "); break;
case IGRAPH_LOOPS_TWICE: printf("LOOPS_TWICE; "); break;
}
}
void print_multiple(igraph_bool_t multiple) {
printf(multiple ? "MULTIPLE; " : "NO_MULTIPLE; ");
}
/* Print adjacency list based on igraph_neighbors() */
void print_adj1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_vector_int_t neis;
print_params(graph, mode, loops);
print_multiple(multiple);
printf("\n");
igraph_vector_int_init(&neis, 0);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
igraph_neighbors(graph, &neis, v, mode, loops, multiple);
print_vector_int(&neis);
}
igraph_vector_int_destroy(&neis);
}
/* Print adjacency list based on igraph_adjlist_init() */
void print_adj2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_adjlist_t al;
print_params(graph, mode, loops);
print_multiple(multiple);
printf("\n");
igraph_adjlist_init(graph, &al, mode, loops, multiple);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
print_vector_int(igraph_adjlist_get(&al, v));
}
igraph_adjlist_destroy(&al);
}
/* Print incidence list based on igraph_incident() */
void print_inc1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_vector_int_t incs;
print_params(graph, mode, loops);
printf("\n");
igraph_vector_int_init(&incs, 0);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
igraph_incident(graph, &incs, v, mode, loops);
print_vector_int(&incs);
}
igraph_vector_int_destroy(&incs);
}
/* Print incidence list based on igraph_inclist_init() */
void print_inc2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_inclist_t il;
print_params(graph, mode, loops);
printf("\n");
igraph_inclist_init(graph, &il, mode, loops);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
print_vector_int(igraph_inclist_get(&il, v));
}
igraph_inclist_destroy(&il);
}
/* Verifies that igraph_neighbors() and igraph_incident() produce results in the same order. */
void verify_ordering1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_vector_int_t neis, incs;
igraph_int_t vcount = igraph_vcount(graph);
if (! igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
igraph_vector_int_init(&neis, 0);
igraph_vector_int_init(&incs, 0);
for (igraph_int_t v=0; v < vcount; v++) {
igraph_neighbors(graph, &neis, v, mode, loops, IGRAPH_MULTIPLE);
igraph_incident(graph, &incs, v, mode, loops);
igraph_int_t n = igraph_vector_int_size(&neis);
IGRAPH_ASSERT(igraph_vector_int_size(&incs) == n);
for (igraph_int_t i=0; i < n; i++) {
igraph_int_t u1, u2;
u1 = VECTOR(neis)[i];
switch (mode) {
case IGRAPH_ALL: u2 = IGRAPH_OTHER(graph, VECTOR(incs)[i], v); break;
case IGRAPH_OUT: u2 = IGRAPH_TO(graph, VECTOR(incs)[i]); break;
case IGRAPH_IN: u2 = IGRAPH_FROM(graph, VECTOR(incs)[i]); break;
}
if (u1 != u2) {
IGRAPH_FATALF(
"For vertex %d, the %dth neighbor vertex between adj (%d) and inc (%d) differs.",
(int) v, (int) i, (int) u1, (int) u2
);
}
}
}
igraph_vector_int_destroy(&incs);
igraph_vector_int_destroy(&neis);
}
/* Verifies that igraph_adjlist_init() and igraph_inclist_init() produce results in the same order. */
void verify_ordering2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_adjlist_t al;
igraph_inclist_t il;
igraph_int_t vcount = igraph_vcount(graph);
if (! igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
igraph_adjlist_init(graph, &al, mode, loops, IGRAPH_MULTIPLE);
igraph_inclist_init(graph, &il, mode, loops);
for (igraph_int_t v=0; v < vcount; v++) {
igraph_vector_int_t *neis = igraph_adjlist_get(&al, v);
igraph_vector_int_t *incs = igraph_inclist_get(&il, v);
igraph_int_t n = igraph_vector_int_size(neis);
IGRAPH_ASSERT(igraph_vector_int_size(incs) == n);
for (igraph_int_t i=0; i < n; i++) {
igraph_int_t u1, u2;
u1 = VECTOR(*neis)[i];
switch (mode) {
case IGRAPH_ALL: u2 = IGRAPH_OTHER(graph, VECTOR(*incs)[i], v); break;
case IGRAPH_OUT: u2 = IGRAPH_TO(graph, VECTOR(*incs)[i]); break;
case IGRAPH_IN: u2 = IGRAPH_FROM(graph, VECTOR(*incs)[i]); break;
}
if (u1 != u2) {
IGRAPH_FATALF(
"For vertex %d, the %dth neighbor vertex between adj (%d) and inc (%d) differs.",
(int) v, (int) i, (int) u1, (int) u2
);
}
}
}
igraph_adjlist_destroy(&al);
igraph_inclist_destroy(&il);
}
int main(void) {
igraph_t dg, ug;
igraph_small(&dg, 7, IGRAPH_DIRECTED,
// 0 1 2 3 4 5 6 7 8 9 10 11 12
4,4, 0,3, 0,3, 2,3, 1,4, 2,4, 3,4, 3,2, 4,4, 2,3, 1,1, 6,6, 6,6,
-1);
igraph_copy(&ug, &dg);
igraph_to_undirected(&ug, IGRAPH_TO_UNDIRECTED_EACH, NULL);
printf("UNDIRECTED\n\n");
printf("igraph_neighbors()\n");
print_adj1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nigraph_inclist_init()\n");
print_inc2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nDIRECTED ALL\n\n");
printf("igraph_neighbors()\n");
print_adj1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nigraph_inclist_init()\n");
print_inc2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nDIRECTED OUT\n\n");
printf("igraph_neighbors()\n");
print_adj1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
print_inc1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
printf("\nigraph_inclist_init()\n");
print_inc2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
print_inc2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
/* Verify that neighbour lists (adjlist) and incident edge lists (inclist)
* have the same ordering with all parameter combinations. */
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
verify_ordering1(&dg, IGRAPH_IN, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_IN, IGRAPH_LOOPS_ONCE);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
verify_ordering2(&dg, IGRAPH_IN, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_IN, IGRAPH_LOOPS_ONCE);
igraph_destroy(&ug);
igraph_destroy(&dg);
VERIFY_FINALLY_STACK();
return 0;
}
+285
View File
@@ -0,0 +1,285 @@
UNDIRECTED
igraph_neighbors()
undirected; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
undirected; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_adjlist_init()
undirected; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
undirected; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_incident()
undirected; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
undirected; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 8 0 )
5: ( )
6: ( 12 11 12 11 )
igraph_inclist_init()
undirected; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
undirected; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 8 0 )
5: ( )
6: ( 12 11 12 11 )
DIRECTED ALL
igraph_neighbors()
directed; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
directed; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_adjlist_init()
directed; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
directed; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_incident()
directed; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
directed; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 8 0 0 )
5: ( )
6: ( 12 12 11 11 )
igraph_inclist_init()
directed; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
directed; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 8 0 0 )
5: ( )
6: ( 12 12 11 11 )
DIRECTED OUT
igraph_neighbors()
directed; OUT; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( 4 4 )
5: ( )
6: ( 6 6 )
igraph_adjlist_init()
directed; OUT; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( 4 4 )
5: ( )
6: ( 6 6 )
igraph_incident()
directed; OUT; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( 8 0 )
5: ( )
6: ( 12 11 )
igraph_inclist_init()
directed; OUT; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( 8 0 )
5: ( )
6: ( 12 11 )
@@ -0,0 +1,348 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int test_simple_trees(void) {
igraph_t g, g2;
igraph_adjlist_t adjlist;
igraph_bool_t iso;
/* Directed, out */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_OUT);
igraph_adjlist_init(&g, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_OUT, /*duplicate=*/ 0);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
/* Directed, in */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_OUT);
igraph_adjlist_init(&g, &adjlist, IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_IN, /*duplicate=*/ 0);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
/* Undirected */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_UNDIRECTED);
igraph_adjlist_init(&g, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_ALL, /*duplicate=*/ 1);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
return 0;
}
#define TEST_ADJLIST(label, mode, loops, multiple) { \
igraph_adjlist_init(&g, &adjlist, mode, loops, multiple); \
printf(label ": "); \
print_adjlist(&adjlist); \
printf("\n"); \
igraph_adjlist_destroy(&adjlist); \
}
#define TEST_LAZY_ADJLIST(label, mode, loops, multiple) { \
igraph_lazy_adjlist_init(&g, &lazy_adjlist, mode, loops, multiple); \
printf(label ": "); \
print_lazy_adjlist(&lazy_adjlist); \
printf("\n"); \
igraph_lazy_adjlist_destroy(&lazy_adjlist); \
}
int test_loop_elimination_for_undirected_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 0,
0, 1, 0, 3,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4,
-1
);
printf("Testing loop edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_ADJLIST("Loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy loop edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_LAZY_ADJLIST("Loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_loop_elimination_for_directed_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 1,
0, 1, 0, 3,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4,
-1
);
printf("Testing loop edge elimination in directed graph\n\n");
TEST_ADJLIST("In-edges, loops eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy loop edge elimination in directed graph\n\n");
TEST_LAZY_ADJLIST("In-edges, loops eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_multiedge_elimination_for_undirected_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 0,
0, 1, 0, 3, 0, 8,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4, 4, 5, 4, 5, 4, 5,
5, 6,
6, 7, 6, 8,
8, 0,
-1
);
printf("Testing multiple edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_ADJLIST("Loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy multiple edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_LAZY_ADJLIST("Loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_multiedge_elimination_for_directed_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 1,
0, 1, 0, 3, 0, 8,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4, 4, 5, 4, 5, 4, 5,
5, 6,
6, 7, 6, 8,
8, 0,
-1
);
printf("Testing multiple edge elimination in directed graph\n\n");
TEST_ADJLIST("In-edges, loops also eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops also eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy multiple edge elimination in directed graph\n\n");
TEST_LAZY_ADJLIST("In-edges, loops also eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops also eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_caching(void) {
igraph_t g_simple, g_loop, g_multiloop, g_multi, g_multi_and_loop;
char *g_desc[] = {"simple", "loop", "multiloop", "multi", "multi and loop"};
igraph_adjlist_t adjlist;
igraph_loops_t loops[] = {IGRAPH_NO_LOOPS, IGRAPH_LOOPS_ONCE, IGRAPH_LOOPS_TWICE};
igraph_bool_t multiple[] = {IGRAPH_NO_MULTIPLE, IGRAPH_MULTIPLE};
igraph_neimode_t modes[] = {IGRAPH_OUT, IGRAPH_ALL};
igraph_vector_int_t edge;
igraph_int_t vloop[] = {0,0};
igraph_int_t vmult[] = {0,1};
igraph_full(&g_simple, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_loop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multiloop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multi, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multi_and_loop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
edge = igraph_vector_int_view(vloop, 2);
igraph_add_edges(&g_loop, &edge, NULL);
igraph_add_edges(&g_multiloop, &edge, NULL);
igraph_add_edges(&g_multiloop, &edge, NULL);
igraph_add_edges(&g_multi_and_loop, &edge, NULL);
edge = igraph_vector_int_view(vmult, 2);
igraph_add_edges(&g_multi, &edge, NULL);
igraph_add_edges(&g_multi_and_loop, &edge, NULL);
igraph_t *graphs[] = {&g_simple, &g_loop, &g_multiloop, &g_multi, &g_multi_and_loop};
for (int g = 0; g < 5; g++) {
for (int loop = 0; loop < 3; loop++) {
for (int multi = 0; multi < 2; multi++) {
for (int mode = 0; mode < 2; mode++) {
printf("graph: %s, loop: %d multi: %d, mode: %d\n", g_desc[g], loop, multi, mode);
igraph_invalidate_cache(graphs[g]);
igraph_adjlist_init(graphs[g], &adjlist, modes[mode], loops[loop], multiple[multi]);
if (!igraph_i_property_cache_has(graphs[g], IGRAPH_PROP_HAS_LOOP)) {
printf("loop not cached\n");
} else {
printf("loop cached: %d\n", igraph_i_property_cache_get_bool(graphs[g], IGRAPH_PROP_HAS_LOOP));
}
if (!igraph_i_property_cache_has(graphs[g], IGRAPH_PROP_HAS_MULTI)) {
printf("multi not cached\n");
} else {
printf("multi cached: %d\n", igraph_i_property_cache_get_bool(graphs[g], IGRAPH_PROP_HAS_MULTI));
}
igraph_adjlist_destroy(&adjlist);
}
}
}
igraph_destroy(graphs[g]);
}
return 0;
}
int main(void) {
RUN_TEST(test_simple_trees);
RUN_TEST(test_loop_elimination_for_undirected_graph);
RUN_TEST(test_loop_elimination_for_directed_graph);
RUN_TEST(test_multiedge_elimination_for_undirected_graph);
RUN_TEST(test_multiedge_elimination_for_directed_graph);
RUN_TEST(test_caching);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,692 @@
Testing loop edge elimination in undirected graph
Loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
Loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
Loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing lazy loop edge elimination in undirected graph
Loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
Loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
Loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing loop edge elimination in directed graph
In-edges, loops eliminated: {
0: ( 3 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
}
In-edges, loops listed once: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
Out-edges, loops eliminated: {
0: ( 1 3 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( )
}
Out-edges, loops listed once: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
In- and out-edges, loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing lazy loop edge elimination in directed graph
In-edges, loops eliminated: {
0: ( 3 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
}
In-edges, loops listed once: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
Out-edges, loops eliminated: {
0: ( 1 3 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( )
}
Out-edges, loops listed once: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
In- and out-edges, loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing multiple edge elimination in undirected graph
Loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing lazy multiple edge elimination in undirected graph
Loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing multiple edge elimination in directed graph
In-edges, loops also eliminated: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
Out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
In- and out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing lazy multiple edge elimination in directed graph
In-edges, loops also eliminated: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
Out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
In- and out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
graph: simple, loop: 0 multi: 0, mode: 0
loop cached: 0
multi cached: 0
graph: simple, loop: 0 multi: 0, mode: 1
loop cached: 0
multi cached: 0
graph: simple, loop: 0 multi: 1, mode: 0
loop cached: 0
multi not cached
graph: simple, loop: 0 multi: 1, mode: 1
loop cached: 0
multi not cached
graph: simple, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: simple, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: simple, loop: 1 multi: 1, mode: 0
loop not cached
multi not cached
graph: simple, loop: 1 multi: 1, mode: 1
loop not cached
multi not cached
graph: simple, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: simple, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: simple, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: simple, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: loop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 0
graph: loop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 0
graph: loop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: loop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: loop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: loop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: loop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: loop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: loop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: loop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: loop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: loop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multiloop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 1
graph: multiloop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 1
graph: multiloop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multiloop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multiloop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multiloop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multiloop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multiloop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multiloop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multiloop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multiloop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multiloop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi, loop: 0 multi: 0, mode: 0
loop cached: 0
multi cached: 1
graph: multi, loop: 0 multi: 0, mode: 1
loop cached: 0
multi cached: 1
graph: multi, loop: 0 multi: 1, mode: 0
loop cached: 0
multi not cached
graph: multi, loop: 0 multi: 1, mode: 1
loop cached: 0
multi not cached
graph: multi, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi, loop: 1 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi, loop: 1 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi and loop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 1
graph: multi and loop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 1
graph: multi and loop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multi and loop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multi and loop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi and loop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi and loop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multi and loop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multi and loop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi and loop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi and loop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi and loop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <math.h>
#include <float.h>
#include "test_utilities.h"
int main(void) {
igraph_matrix_t rm1, rm2;
igraph_matrix_complex_t cm1, cm2;
const igraph_int_t nrow = 50, ncol = 60;
igraph_rng_seed(igraph_rng_default(), 97);
/* Real matrices */
igraph_matrix_init(&rm1, nrow, ncol);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(rm1, i, j) = RNG_UNIF(0.0, 3.0);
}
}
igraph_matrix_init_copy(&rm2, &rm1);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(rm2, i, j) = pow(MATRIX(rm2, i, j), 1 / 7.0);
MATRIX(rm2, i, j) = pow(MATRIX(rm2, i, j), 7.0);
}
}
IGRAPH_ASSERT(igraph_matrix_all_almost_e(&rm1, &rm2, 4*DBL_EPSILON));
MATRIX(rm2, 0, 0) *= 2;
IGRAPH_ASSERT(! igraph_matrix_all_almost_e(&rm1, &rm2, 4*DBL_EPSILON));
igraph_matrix_destroy(&rm2);
igraph_matrix_destroy(&rm1);
/* Complex matrices */
igraph_matrix_complex_init(&cm1, nrow, ncol);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
IGRAPH_REAL(MATRIX(cm1, i, j)) = RNG_NORMAL(0,1);
IGRAPH_IMAG(MATRIX(cm1, i, j)) = RNG_NORMAL(0,1);
}
}
igraph_matrix_complex_init_copy(&cm2, &cm1);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(cm2, i, j) = igraph_complex_pow_real(MATRIX(cm2, i, j), 1 / 7.0);
MATRIX(cm2, i, j) = igraph_complex_pow_real(MATRIX(cm2, i, j), 7.0);
}
}
IGRAPH_ASSERT(igraph_matrix_complex_all_almost_e(&cm1, &cm2, 8*DBL_EPSILON));
MATRIX(cm2, 0, 0) = igraph_complex_mul(MATRIX(cm2, 0, 0), MATRIX(cm2, 1, 1));
IGRAPH_ASSERT(! igraph_matrix_complex_all_almost_e(&cm1, &cm2, 8*DBL_EPSILON));
igraph_matrix_complex_destroy(&cm2);
igraph_matrix_complex_destroy(&cm1);
VERIFY_FINALLY_STACK();
return 0;
}

Some files were not shown because too many files have changed in this diff Show More