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
@@ -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;
}