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
+167
View File
@@ -0,0 +1,167 @@
/*
igraph library.
Copyright (C) 2008-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdlib.h>
#include "core/indheap.h"
#include "test_utilities.h"
int main(void) {
igraph_vector_t elems;
igraph_2wheap_t Q;
igraph_int_t i;
igraph_real_t prev = IGRAPH_INFINITY;
igraph_rng_seed(igraph_rng_default(), 42); /* make tests deterministic */
igraph_vector_init(&elems, 100);
for (i = 0; i < igraph_vector_size(&elems); i++) {
VECTOR(elems)[i] = RNG_UNIF01();
}
igraph_2wheap_init(&Q, igraph_vector_size(&elems));
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_2wheap_push_with_index(&Q, i, VECTOR(elems)[i]);
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
if (VECTOR(elems)[i] != igraph_2wheap_get(&Q, i)) {
return 1;
}
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_int_t j;
igraph_real_t tmp = igraph_2wheap_max(&Q);
if (tmp > prev) {
return 2;
}
if (tmp != igraph_2wheap_delete_max_index(&Q, &j)) {
return 3;
}
if (VECTOR(elems)[j] != tmp) {
return 4;
}
prev = tmp;
}
/*****/
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_2wheap_push_with_index(&Q, i, VECTOR(elems)[i]);
}
if (igraph_2wheap_size(&Q) != igraph_vector_size(&elems)) {
return 5;
}
for (i = 0; i < igraph_vector_size(&elems); i++) {
VECTOR(elems)[i] = RNG_UNIF01();
igraph_2wheap_modify(&Q, i, VECTOR(elems)[i]);
}
for (i = 0; i < igraph_vector_size(&elems); i++) {
if (VECTOR(elems)[i] != igraph_2wheap_get(&Q, i)) {
return 6;
}
}
prev = IGRAPH_INFINITY;
for (i = 0; i < igraph_vector_size(&elems); i++) {
igraph_int_t j;
igraph_real_t tmp = igraph_2wheap_max(&Q);
if (tmp > prev) {
return 7;
}
if (tmp != igraph_2wheap_delete_max_index(&Q, &j)) {
return 8;
}
if (VECTOR(elems)[j] != tmp) {
return 9;
}
prev = tmp;
}
if (!igraph_2wheap_empty(&Q)) {
return 10;
}
if (igraph_2wheap_size(&Q) != 0) {
return 11;
}
igraph_2wheap_destroy(&Q);
igraph_vector_destroy(&elems);
/* Hand-made example */
#define MAX do { igraph_2wheap_delete_max(&Q); igraph_2wheap_check(&Q); } while (0)
#define PUSH(i,e) do { igraph_2wheap_push_with_index(&Q, (i), -(e)); igraph_2wheap_check(&Q); } while (0);
#define MOD(i, e) do { igraph_2wheap_modify(&Q, (i), -(e)); igraph_2wheap_check(&Q); } while (0)
igraph_2wheap_init(&Q, 21);
/* 0.00 [ 4] */ PUSH(4, 0);
/* MAX */ MAX;
/* 0.63 [11] */ PUSH(11, 0.63);
/* 0.05 [15] */ PUSH(15, 0.05);
/* MAX */ MAX;
/* 0.4 [12] */ PUSH(12, 0.4);
/* 0.4 [13] */ PUSH(13, 0.4);
/* 0.12 [16] */ PUSH(16, 0.12);
/* MAX */ MAX;
/* 1.1 [ 0] */ PUSH(0, 1.1);
/* 1.1 [14] */ PUSH(14, 1.1);
/* MAX */ MAX;
/* [11]/0.44 */ MOD(11, 0.44);
/* MAX */ MAX;
/* MAX */ MAX;
/* 1.1 [20] */ PUSH(20, 1.1);
/* MAX */ MAX;
/* 1.3 [ 7] */ PUSH(7, 1.3);
/* 1.7 [ 9] */ PUSH(9, 1.7);
/* MAX */ MAX;
/* 1.6 [19] */ PUSH(19, 1.6);
/* MAX */ MAX;
/* 2.1 [17] */ PUSH(17, 2.1);
/* 1.3 [18] */ PUSH(18, 1.3);
/* MAX */ MAX;
/* 2.3 [ 1] */ PUSH(1, 2.3);
/* 2.2 [ 5] */ PUSH(5, 2.2);
/* 2.3 [10] */ PUSH(10, 2.3);
/* MAX */ MAX;
/* [17]/1.5 */ MOD(17, 1.5);
/* MAX */ MAX;
/* 1.8 [ 6] */ PUSH(6, 1.8);
/* MAX */ MAX;
/* 1.3 [ 3] */ PUSH(3, 1.3);
/* [ 6]/1.3 */ MOD(6, 1.3);
/* MAX */ MAX;
/* 1.6 [ 8] */ PUSH(8, 1.6);
/* MAX */ MAX;
igraph_2wheap_destroy(&Q);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,257 @@
/*
igraph library.
Copyright (C) 2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdlib.h>
#include "test_utilities.h"
/* ----------------------------------------------------------- */
/* Vertices/edges with the same parity match */
igraph_bool_t compat_parity(const igraph_t *graph1,
const igraph_t *graph2,
const igraph_int_t g1_num,
const igraph_int_t g2_num,
void *arg) {
IGRAPH_UNUSED(graph1);
IGRAPH_UNUSED(graph2);
IGRAPH_UNUSED(arg);
return (g1_num % 2) == (g2_num % 2);
}
/* Nothing vertex/edge 0 in graph1 */
igraph_bool_t compat_not0(const igraph_t *graph1,
const igraph_t *graph2,
const igraph_int_t g1_num,
const igraph_int_t g2_num,
void *arg) {
IGRAPH_UNUSED(graph1);
IGRAPH_UNUSED(graph2);
IGRAPH_UNUSED(arg);
IGRAPH_UNUSED(g2_num);
return g1_num != 0;
}
int match_rings(void) {
igraph_t r1, r2;
igraph_bool_t iso;
igraph_int_t count;
igraph_ring(&r1, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_ring(&r2, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(1);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_parity, /*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (!iso) {
exit(2);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_not0, /*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (iso) {
exit(3);
}
/* ------- */
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_parity, /*arg=*/ 0);
if (!iso) {
exit(4);
}
igraph_isomorphic_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_not0, /*arg=*/ 0);
if (iso) {
exit(5);
}
/* ------- */
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 20) {
exit(6);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_parity, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 10) {
exit(7);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 0) {
exit(8);
}
/* ------- */
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_parity,
/*arg=*/ 0);
if (count != 10) {
exit(9);
}
igraph_count_isomorphisms_vf2(&r1, &r2, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (count != 0) {
exit(10);
}
igraph_destroy(&r1);
igraph_destroy(&r2);
return 0;
}
int match_rings_open_closed(void) {
igraph_t ro, rc;
igraph_bool_t iso;
igraph_int_t count;
igraph_ring(&ro, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 0);
igraph_ring(&rc, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(31);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_parity, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (!iso) {
exit(32);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (iso) {
exit(33);
}
/* ------- */
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_parity,
/*arg=*/ 0);
if (!iso) {
exit(34);
}
igraph_subisomorphic_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&iso, /*map12=*/ 0, /*map21=*/ 0,
/*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (!iso) {
exit(35);
}
/* ------- */
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 20) {
exit(36);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_parity,
/*edge_compat_fn=*/ 0, /*arg=*/ 0);
if (count != 10) {
exit(37);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, compat_not0, /*edge_compat_fn=*/ 0,
/*arg=*/ 0);
if (count != 0) {
exit(38);
}
/* ------- */
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0,
compat_parity, /*arg=*/ 0);
if (count != 10) {
exit(39);
}
igraph_count_subisomorphisms_vf2(&rc, &ro, /*colors(4x)*/ 0, 0, 0, 0,
&count, /*node_compat_fn=*/ 0, compat_not0,
/*arg=*/ 0);
if (count != 2) {
exit(40);
}
igraph_destroy(&ro);
igraph_destroy(&rc);
return 0;
}
/* ----------------------------------------------------------- */
int main(void) {
match_rings();
match_rings_open_closed();
VERIFY_FINALLY_STACK();
return 0;
}
+305
View File
@@ -0,0 +1,305 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void print_params(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
printf(igraph_is_directed(graph) ? "directed; " : "undirected; ");
switch (mode) {
case IGRAPH_ALL: printf("ALL; "); break;
case IGRAPH_OUT: printf("OUT; "); break;
case IGRAPH_IN : printf("IN; "); break;
}
switch (loops) {
case IGRAPH_NO_LOOPS: printf("NO_LOOPS; "); break;
case IGRAPH_LOOPS_ONCE: printf("LOOPS_ONCE; "); break;
case IGRAPH_LOOPS_TWICE: printf("LOOPS_TWICE; "); break;
}
}
void print_multiple(igraph_bool_t multiple) {
printf(multiple ? "MULTIPLE; " : "NO_MULTIPLE; ");
}
/* Print adjacency list based on igraph_neighbors() */
void print_adj1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_vector_int_t neis;
print_params(graph, mode, loops);
print_multiple(multiple);
printf("\n");
igraph_vector_int_init(&neis, 0);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
igraph_neighbors(graph, &neis, v, mode, loops, multiple);
print_vector_int(&neis);
}
igraph_vector_int_destroy(&neis);
}
/* Print adjacency list based on igraph_adjlist_init() */
void print_adj2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops, igraph_bool_t multiple) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_adjlist_t al;
print_params(graph, mode, loops);
print_multiple(multiple);
printf("\n");
igraph_adjlist_init(graph, &al, mode, loops, multiple);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
print_vector_int(igraph_adjlist_get(&al, v));
}
igraph_adjlist_destroy(&al);
}
/* Print incidence list based on igraph_incident() */
void print_inc1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_vector_int_t incs;
print_params(graph, mode, loops);
printf("\n");
igraph_vector_int_init(&incs, 0);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
igraph_incident(graph, &incs, v, mode, loops);
print_vector_int(&incs);
}
igraph_vector_int_destroy(&incs);
}
/* Print incidence list based on igraph_inclist_init() */
void print_inc2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_int_t vcount = igraph_vcount(graph);
igraph_inclist_t il;
print_params(graph, mode, loops);
printf("\n");
igraph_inclist_init(graph, &il, mode, loops);
for (igraph_int_t v=0; v < vcount; v++) {
printf("%3" IGRAPH_PRId ": ", v);
print_vector_int(igraph_inclist_get(&il, v));
}
igraph_inclist_destroy(&il);
}
/* Verifies that igraph_neighbors() and igraph_incident() produce results in the same order. */
void verify_ordering1(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_vector_int_t neis, incs;
igraph_int_t vcount = igraph_vcount(graph);
if (! igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
igraph_vector_int_init(&neis, 0);
igraph_vector_int_init(&incs, 0);
for (igraph_int_t v=0; v < vcount; v++) {
igraph_neighbors(graph, &neis, v, mode, loops, IGRAPH_MULTIPLE);
igraph_incident(graph, &incs, v, mode, loops);
igraph_int_t n = igraph_vector_int_size(&neis);
IGRAPH_ASSERT(igraph_vector_int_size(&incs) == n);
for (igraph_int_t i=0; i < n; i++) {
igraph_int_t u1, u2;
u1 = VECTOR(neis)[i];
switch (mode) {
case IGRAPH_ALL: u2 = IGRAPH_OTHER(graph, VECTOR(incs)[i], v); break;
case IGRAPH_OUT: u2 = IGRAPH_TO(graph, VECTOR(incs)[i]); break;
case IGRAPH_IN: u2 = IGRAPH_FROM(graph, VECTOR(incs)[i]); break;
}
if (u1 != u2) {
IGRAPH_FATALF(
"For vertex %d, the %dth neighbor vertex between adj (%d) and inc (%d) differs.",
(int) v, (int) i, (int) u1, (int) u2
);
}
}
}
igraph_vector_int_destroy(&incs);
igraph_vector_int_destroy(&neis);
}
/* Verifies that igraph_adjlist_init() and igraph_inclist_init() produce results in the same order. */
void verify_ordering2(const igraph_t *graph, igraph_neimode_t mode, igraph_loops_t loops) {
igraph_adjlist_t al;
igraph_inclist_t il;
igraph_int_t vcount = igraph_vcount(graph);
if (! igraph_is_directed(graph)) {
mode = IGRAPH_ALL;
}
igraph_adjlist_init(graph, &al, mode, loops, IGRAPH_MULTIPLE);
igraph_inclist_init(graph, &il, mode, loops);
for (igraph_int_t v=0; v < vcount; v++) {
igraph_vector_int_t *neis = igraph_adjlist_get(&al, v);
igraph_vector_int_t *incs = igraph_inclist_get(&il, v);
igraph_int_t n = igraph_vector_int_size(neis);
IGRAPH_ASSERT(igraph_vector_int_size(incs) == n);
for (igraph_int_t i=0; i < n; i++) {
igraph_int_t u1, u2;
u1 = VECTOR(*neis)[i];
switch (mode) {
case IGRAPH_ALL: u2 = IGRAPH_OTHER(graph, VECTOR(*incs)[i], v); break;
case IGRAPH_OUT: u2 = IGRAPH_TO(graph, VECTOR(*incs)[i]); break;
case IGRAPH_IN: u2 = IGRAPH_FROM(graph, VECTOR(*incs)[i]); break;
}
if (u1 != u2) {
IGRAPH_FATALF(
"For vertex %d, the %dth neighbor vertex between adj (%d) and inc (%d) differs.",
(int) v, (int) i, (int) u1, (int) u2
);
}
}
}
igraph_adjlist_destroy(&al);
igraph_inclist_destroy(&il);
}
int main(void) {
igraph_t dg, ug;
igraph_small(&dg, 7, IGRAPH_DIRECTED,
// 0 1 2 3 4 5 6 7 8 9 10 11 12
4,4, 0,3, 0,3, 2,3, 1,4, 2,4, 3,4, 3,2, 4,4, 2,3, 1,1, 6,6, 6,6,
-1);
igraph_copy(&ug, &dg);
igraph_to_undirected(&ug, IGRAPH_TO_UNDIRECTED_EACH, NULL);
printf("UNDIRECTED\n\n");
printf("igraph_neighbors()\n");
print_adj1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nigraph_inclist_init()\n");
print_inc2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nDIRECTED ALL\n\n");
printf("igraph_neighbors()\n");
print_adj1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nigraph_inclist_init()\n");
print_inc2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
print_inc2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
print_inc2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
printf("\nDIRECTED OUT\n\n");
printf("igraph_neighbors()\n");
print_adj1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
printf("\nigraph_adjlist_init()\n");
print_adj2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
print_adj2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
printf("\nigraph_incident()\n");
print_inc1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
print_inc1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
printf("\nigraph_inclist_init()\n");
print_inc2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
print_inc2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
/* Verify that neighbour lists (adjlist) and incident edge lists (inclist)
* have the same ordering with all parameter combinations. */
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering1(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering1(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering1(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
verify_ordering1(&dg, IGRAPH_IN, IGRAPH_NO_LOOPS);
verify_ordering1(&dg, IGRAPH_IN, IGRAPH_LOOPS_ONCE);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering2(&ug, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_ONCE);
verify_ordering2(&dg, IGRAPH_ALL, IGRAPH_LOOPS_TWICE);
verify_ordering2(&dg, IGRAPH_OUT, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_OUT, IGRAPH_LOOPS_ONCE);
verify_ordering2(&dg, IGRAPH_IN, IGRAPH_NO_LOOPS);
verify_ordering2(&dg, IGRAPH_IN, IGRAPH_LOOPS_ONCE);
igraph_destroy(&ug);
igraph_destroy(&dg);
VERIFY_FINALLY_STACK();
return 0;
}
+285
View File
@@ -0,0 +1,285 @@
UNDIRECTED
igraph_neighbors()
undirected; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
undirected; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_adjlist_init()
undirected; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
undirected; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_incident()
undirected; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
undirected; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 8 0 )
5: ( )
6: ( 12 11 12 11 )
igraph_inclist_init()
undirected; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
undirected; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
undirected; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 9 7 3 6 )
4: ( 4 5 6 8 0 8 0 )
5: ( )
6: ( 12 11 12 11 )
DIRECTED ALL
igraph_neighbors()
directed; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
directed; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_adjlist_init()
directed; ALL; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 )
5: ( )
6: ( 6 6 )
directed; ALL; LOOPS_TWICE; MULTIPLE;
0: ( 3 3 )
1: ( 1 1 4 )
2: ( 3 3 3 4 )
3: ( 0 0 2 2 2 4 )
4: ( 1 2 3 4 4 4 4 )
5: ( )
6: ( 6 6 6 6 )
igraph_incident()
directed; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
directed; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 8 0 0 )
5: ( )
6: ( 12 12 11 11 )
igraph_inclist_init()
directed; ALL; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 )
5: ( )
6: ( )
directed; ALL; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 0 )
5: ( )
6: ( 12 11 )
directed; ALL; LOOPS_TWICE;
0: ( 2 1 )
1: ( 10 10 4 )
2: ( 9 7 3 5 )
3: ( 2 1 7 9 3 6 )
4: ( 4 5 6 8 8 0 0 )
5: ( )
6: ( 12 12 11 11 )
DIRECTED OUT
igraph_neighbors()
directed; OUT; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( 4 4 )
5: ( )
6: ( 6 6 )
igraph_adjlist_init()
directed; OUT; NO_LOOPS; MULTIPLE;
0: ( 3 3 )
1: ( 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE; MULTIPLE;
0: ( 3 3 )
1: ( 1 4 )
2: ( 3 3 4 )
3: ( 2 4 )
4: ( 4 4 )
5: ( )
6: ( 6 6 )
igraph_incident()
directed; OUT; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( 8 0 )
5: ( )
6: ( 12 11 )
igraph_inclist_init()
directed; OUT; NO_LOOPS;
0: ( 2 1 )
1: ( 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( )
5: ( )
6: ( )
directed; OUT; LOOPS_ONCE;
0: ( 2 1 )
1: ( 10 4 )
2: ( 9 3 5 )
3: ( 7 6 )
4: ( 8 0 )
5: ( )
6: ( 12 11 )
@@ -0,0 +1,348 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int test_simple_trees(void) {
igraph_t g, g2;
igraph_adjlist_t adjlist;
igraph_bool_t iso;
/* Directed, out */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_OUT);
igraph_adjlist_init(&g, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_OUT, /*duplicate=*/ 0);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
/* Directed, in */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_OUT);
igraph_adjlist_init(&g, &adjlist, IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_IN, /*duplicate=*/ 0);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
/* Undirected */
igraph_kary_tree(&g, 42, 3, IGRAPH_TREE_UNDIRECTED);
igraph_adjlist_init(&g, &adjlist, IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
igraph_adjlist(&g2, &adjlist, IGRAPH_ALL, /*duplicate=*/ 1);
igraph_isomorphic(&g, &g2, &iso);
IGRAPH_ASSERT(iso);
igraph_adjlist_destroy(&adjlist);
igraph_destroy(&g2);
igraph_destroy(&g);
return 0;
}
#define TEST_ADJLIST(label, mode, loops, multiple) { \
igraph_adjlist_init(&g, &adjlist, mode, loops, multiple); \
printf(label ": "); \
print_adjlist(&adjlist); \
printf("\n"); \
igraph_adjlist_destroy(&adjlist); \
}
#define TEST_LAZY_ADJLIST(label, mode, loops, multiple) { \
igraph_lazy_adjlist_init(&g, &lazy_adjlist, mode, loops, multiple); \
printf(label ": "); \
print_lazy_adjlist(&lazy_adjlist); \
printf("\n"); \
igraph_lazy_adjlist_destroy(&lazy_adjlist); \
}
int test_loop_elimination_for_undirected_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 0,
0, 1, 0, 3,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4,
-1
);
printf("Testing loop edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_ADJLIST("Loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy loop edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_LAZY_ADJLIST("Loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_loop_elimination_for_directed_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 1,
0, 1, 0, 3,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4,
-1
);
printf("Testing loop edge elimination in directed graph\n\n");
TEST_ADJLIST("In-edges, loops eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy loop edge elimination in directed graph\n\n");
TEST_LAZY_ADJLIST("In-edges, loops eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_multiedge_elimination_for_undirected_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 0,
0, 1, 0, 3, 0, 8,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4, 4, 5, 4, 5, 4, 5,
5, 6,
6, 7, 6, 8,
8, 0,
-1
);
printf("Testing multiple edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_ADJLIST("Loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy multiple edge elimination in undirected graph\n\n");
/* We are testing IGRAPH_ALL, IGRAPH_IN and IGRAPH_OUT below; it should
* make no difference */
TEST_LAZY_ADJLIST("Loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Loops listed twice", IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_multiedge_elimination_for_directed_graph(void) {
igraph_t g;
igraph_adjlist_t adjlist;
igraph_lazy_adjlist_t lazy_adjlist;
igraph_small(
&g, 5, /* directed = */ 1,
0, 1, 0, 3, 0, 8,
1, 2,
2, 2, 2, 3,
3, 0, 3, 4,
4, 4, 4, 4, 4, 5, 4, 5, 4, 5,
5, 6,
6, 7, 6, 8,
8, 0,
-1
);
printf("Testing multiple edge elimination in directed graph\n\n");
TEST_ADJLIST("In-edges, loops also eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops also eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
printf("Testing lazy multiple edge elimination in directed graph\n\n");
TEST_LAZY_ADJLIST("In-edges, loops also eliminated", IGRAPH_IN, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once", IGRAPH_IN, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_IN, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops also eliminated", IGRAPH_OUT, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once", IGRAPH_OUT, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given",
IGRAPH_OUT, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops also eliminated", IGRAPH_ALL, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed once", IGRAPH_ALL, IGRAPH_LOOPS_ONCE, IGRAPH_NO_MULTIPLE);
TEST_LAZY_ADJLIST("In- and out-edges, loops listed twice", IGRAPH_ALL, IGRAPH_LOOPS_TWICE, IGRAPH_NO_MULTIPLE);
printf("============================================================\n\n");
igraph_destroy(&g);
return 0;
}
int test_caching(void) {
igraph_t g_simple, g_loop, g_multiloop, g_multi, g_multi_and_loop;
char *g_desc[] = {"simple", "loop", "multiloop", "multi", "multi and loop"};
igraph_adjlist_t adjlist;
igraph_loops_t loops[] = {IGRAPH_NO_LOOPS, IGRAPH_LOOPS_ONCE, IGRAPH_LOOPS_TWICE};
igraph_bool_t multiple[] = {IGRAPH_NO_MULTIPLE, IGRAPH_MULTIPLE};
igraph_neimode_t modes[] = {IGRAPH_OUT, IGRAPH_ALL};
igraph_vector_int_t edge;
igraph_int_t vloop[] = {0,0};
igraph_int_t vmult[] = {0,1};
igraph_full(&g_simple, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_loop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multiloop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multi, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
igraph_full(&g_multi_and_loop, 5, IGRAPH_UNDIRECTED, /*loops*/ 0);
edge = igraph_vector_int_view(vloop, 2);
igraph_add_edges(&g_loop, &edge, NULL);
igraph_add_edges(&g_multiloop, &edge, NULL);
igraph_add_edges(&g_multiloop, &edge, NULL);
igraph_add_edges(&g_multi_and_loop, &edge, NULL);
edge = igraph_vector_int_view(vmult, 2);
igraph_add_edges(&g_multi, &edge, NULL);
igraph_add_edges(&g_multi_and_loop, &edge, NULL);
igraph_t *graphs[] = {&g_simple, &g_loop, &g_multiloop, &g_multi, &g_multi_and_loop};
for (int g = 0; g < 5; g++) {
for (int loop = 0; loop < 3; loop++) {
for (int multi = 0; multi < 2; multi++) {
for (int mode = 0; mode < 2; mode++) {
printf("graph: %s, loop: %d multi: %d, mode: %d\n", g_desc[g], loop, multi, mode);
igraph_invalidate_cache(graphs[g]);
igraph_adjlist_init(graphs[g], &adjlist, modes[mode], loops[loop], multiple[multi]);
if (!igraph_i_property_cache_has(graphs[g], IGRAPH_PROP_HAS_LOOP)) {
printf("loop not cached\n");
} else {
printf("loop cached: %d\n", igraph_i_property_cache_get_bool(graphs[g], IGRAPH_PROP_HAS_LOOP));
}
if (!igraph_i_property_cache_has(graphs[g], IGRAPH_PROP_HAS_MULTI)) {
printf("multi not cached\n");
} else {
printf("multi cached: %d\n", igraph_i_property_cache_get_bool(graphs[g], IGRAPH_PROP_HAS_MULTI));
}
igraph_adjlist_destroy(&adjlist);
}
}
}
igraph_destroy(graphs[g]);
}
return 0;
}
int main(void) {
RUN_TEST(test_simple_trees);
RUN_TEST(test_loop_elimination_for_undirected_graph);
RUN_TEST(test_loop_elimination_for_directed_graph);
RUN_TEST(test_multiedge_elimination_for_undirected_graph);
RUN_TEST(test_multiedge_elimination_for_directed_graph);
RUN_TEST(test_caching);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,692 @@
Testing loop edge elimination in undirected graph
Loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
Loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
Loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing lazy loop edge elimination in undirected graph
Loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
Loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
Loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing loop edge elimination in directed graph
In-edges, loops eliminated: {
0: ( 3 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
}
In-edges, loops listed once: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
Out-edges, loops eliminated: {
0: ( 1 3 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( )
}
Out-edges, loops listed once: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
In- and out-edges, loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing lazy loop edge elimination in directed graph
In-edges, loops eliminated: {
0: ( 3 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
}
In-edges, loops listed once: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 4 )
}
Out-edges, loops eliminated: {
0: ( 1 3 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( )
}
Out-edges, loops listed once: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 4 )
}
In- and out-edges, loops eliminated: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 0 2 4 )
4: ( 3 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 3 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 0 2 4 )
4: ( 3 4 4 4 4 )
}
============================================================
Testing multiple edge elimination in undirected graph
Loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing lazy multiple edge elimination in undirected graph
Loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
Loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing multiple edge elimination in directed graph
In-edges, loops also eliminated: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
Out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
In- and out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
Testing lazy multiple edge elimination in directed graph
In-edges, loops also eliminated: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 )
3: ( 0 2 )
4: ( 3 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
In-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 3 8 )
1: ( 0 )
2: ( 1 2 )
3: ( 0 2 )
4: ( 3 4 )
5: ( 4 )
6: ( 5 )
7: ( 6 )
8: ( 0 6 )
}
Out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 3 )
3: ( 0 4 )
4: ( 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
Out-edges, loops listed once even if IGRAPH_LOOPS_TWICE is given: {
0: ( 1 3 8 )
1: ( 2 )
2: ( 2 3 )
3: ( 0 4 )
4: ( 4 5 )
5: ( 6 )
6: ( 7 8 )
7: ( )
8: ( 0 )
}
In- and out-edges, loops also eliminated: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 3 )
3: ( 0 2 4 )
4: ( 3 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed once: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 3 )
3: ( 0 2 4 )
4: ( 3 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
In- and out-edges, loops listed twice: {
0: ( 1 3 8 )
1: ( 0 2 )
2: ( 1 2 2 3 )
3: ( 0 2 4 )
4: ( 3 4 4 5 )
5: ( 4 6 )
6: ( 5 7 8 )
7: ( 6 )
8: ( 0 6 )
}
============================================================
graph: simple, loop: 0 multi: 0, mode: 0
loop cached: 0
multi cached: 0
graph: simple, loop: 0 multi: 0, mode: 1
loop cached: 0
multi cached: 0
graph: simple, loop: 0 multi: 1, mode: 0
loop cached: 0
multi not cached
graph: simple, loop: 0 multi: 1, mode: 1
loop cached: 0
multi not cached
graph: simple, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: simple, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: simple, loop: 1 multi: 1, mode: 0
loop not cached
multi not cached
graph: simple, loop: 1 multi: 1, mode: 1
loop not cached
multi not cached
graph: simple, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: simple, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: simple, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: simple, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: loop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 0
graph: loop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 0
graph: loop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: loop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: loop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 0
graph: loop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 0
graph: loop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: loop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: loop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: loop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: loop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: loop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multiloop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 1
graph: multiloop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 1
graph: multiloop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multiloop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multiloop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multiloop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multiloop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multiloop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multiloop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multiloop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multiloop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multiloop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi, loop: 0 multi: 0, mode: 0
loop cached: 0
multi cached: 1
graph: multi, loop: 0 multi: 0, mode: 1
loop cached: 0
multi cached: 1
graph: multi, loop: 0 multi: 1, mode: 0
loop cached: 0
multi not cached
graph: multi, loop: 0 multi: 1, mode: 1
loop cached: 0
multi not cached
graph: multi, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi, loop: 1 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi, loop: 1 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
graph: multi and loop, loop: 0 multi: 0, mode: 0
loop cached: 1
multi cached: 1
graph: multi and loop, loop: 0 multi: 0, mode: 1
loop cached: 1
multi cached: 1
graph: multi and loop, loop: 0 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multi and loop, loop: 0 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multi and loop, loop: 1 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi and loop, loop: 1 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi and loop, loop: 1 multi: 1, mode: 0
loop cached: 1
multi not cached
graph: multi and loop, loop: 1 multi: 1, mode: 1
loop cached: 1
multi not cached
graph: multi and loop, loop: 2 multi: 0, mode: 0
loop not cached
multi cached: 1
graph: multi and loop, loop: 2 multi: 0, mode: 1
loop not cached
multi cached: 1
graph: multi and loop, loop: 2 multi: 1, mode: 0
loop not cached
multi not cached
graph: multi and loop, loop: 2 multi: 1, mode: 1
loop not cached
multi not cached
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <math.h>
#include <float.h>
#include "test_utilities.h"
int main(void) {
igraph_matrix_t rm1, rm2;
igraph_matrix_complex_t cm1, cm2;
const igraph_int_t nrow = 50, ncol = 60;
igraph_rng_seed(igraph_rng_default(), 97);
/* Real matrices */
igraph_matrix_init(&rm1, nrow, ncol);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(rm1, i, j) = RNG_UNIF(0.0, 3.0);
}
}
igraph_matrix_init_copy(&rm2, &rm1);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(rm2, i, j) = pow(MATRIX(rm2, i, j), 1 / 7.0);
MATRIX(rm2, i, j) = pow(MATRIX(rm2, i, j), 7.0);
}
}
IGRAPH_ASSERT(igraph_matrix_all_almost_e(&rm1, &rm2, 4*DBL_EPSILON));
MATRIX(rm2, 0, 0) *= 2;
IGRAPH_ASSERT(! igraph_matrix_all_almost_e(&rm1, &rm2, 4*DBL_EPSILON));
igraph_matrix_destroy(&rm2);
igraph_matrix_destroy(&rm1);
/* Complex matrices */
igraph_matrix_complex_init(&cm1, nrow, ncol);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
IGRAPH_REAL(MATRIX(cm1, i, j)) = RNG_NORMAL(0,1);
IGRAPH_IMAG(MATRIX(cm1, i, j)) = RNG_NORMAL(0,1);
}
}
igraph_matrix_complex_init_copy(&cm2, &cm1);
for (igraph_int_t i=0; i < nrow; i++) {
for (igraph_int_t j=0; j < ncol; j++) {
MATRIX(cm2, i, j) = igraph_complex_pow_real(MATRIX(cm2, i, j), 1 / 7.0);
MATRIX(cm2, i, j) = igraph_complex_pow_real(MATRIX(cm2, i, j), 7.0);
}
}
IGRAPH_ASSERT(igraph_matrix_complex_all_almost_e(&cm1, &cm2, 8*DBL_EPSILON));
MATRIX(cm2, 0, 0) = igraph_complex_mul(MATRIX(cm2, 0, 0), MATRIX(cm2, 1, 1));
IGRAPH_ASSERT(! igraph_matrix_complex_all_almost_e(&cm1, &cm2, 8*DBL_EPSILON));
igraph_matrix_complex_destroy(&cm2);
igraph_matrix_complex_destroy(&cm1);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,162 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t graph;
igraph_vector_int_list_t paths, paths_edge;
igraph_vector_int_t nrgeo;
igraph_vector_t weights;
igraph_int_t from, to;
igraph_vector_int_list_init(&paths, 0);
igraph_vector_int_list_init(&paths_edge, 0);
igraph_vector_int_init(&nrgeo, 0);
igraph_vector_init(&weights, 0);
/* Note on the output:
* get_all_shortest_paths functions sort their output based on the
* last vertex only. Thus the ordering is not fully defined.
*
* This test does not currently canonicalize (i.e. sort)
* the result before printing it.
*/
printf("Singleton graph\n");
igraph_empty(&graph, 1, IGRAPH_UNDIRECTED);
from = 0; to = 0;
igraph_get_all_shortest_paths(&graph, NULL, &paths, NULL, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
printf("\nSingleton graph, weighted\n");
igraph_vector_resize(&weights, igraph_ecount(&graph));
igraph_vector_fill(&weights, 1);
igraph_get_all_shortest_paths(&graph, &weights, &paths, NULL, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
igraph_destroy(&graph);
printf("\nNo paths\n");
igraph_empty(&graph, 2, IGRAPH_UNDIRECTED);
from = 0; to = 1;
igraph_get_all_shortest_paths(&graph, NULL, &paths, &paths_edge, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
printf("Edge paths:\n");
print_vector_int_list(&paths_edge);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
igraph_destroy(&graph);
/* This graph has multi-edges (which induce multiple paths of the
* same length) as well as more paths of the same length between
* vertices 0 and 4. */
igraph_small(&graph, 0, IGRAPH_ADJ_UNDIRECTED,
0, 1, 1, 2, 2, 3, 3, 4, 0, 1, 2, 5, 4, 5, 1, 6, 6, 7, 3, 7,
-1);
from = 0; to = 4;
printf("\nUnweighted\n");
igraph_get_all_shortest_paths(&graph, NULL, &paths, &paths_edge, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
printf("Edge paths:\n");
print_vector_int_list(&paths_edge);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
printf("\nWeighted, uniform weights\n");
igraph_vector_resize(&weights, igraph_ecount(&graph));
igraph_vector_fill(&weights, 1.5); /* constant weights */
igraph_get_all_shortest_paths(&graph, &weights, &paths, &paths_edge, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
printf("Edge paths:\n");
print_vector_int_list(&paths_edge);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
printf("\nWeighted, multiple weighted shortest paths\n");
VECTOR(weights)[1] = 3.0; /* create path with one more hop, but equal weighted length */
VECTOR(weights)[4] = 2.0; /* break symmetry on pair of parallel edges */
igraph_get_all_shortest_paths(&graph, &weights, &paths, &paths_edge, &nrgeo, from, igraph_vss_1(to), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
printf("Edge paths:\n");
print_vector_int_list(&paths_edge);
IGRAPH_ASSERT(igraph_vector_int_list_size(&paths) == VECTOR(nrgeo)[to]);
igraph_vector_destroy(&weights);
igraph_destroy(&graph);
/* Graph is from https://github.com/igraph/rigraph/issues/314 */
printf("\nWeighted, multiple weighted shortest paths, testing tolerances\n");
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
0,3, 1,2, 2,5, 2,3, 2,4, 3,5, 5,6, 6,7, 1,8, 8,9, 4,10, 6,11, 8,12, 8,13, 4,14, 7,15,
-1);
igraph_real_t weights_raw[] = { 1.9617537, 0.9060834, 2.2165446, 1.6251956,
2.4473929, 0.5913490, 8.7093236, 2.8387330,
6.1225042, 20.7217776, 6.8027218, 16.3147479,
5.2605598, 6.6816853, 4.9482123, 1.8989790 };
/* Choose carefully: If not using tolerances, the result would be incorrect
* for starting vertices 5 and 6, but not for all other starting vertices. */
from = 6;
printf("From: %" IGRAPH_PRId ", to: all.\n", from);
weights = igraph_vector_view(weights_raw, sizeof(weights_raw) / sizeof(igraph_real_t));
igraph_get_all_shortest_paths(&graph, &weights, &paths, &paths_edge, &nrgeo, from, igraph_vss_all(), IGRAPH_ALL);
printf("Vertex paths:\n");
print_vector_int_list(&paths);
printf("Edge paths:\n");
print_vector_int_list(&paths_edge);
printf("nrgeo: ");
print_vector_int(&nrgeo);
igraph_vector_int_list_destroy(&paths);
igraph_vector_int_list_destroy(&paths_edge);
igraph_vector_int_destroy(&nrgeo);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,125 @@
Singleton graph
Vertex paths:
{
0: ( 0 )
}
Singleton graph, weighted
Vertex paths:
{
0: ( 0 )
}
No paths
Vertex paths:
{
}
Edge paths:
{
}
Unweighted
Vertex paths:
{
0: ( 0 1 2 5 4 )
1: ( 0 1 2 5 4 )
2: ( 0 1 2 3 4 )
3: ( 0 1 2 3 4 )
}
Edge paths:
{
0: ( 4 1 5 6 )
1: ( 0 1 5 6 )
2: ( 4 1 2 3 )
3: ( 0 1 2 3 )
}
Weighted, uniform weights
Vertex paths:
{
0: ( 0 1 2 3 4 )
1: ( 0 1 2 3 4 )
2: ( 0 1 2 5 4 )
3: ( 0 1 2 5 4 )
}
Edge paths:
{
0: ( 0 1 2 3 )
1: ( 4 1 2 3 )
2: ( 0 1 5 6 )
3: ( 4 1 5 6 )
}
Weighted, multiple weighted shortest paths
Vertex paths:
{
0: ( 0 1 2 3 4 )
1: ( 0 1 6 7 3 4 )
2: ( 0 1 2 5 4 )
}
Edge paths:
{
0: ( 0 1 2 3 )
1: ( 0 7 8 9 3 )
2: ( 0 1 5 6 )
}
Weighted, multiple weighted shortest paths, testing tolerances
From: 6, to: all.
Vertex paths:
{
0: ( 6 5 3 0 )
1: ( 6 5 3 2 1 )
2: ( 6 5 2 1 )
3: ( 6 5 3 2 )
4: ( 6 5 2 )
5: ( 6 5 3 )
6: ( 6 5 3 2 4 )
7: ( 6 5 2 4 )
8: ( 6 5 )
9: ( 6 )
10: ( 6 7 )
11: ( 6 5 3 2 1 8 )
12: ( 6 5 2 1 8 )
13: ( 6 5 3 2 1 8 9 )
14: ( 6 5 2 1 8 9 )
15: ( 6 5 3 2 4 10 )
16: ( 6 5 2 4 10 )
17: ( 6 11 )
18: ( 6 5 3 2 1 8 12 )
19: ( 6 5 2 1 8 12 )
20: ( 6 5 3 2 1 8 13 )
21: ( 6 5 2 1 8 13 )
22: ( 6 5 3 2 4 14 )
23: ( 6 5 2 4 14 )
24: ( 6 7 15 )
}
Edge paths:
{
0: ( 6 5 0 )
1: ( 6 5 3 1 )
2: ( 6 2 1 )
3: ( 6 5 3 )
4: ( 6 2 )
5: ( 6 5 )
6: ( 6 5 3 4 )
7: ( 6 2 4 )
8: ( 6 )
9: ( )
10: ( 7 )
11: ( 6 5 3 1 8 )
12: ( 6 2 1 8 )
13: ( 6 5 3 1 8 9 )
14: ( 6 2 1 8 9 )
15: ( 6 5 3 4 10 )
16: ( 6 2 4 10 )
17: ( 11 )
18: ( 6 5 3 1 8 12 )
19: ( 6 2 1 8 12 )
20: ( 6 5 3 1 8 13 )
21: ( 6 2 1 8 13 )
22: ( 6 5 3 4 14 )
23: ( 6 2 4 14 )
24: ( 7 15 )
}
nrgeo: ( 1 2 2 1 2 1 1 1 2 2 2 1 2 2 2 1 )
@@ -0,0 +1,357 @@
/*
igraph library.
Copyright (C) 2009-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 <stdio.h>
#include "test_utilities.h"
void assortativity_unnormalized(const igraph_t *graph, igraph_real_t *res, igraph_bool_t directed) {
if (! igraph_is_directed(graph)) {
directed = 0;
}
if (directed) {
igraph_vector_t outdeg, indeg;
igraph_vector_init(&outdeg, 0);
igraph_vector_init(&indeg, 0);
igraph_strength(graph, &outdeg, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, NULL);
igraph_strength(graph, &indeg, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, NULL);
igraph_assortativity(graph, NULL, &outdeg, &indeg, res, directed, false);
igraph_vector_destroy(&outdeg);
igraph_vector_destroy(&indeg);
} else {
igraph_vector_t deg;
igraph_vector_init(&deg, 0);
igraph_strength(graph, &deg, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS, NULL);
igraph_assortativity(graph, NULL, &deg, NULL, res, directed, false);
igraph_vector_destroy(&deg);
}
}
int main(void) {
igraph_t g;
igraph_real_t assort, assort2, assort_unnorm, modularity;
igraph_vector_t values;
igraph_vector_int_t types;
/* Assortativity based on vertex categories */
igraph_vector_int_init(&types, 0);
igraph_vector_init(&values, 0);
igraph_empty(&g, 0, IGRAPH_UNDIRECTED);
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Null graph nominal assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Null graph value assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_destroy(&g);
igraph_empty(&g, 1, IGRAPH_UNDIRECTED);
igraph_vector_int_resize(&types, 1);
VECTOR(types)[0] = 0;
igraph_vector_resize(&values, 1);
VECTOR(values)[0] = 0;
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Singleton graph nominal assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Singleton graph nominal assortativity, unnormalized: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Singleton graph value assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Singleton graph value assortativity, unnormalized: ");
igraph_real_printf(assort);
printf("\n");
igraph_add_edge(&g, 0, 0);
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Singleton graph with loop, nominal assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Singleton graph with loop, nominal assortativity, unnormalized: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Singleton graph with loop, value assortativity: ");
igraph_real_printf(assort);
printf("\n");
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Singleton graph with loop, value assortativity, unnormalized: ");
igraph_real_printf(assort);
printf("\n");
igraph_destroy(&g);
igraph_vector_destroy(&values);
printf("\n");
igraph_famous(&g, "zachary");
igraph_degree(&g, &types, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Karate club, normalized assortativity based on degree categories: %g\n", assort);
igraph_assortativity_nominal(&g, NULL, &types, &assort_unnorm, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Karate club, non-normalized assortativity based on degree categories: %g\n", assort_unnorm);
/* unnormalized assortativity based on categories is the same as modularity */
igraph_modularity(&g, &types, NULL, 1, IGRAPH_UNDIRECTED, &modularity);
IGRAPH_ASSERT(igraph_almost_equals(assort_unnorm, modularity, 1e-15));
igraph_destroy(&g);
igraph_vector_int_destroy(&types);
/*--------------------------------------*/
/* Assortativity based on vertex values */
igraph_famous(&g, "zachary");
igraph_vector_init_range(&values, 0, igraph_vcount(&g));
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ true);
printf("Assortativity based on values: %g\n", assort);
/* Assortativity is a Pearson correlation, thus it must be invariant to
* a constant shift in the values. */
igraph_vector_add_constant(&values, -5);
igraph_assortativity(&g, NULL, &values, NULL, &assort2, IGRAPH_UNDIRECTED, /* normalized */ true);
IGRAPH_ASSERT(igraph_almost_equals(assort, assort2, 1e-15));
igraph_assortativity(&g, NULL, &values, NULL, &assort, IGRAPH_UNDIRECTED, /* normalized */ false);
printf("Assortativity based on values, unnormalized: %g\n", assort);
/* Assortativity is a Pearson correlation, thus it must be invariant to
* a constant shift in the values. */
igraph_vector_add_constant(&values, -5);
igraph_assortativity(&g, NULL, &values, NULL, &assort2, IGRAPH_UNDIRECTED, /* normalized */ false);
IGRAPH_ASSERT(igraph_almost_equals(assort, assort2, 1e-15));
igraph_vector_destroy(&values);
igraph_destroy(&g);
/*--------------------------------*/
/* Assortativity based on degrees */
/* Normalized case */
printf("\nDegree assortativity, NORMALIZED\n");
igraph_famous(&g, "zachary");
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity: %g\n", assort);
igraph_destroy(&g);
/* Directed graph */
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, -1);
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed: %g\n", assort);
igraph_destroy(&g);
/* Verify handling of self-loops */
igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0,1, 1,2, 2,0, 0,3, 3,3, -1);
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, undirected, with self-loop: %g\n", assort);
igraph_destroy(&g);
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, 2,2, -1);
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed, with self-loop: %g\n", assort);
igraph_destroy(&g);
/* Verify handling of multi-edges */
igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0,1, 1,2, 2,0, 0,3, 1,2, -1);
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, undirected, with multi-edges: %g\n", assort);
igraph_destroy(&g);
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, 0,2, -1);
igraph_assortativity_degree(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed, with multi-edges: %g\n", assort);
igraph_destroy(&g);
/* Unnormalized case */
printf("\nDegree assortativity, UNNORMALIZED\n");
igraph_famous(&g, "zachary");
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity: %g\n", assort);
igraph_destroy(&g);
/* Directed graph */
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, -1);
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed: %g\n", assort);
igraph_destroy(&g);
/* Verify handling of self-loops */
igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0,1, 1,2, 2,0, 0,3, 3,3, -1);
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, undirected, with self-loop: %g\n", assort);
igraph_destroy(&g);
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, 2,2, -1);
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed, with self-loop: %g\n", assort);
igraph_destroy(&g);
/* Verify handling of multi-edges */
igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0,1, 1,2, 2,0, 0,3, 1,2, -1);
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, undirected, with multi-edges: %g\n", assort);
igraph_destroy(&g);
igraph_small(&g, 0, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 0,3, 3,2, 0,2, -1);
assortativity_unnormalized(&g, &assort, /*directed=*/ 1);
printf("Degree assortativity, directed, with multi-edges: %g\n", assort);
igraph_destroy(&g);
/*------------------*/
/* Football network */
igraph_int_t football_types[] = {
7, 0, 2, 3, 7, 3, 2, 8, 8, 7, 3, 10, 6, 2, 6, 2, 7, 9, 6, 1, 9, 8, 8, 7, 10, 0, 6, 9,
11, 1, 1, 6, 2, 0, 6, 1, 5, 0, 6, 2, 3, 7, 5, 6, 4, 0, 11, 2, 4, 11, 10, 8, 3, 11, 6,
1, 9, 4, 11, 10, 2, 6, 9, 10, 2, 9, 4, 11, 8, 10, 9, 6, 3, 11, 3, 4, 9, 8, 8, 1, 5, 3,
5, 11, 3, 6, 4, 9, 11, 0, 5, 4, 4, 7, 1, 9, 9, 10, 3, 6, 2, 1, 3, 0, 7, 0, 2, 3, 8, 0,
4, 8, 4, 9, 11
};
printf("\nFootball network: ");
igraph_small(&g, sizeof(football_types) / sizeof(football_types[0]),
IGRAPH_UNDIRECTED,
0, 1, 2, 3, 0, 4, 4, 5, 3, 5, 2, 6, 6, 7, 7, 8, 8, 9, 0, 9, 4, 9, 5, 10, 10, 11, 5, 11,
3, 11, 12, 13, 2, 13, 2, 14, 12, 14, 14, 15, 13, 15, 2, 15, 4, 16, 9, 16, 0, 16,
16, 17, 12, 17, 12, 18, 18, 19, 17, 20, 20, 21, 8, 21, 7, 21, 9, 22, 7, 22, 21,
22, 8, 22, 22, 23, 9, 23, 4, 23, 16, 23, 0, 23, 11, 24, 24, 25, 1, 25, 3, 26, 12,
26, 14, 26, 26, 27, 17, 27, 1, 27, 17, 27, 4, 28, 11, 28, 24, 28, 19, 29, 29,
30, 19, 30, 18, 31, 31, 32, 21, 32, 15, 32, 13, 32, 6, 32, 0, 33, 1, 33, 25, 33,
19, 33, 31, 34, 26, 34, 12, 34, 18, 34, 34, 35, 0, 35, 29, 35, 19, 35, 30, 35,
18, 36, 12, 36, 20, 36, 19, 36, 36, 37, 1, 37, 25, 37, 33, 37, 18, 38, 16, 38,
28, 38, 26, 38, 14, 38, 12, 38, 38, 39, 6, 39, 32, 39, 13, 39, 15, 39, 7, 40, 3,
40, 40, 41, 8, 41, 4, 41, 23, 41, 9, 41, 0, 41, 16, 41, 34, 42, 29, 42, 18, 42,
26, 42, 42, 43, 36, 43, 26, 43, 31, 43, 38, 43, 12, 43, 14, 43, 19, 44, 35, 44,
30, 44, 44, 45, 13, 45, 33, 45, 1, 45, 37, 45, 25, 45, 21, 46, 46, 47, 22, 47,
6, 47, 15, 47, 2, 47, 39, 47, 32, 47, 44, 48, 48, 49, 32, 49, 46, 49, 30, 50,
24, 50, 11, 50, 28, 50, 50, 51, 40, 51, 8, 51, 22, 51, 21, 51, 3, 52, 40, 52, 5,
52, 52, 53, 25, 53, 48, 53, 49, 53, 46, 53, 39, 54, 31, 54, 38, 54, 14, 54, 34,
54, 18, 54, 54, 55, 31, 55, 6, 55, 35, 55, 29, 55, 19, 55, 30, 55, 27, 56, 56,
57, 1, 57, 42, 57, 44, 57, 48, 57, 3, 58, 6, 58, 17, 58, 36, 58, 36, 59, 58, 59,
59, 60, 10, 60, 39, 60, 6, 60, 47, 60, 13, 60, 15, 60, 2, 60, 43, 61, 47, 61,
54, 61, 18, 61, 26, 61, 31, 61, 34, 61, 61, 62, 20, 62, 45, 62, 17, 62, 27, 62,
56, 62, 27, 63, 58, 63, 59, 63, 42, 63, 63, 64, 9, 64, 32, 64, 60, 64, 2, 64, 6,
64, 47, 64, 13, 64, 0, 65, 27, 65, 17, 65, 63, 65, 56, 65, 20, 65, 65, 66, 59,
66, 24, 66, 44, 66, 48, 66, 16, 67, 41, 67, 46, 67, 53, 67, 49, 67, 67, 68, 15,
68, 50, 68, 21, 68, 51, 68, 7, 68, 22, 68, 8, 68, 4, 69, 24, 69, 28, 69, 50, 69,
11, 69, 69, 70, 43, 70, 65, 70, 20, 70, 56, 70, 62, 70, 27, 70, 60, 71, 18, 71,
14, 71, 34, 71, 54, 71, 38, 71, 61, 71, 31, 71, 71, 72, 2, 72, 10, 72, 3, 72,
40, 72, 52, 72, 7, 73, 49, 73, 53, 73, 67, 73, 46, 73, 73, 74, 2, 74, 72, 74, 5,
74, 10, 74, 52, 74, 3, 74, 40, 74, 20, 75, 66, 75, 48, 75, 57, 75, 44, 75, 75,
76, 27, 76, 59, 76, 20, 76, 70, 76, 66, 76, 56, 76, 62, 76, 73, 77, 22, 77, 7,
77, 51, 77, 21, 77, 8, 77, 77, 78, 23, 78, 50, 78, 28, 78, 22, 78, 8, 78, 68,
78, 7, 78, 51, 78, 31, 79, 43, 79, 30, 79, 19, 79, 29, 79, 35, 79, 55, 79, 79,
80, 37, 80, 29, 80, 16, 81, 5, 81, 40, 81, 10, 81, 72, 81, 3, 81, 81, 82, 74,
82, 39, 82, 77, 82, 80, 82, 30, 82, 29, 82, 7, 82, 53, 83, 81, 83, 69, 83, 73,
83, 46, 83, 67, 83, 49, 83, 83, 84, 24, 84, 49, 84, 52, 84, 3, 84, 74, 84, 10,
84, 81, 84, 5, 84, 3, 84, 6, 85, 14, 85, 38, 85, 43, 85, 80, 85, 12, 85, 26, 85,
31, 85, 44, 86, 53, 86, 75, 86, 57, 86, 48, 86, 80, 86, 66, 86, 86, 87, 17, 87,
62, 87, 56, 87, 24, 87, 20, 87, 65, 87, 49, 88, 58, 88, 83, 88, 69, 88, 46, 88,
53, 88, 73, 88, 67, 88, 88, 89, 1, 89, 37, 89, 25, 89, 33, 89, 55, 89, 45, 89,
5, 90, 8, 90, 23, 90, 0, 90, 11, 90, 50, 90, 24, 90, 69, 90, 28, 90, 29, 91, 48,
91, 66, 91, 69, 91, 44, 91, 86, 91, 57, 91, 80, 91, 91, 92, 35, 92, 15, 92, 86,
92, 48, 92, 57, 92, 61, 92, 66, 92, 75, 92, 0, 93, 23, 93, 80, 93, 16, 93, 4,
93, 82, 93, 91, 93, 41, 93, 9, 93, 34, 94, 19, 94, 55, 94, 79, 94, 80, 94, 29,
94, 30, 94, 82, 94, 35, 94, 70, 95, 69, 95, 76, 95, 62, 95, 56, 95, 27, 95, 17,
95, 87, 95, 37, 95, 48, 96, 17, 96, 76, 96, 27, 96, 56, 96, 65, 96, 20, 96, 87,
96, 5, 97, 86, 97, 58, 97, 11, 97, 59, 97, 63, 97, 97, 98, 77, 98, 48, 98, 84,
98, 40, 98, 10, 98, 5, 98, 52, 98, 81, 98, 89, 99, 34, 99, 14, 99, 85, 99, 54,
99, 18, 99, 31, 99, 61, 99, 71, 99, 14, 99, 99, 100, 82, 100, 13, 100, 2, 100,
15, 100, 32, 100, 64, 100, 47, 100, 39, 100, 6, 100, 51, 101, 30, 101, 94,
101, 1, 101, 79, 101, 58, 101, 19, 101, 55, 101, 35, 101, 29, 101, 100, 102,
74, 102, 52, 102, 98, 102, 72, 102, 40, 102, 10, 102, 3, 102, 102, 103, 33,
103, 45, 103, 25, 103, 89, 103, 37, 103, 1, 103, 70, 103, 72, 104, 11, 104,
0, 104, 93, 104, 67, 104, 41, 104, 16, 104, 87, 104, 23, 104, 4, 104, 9, 104,
89, 105, 103, 105, 33, 105, 62, 105, 37, 105, 45, 105, 1, 105, 80, 105, 25,
105, 25, 106, 56, 106, 92, 106, 2, 106, 13, 106, 32, 106, 60, 106, 6, 106,
64, 106, 15, 106, 39, 106, 88, 107, 75, 107, 98, 107, 102, 107, 72, 107, 40,
107, 81, 107, 5, 107, 10, 107, 84, 107, 4, 108, 9, 108, 7, 108, 51, 108, 77,
108, 21, 108, 78, 108, 22, 108, 68, 108, 79, 109, 30, 109, 63, 109, 1, 109,
33, 109, 103, 109, 105, 109, 45, 109, 25, 109, 89, 109, 37, 109, 67, 110,
13, 110, 24, 110, 80, 110, 88, 110, 49, 110, 73, 110, 46, 110, 83, 110, 53,
110, 23, 111, 64, 111, 46, 111, 78, 111, 8, 111, 21, 111, 51, 111, 7, 111,
108, 111, 68, 111, 77, 111, 52, 112, 96, 112, 97, 112, 57, 112, 66, 112, 63,
112, 44, 112, 92, 112, 75, 112, 91, 112, 28, 113, 20, 113, 95, 113, 59, 113,
70, 113, 17, 113, 87, 113, 76, 113, 65, 113, 96, 113, 83, 114, 88, 114, 110,
114, 53, 114, 49, 114, 73, 114, 46, 114, 67, 114, 58, 114, 15, 114, 104, 114,
-1);
igraph_simplify(&g, /*remove_multiple=*/ true, /*remove_loops=*/ true, /*edge_comb=*/ NULL);
types = igraph_vector_int_view(football_types, sizeof(football_types) / sizeof(football_types[0]));
igraph_assortativity_nominal(&g, NULL, &types, &assort, IGRAPH_UNDIRECTED, /*normalized=*/ true);
printf("%g\n", assort);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,33 @@
Null graph nominal assortativity: NaN
Null graph value assortativity: NaN
Singleton graph nominal assortativity: NaN
Singleton graph nominal assortativity, unnormalized: NaN
Singleton graph value assortativity: NaN
Singleton graph value assortativity, unnormalized: NaN
Singleton graph with loop, nominal assortativity: NaN
Singleton graph with loop, nominal assortativity, unnormalized: 0
Singleton graph with loop, value assortativity: NaN
Singleton graph with loop, value assortativity, unnormalized: 0
Karate club, normalized assortativity based on degree categories: -0.077745
Karate club, non-normalized assortativity based on degree categories: -0.0693623
Assortativity based on values: 0.448049
Assortativity based on values, unnormalized: 69.3478
Degree assortativity, NORMALIZED
Degree assortativity: -0.475613
Degree assortativity, directed: -0.666667
Degree assortativity, undirected, with self-loop: 0.166667
Degree assortativity, directed, with self-loop: -0.707107
Degree assortativity, undirected, with multi-edges: -0.111111
Degree assortativity, directed, with multi-edges: -0.333333
Degree assortativity, UNNORMALIZED
Degree assortativity: -13.6943
Degree assortativity, directed: -0.16
Degree assortativity, undirected, with self-loop: 0.04
Degree assortativity, directed, with self-loop: -0.333333
Degree assortativity, undirected, with multi-edges: -0.04
Degree assortativity, directed, with multi-edges: -0.333333
Football network: 0.607938
@@ -0,0 +1,182 @@
/*
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 "test_utilities.h"
int main(void) {
igraph_t graph, graph2;
igraph_bool_t is_same;
igraph_real_t points[] = {
0.474217, 0.0314797, 0.208089, 0.439308, 0.967367, 0.530466,
0.177005, 0.426713, 0.568462, 0.57507, 0.441834, 0.284514, 0.479224,
0.817988, 0.720209, 0.225744, 0.204941, 0.44297, 0.285318, 0.912984,
0.831097, 0.0176603, 0.827154, 0.472702, 0.173059, 0.561858,
0.156276, 0.88019, 0.65935, 0.538207, 0.570379, 0.518081, 0.900553,
0.656416, 0.726631, 0.863709, 0.380264, 0.287159, 0.31098, 0.230773,
0.243089, 0.164584, 0.967974, 0.524992, 0.726605, 0.0724703,
0.739752, 0.447069, 0.0443581, 0.444839
};
igraph_real_t trig_lattice_points[] = {0.50000000000000000000000000000000000000000000000000, \
2.5980762113533159402911695122588085504142078807156, 0, \
1.7320508075688772935274463415058723669428052538104, \
1.0000000000000000000000000000000000000000000000000, \
1.7320508075688772935274463415058723669428052538104, \
-0.50000000000000000000000000000000000000000000000000, \
0.86602540378443864676372317075293618347140262690519, \
0.50000000000000000000000000000000000000000000000000, \
0.86602540378443864676372317075293618347140262690519, \
1.5000000000000000000000000000000000000000000000000, \
0.86602540378443864676372317075293618347140262690519, \
-1.0000000000000000000000000000000000000000000000000, 0, 0, 0, \
1.0000000000000000000000000000000000000000000000000, 0, \
2.0000000000000000000000000000000000000000000000000, 0
};
igraph_real_t rotated_square_lattice_points[] = {
-0.3594924531727418, 1.3677591805986329, -1.2231182700584293,
1.8718925443115786, -2.0867440869441167, 2.3760259080245243,
-2.950369903829804, 2.8801592717374698, 0.14464091054020378,
2.2313849974843203, -0.7189849063454836, 2.7355183611972658,
-1.582610723231171, 3.2396517249102117, -2.4462365401168586,
3.743785088623157, 0.6487742742531495, 3.0950108143700077,
-0.21485154263253792, 3.5991441780829536, -1.0784773595182253,
4.103277541795899, -1.9421031764039127, 4.607410905508845,
1.152907637966095, 3.958636631255695, 0.28928182108040756,
4.462769994968641, -0.5743439958052798, 4.966903358681586,
-1.4379698126909672, 5.4710367223945315
};
igraph_matrix_t point_mat, point_small_mat, point_singleton_mat, point_null_mat, point_3d_mat, trig_lattice, rot_square_lattice;
igraph_matrix_init_array(&point_mat, points, 25, 2, false);
igraph_matrix_init_array(&point_small_mat, points, 2, 2, false);
igraph_matrix_init_array(&point_singleton_mat, points, 1, 2, false);
igraph_matrix_init_array(&point_null_mat, points, 0, 2, false);
igraph_matrix_init_array(&rot_square_lattice, rotated_square_lattice_points, 16, 2, false);
igraph_matrix_init_array(&trig_lattice, trig_lattice_points, 10, 2, false);
igraph_matrix_init_array(&point_3d_mat, points, 10, 3, false);
printf("Lune beta skeleton beta = 2, 25 points\n");
igraph_lune_beta_skeleton(&graph, &point_mat, 2);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Gabriel graph, 25 points\n");
igraph_lune_beta_skeleton(&graph, &point_mat, 1);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Beta = 0.5, 25 points\n");
igraph_lune_beta_skeleton(&graph, &point_mat, 0.5);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Beta = 1.1, Circle based 25 points\n");
igraph_circle_beta_skeleton(&graph, &point_mat, 1.1);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Beta = 1.1, Circle based 2 points\n");
igraph_circle_beta_skeleton(&graph, &point_small_mat, 1.1);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Beta = 1.1, Circle based 1 point\n");
igraph_circle_beta_skeleton(&graph, &point_singleton_mat, 1.1);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Beta = 1.1, Circle based 0 points\n");
igraph_circle_beta_skeleton(&graph, &point_null_mat, 1.1);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Relative neighborhood graph, 10 points 3d\n");
igraph_lune_beta_skeleton(&graph, &point_3d_mat, 2);
print_graph_canon(&graph);
igraph_destroy(&graph);
igraph_vector_t weights;
printf("Beta weighted gabriel graph, 2d 25 points cutoff = Infinity\n");
igraph_vector_init(&weights, 0);
igraph_beta_weighted_gabriel_graph(&graph, &weights, &point_mat, IGRAPH_INFINITY);
igraph_lune_beta_skeleton(&graph2, &point_mat, 1);
igraph_is_same_graph(&graph, &graph2, &is_same);
igraph_destroy(&graph2);
igraph_destroy(&graph);
print_vector(&weights);
IGRAPH_ASSERT(is_same);
igraph_vector_destroy(&weights);
printf("Beta weighted gabriel graph, 2d 25 points cutoff = 5\n");
igraph_vector_init(&weights, 0);
igraph_beta_weighted_gabriel_graph(&graph, &weights, &point_mat, 5);
igraph_destroy(&graph);
print_vector(&weights);
igraph_vector_destroy(&weights);
printf("Beta weighted gabriel graph, 3d 10 points cutoff = Infinity\n");
igraph_vector_init(&weights, 0);
igraph_beta_weighted_gabriel_graph(&graph, &weights, &point_3d_mat, IGRAPH_INFINITY);
igraph_lune_beta_skeleton(&graph2, &point_3d_mat, 1);
igraph_is_same_graph(&graph, &graph2, &is_same);
igraph_destroy(&graph2);
igraph_destroy(&graph);
print_vector(&weights);
IGRAPH_ASSERT(is_same);
igraph_vector_destroy(&weights);
printf("Beta weighted gabriel graph, 3d 10 points cutoff = 5\n");
igraph_vector_init(&weights, 0);
igraph_beta_weighted_gabriel_graph(&graph, &weights, &point_3d_mat, 5);
igraph_destroy(&graph);
print_vector(&weights);
igraph_vector_destroy(&weights);
printf("Relative neighborhood graph, triangular lattice\n");
igraph_relative_neighborhood_graph(&graph, &trig_lattice);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Lune beta skeleton beta = 2, triangular_lattice\n");
igraph_lune_beta_skeleton(&graph, &trig_lattice, 2);
print_graph_canon(&graph);
igraph_destroy(&graph);
printf("Gabriel graph of rotated square lattice\n");
igraph_gabriel_graph(&graph, &rot_square_lattice);
print_graph_canon(&graph);
igraph_destroy(&graph);
igraph_matrix_destroy(&rot_square_lattice);
igraph_matrix_destroy(&trig_lattice);
igraph_matrix_destroy(&point_3d_mat);
igraph_matrix_destroy(&point_mat);
igraph_matrix_destroy(&point_small_mat);
igraph_matrix_destroy(&point_singleton_mat);
igraph_matrix_destroy(&point_null_mat);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,338 @@
Lune beta skeleton beta = 2, 25 points
directed: false
vcount: 25
edges: {
0 5
0 22
1 8
1 18
2 16
2 21
3 8
3 24
4 6
4 15
5 7
5 15
5 18
6 9
6 17
7 22
7 23
8 12
9 13
10 22
11 21
11 23
12 13
14 15
14 23
16 17
18 19
19 20
}
Gabriel graph, 25 points
directed: false
vcount: 25
edges: {
0 5
0 19
0 20
0 22
1 8
1 15
1 18
1 19
2 16
2 21
3 8
3 24
4 6
4 12
4 14
4 15
4 17
5 7
5 15
5 18
6 9
6 12
6 17
7 22
7 23
8 12
9 13
10 22
11 16
11 21
11 23
12 13
12 24
14 15
14 17
14 23
16 17
18 19
19 20
}
Beta = 0.5, 25 points
directed: false
vcount: 25
edges: {
0 5
0 7
0 10
0 14
0 15
0 18
0 19
0 20
0 22
0 23
1 3
1 4
1 5
1 6
1 8
1 9
1 15
1 17
1 18
1 19
1 20
1 23
2 6
2 7
2 11
2 14
2 16
2 21
2 22
3 5
3 8
3 12
3 18
3 19
3 20
3 24
4 5
4 6
4 8
4 9
4 12
4 13
4 14
4 15
4 16
4 17
4 18
5 6
5 7
5 9
5 12
5 13
5 14
5 15
5 18
5 19
5 22
5 23
6 8
6 9
6 11
6 12
6 13
6 14
6 16
6 17
6 18
6 19
6 21
7 10
7 11
7 12
7 14
7 15
7 19
7 20
7 21
7 22
7 23
8 9
8 12
8 15
8 17
8 20
8 23
8 24
9 12
9 13
9 15
9 17
9 18
9 19
10 11
10 21
10 22
10 23
11 14
11 15
11 16
11 17
11 21
11 23
12 13
12 15
12 18
12 24
13 15
13 18
13 24
14 15
14 16
14 17
14 18
14 21
14 23
15 17
15 18
15 23
16 17
16 23
17 23
18 19
18 22
18 23
19 20
19 22
19 24
20 22
20 24
21 22
}
Beta = 1.1, Circle based 25 points
directed: false
vcount: 25
edges: {
0 22
1 8
2 16
2 21
3 24
4 6
4 15
5 7
5 15
5 18
6 9
6 17
7 22
7 23
8 12
9 13
10 22
11 23
12 13
14 23
16 17
18 19
19 20
}
Beta = 1.1, Circle based 2 points
directed: false
vcount: 2
edges: {
0 1
}
Beta = 1.1, Circle based 1 point
directed: false
vcount: 1
edges: {
}
Beta = 1.1, Circle based 0 points
directed: false
vcount: 0
edges: {
}
Relative neighborhood graph, 10 points 3d
directed: false
vcount: 10
edges: {
0 3
0 5
1 4
1 7
2 4
2 5
2 8
3 8
3 9
4 6
4 9
7 8
}
Beta weighted gabriel graph, 2d 25 points cutoff = Infinity
( 2.13771 1.87896 1.30643 10.5357 Inf 1.04766 2.38206 1.72356 10.9882 41555.3 115.458 6.14845 4.87967 1.32814 1.42918 8.52199 1.20967 2.72446 3.66988 Inf 11.4047 1.33013 3.50412 36.5966 10.6973 4.82793 48.4413 628.646 1.11477 8.32087 Inf 4.28868 1.19886 3.33 1.31892 11.3292 3.3514 15.7597 29.7302 )
Beta weighted gabriel graph, 2d 25 points cutoff = 5
( 2.13771 1.87896 1.30643 Inf Inf 1.04766 2.38206 1.72356 Inf Inf Inf Inf 4.87967 1.32814 1.42918 Inf 1.20967 2.72446 3.66988 Inf Inf 1.33013 3.50412 Inf Inf 4.82793 Inf Inf 1.11477 Inf Inf 4.28868 1.19886 3.33 1.31892 Inf 3.3514 Inf Inf )
Beta weighted gabriel graph, 3d 10 points cutoff = Infinity
( 2.29424 2.87805 1.51364 15.0303 1.01534 2.12088 1.05443 1.30234 2.07368 8.72711 1.0848 1.99727 2.0717 1.25544 1.77266 2.21701 4.16352 58.0727 4.91485 1.47137 1.89216 2.00274 )
Beta weighted gabriel graph, 3d 10 points cutoff = 5
( 2.29424 2.87805 1.51364 Inf 1.01534 2.12088 1.05443 1.30234 2.07368 Inf 1.0848 1.99727 2.0717 1.25544 1.77266 2.21701 4.16352 Inf 4.91485 1.47137 1.89216 2.00274 )
Relative neighborhood graph, triangular lattice
directed: false
vcount: 10
edges: {
0 1
0 2
1 2
1 3
1 4
2 4
2 5
3 4
3 6
3 7
4 5
4 7
4 8
5 8
5 9
6 7
7 8
8 9
}
Lune beta skeleton beta = 2, triangular_lattice
directed: false
vcount: 10
edges: {
}
Gabriel graph of rotated square lattice
directed: false
vcount: 16
edges: {
0 1
0 4
1 2
1 5
2 3
2 6
3 7
4 5
4 8
5 6
5 9
6 7
6 10
7 11
8 9
8 12
9 10
9 13
10 11
10 14
11 15
12 13
13 14
14 15
}
+149
View File
@@ -0,0 +1,149 @@
/*
igraph library.
Copyright (C) 2009-2021 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
igraph_error_t bfs_callback(const igraph_t *graph,
igraph_int_t vid,
igraph_int_t pred,
igraph_int_t succ,
igraph_int_t rank,
igraph_int_t dist,
void *extra) {
IGRAPH_UNUSED(graph);
IGRAPH_UNUSED(pred);
IGRAPH_UNUSED(succ);
IGRAPH_UNUSED(rank);
IGRAPH_UNUSED(dist);
IGRAPH_UNUSED(extra);
printf(" %" IGRAPH_PRId, vid);
return IGRAPH_SUCCESS;
}
int main(void) {
igraph_t graph, ring;
igraph_vector_int_t restricted, order, rank, father, pred, succ, dist, roots;
igraph_int_t i;
igraph_ring(&ring, 10, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/ 1);
igraph_disjoint_union(&graph, &ring, &ring);
igraph_destroy(&ring);
igraph_vector_int_init(&order, 0);
igraph_vector_int_init(&rank, 0);
igraph_vector_int_init(&father, 0);
igraph_vector_int_init(&pred, 0);
igraph_vector_int_init(&succ, 0);
igraph_vector_int_init(&dist, 0);
igraph_bfs(&graph, /*root=*/0, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 1, /*restricted=*/ 0,
&order, &rank, &father, &pred, &succ, &dist,
/*callback=*/ 0, /*extra=*/ 0);
print_vector_int(&order);
print_vector_int(&rank);
print_vector_int(&father);
print_vector_int(&pred);
print_vector_int(&succ);
print_vector_int(&dist);
igraph_vector_int_destroy(&order);
igraph_vector_int_destroy(&rank);
igraph_vector_int_destroy(&father);
igraph_vector_int_destroy(&pred);
igraph_vector_int_destroy(&succ);
igraph_vector_int_destroy(&dist);
/* Test the callback */
printf("(");
igraph_bfs(&graph, /*root=*/ 0, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 1, /*restricted=*/ 0,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
/* Test different roots */
printf("(");
igraph_bfs(&graph, /*root=*/ 2, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 1, /*restricted=*/ 0,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
/* Test restricted */
igraph_vector_int_init(&restricted, 0);
for (i = 5; i < igraph_vcount(&graph); i++) {
igraph_vector_int_push_back(&restricted, i);
}
printf("(");
igraph_bfs(&graph, /*root=*/ 5, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 1, &restricted,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
/* Root not in restricted set */
printf("(");
igraph_bfs(&graph, /*root=*/ 4, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 1, &restricted,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
printf("(");
igraph_bfs(&graph, /*root=*/ 3, /*roots=*/ 0, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 0, &restricted,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
/* Multiple root vertices */
igraph_vector_int_init(&roots, 3);
VECTOR(roots)[0] = 3;
VECTOR(roots)[1] = 4;
VECTOR(roots)[2] = 6;
printf("(");
igraph_bfs(&graph, /*root=*/ -1, &roots, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 0, &restricted,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
/* Empty root vertex vector */
igraph_vector_int_clear(&roots);
printf("(");
igraph_bfs(&graph, /*root=*/ -1, &roots, /*mode=*/ IGRAPH_OUT,
/*unreachable=*/ 0, &restricted,
0, 0, 0, 0, 0, 0, &bfs_callback, 0);
printf(" )\n");
igraph_vector_int_destroy(&roots);
igraph_vector_int_destroy(&restricted);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,13 @@
( 0 1 9 2 8 3 7 4 6 5 10 11 19 12 18 13 17 14 16 15 )
( 0 1 3 5 7 9 8 6 4 2 10 11 13 15 17 19 18 16 14 12 )
( -1 0 1 2 3 4 7 8 9 0 -1 10 11 12 13 14 17 18 19 10 )
( -1 0 9 8 7 6 4 3 2 1 -1 10 19 18 17 16 14 13 12 11 )
( 1 9 8 7 6 -1 5 4 3 2 11 19 18 17 16 -1 15 14 13 12 )
( 0 1 2 3 4 5 4 3 2 1 0 1 2 3 4 5 4 3 2 1 )
( 0 1 9 2 8 3 7 4 6 5 10 11 19 12 18 13 17 14 16 15 )
( 2 1 3 0 4 9 5 8 6 7 10 11 19 12 18 13 17 14 16 15 )
( 5 6 7 8 9 10 11 19 12 18 13 17 14 16 15 )
( 5 6 7 8 9 10 11 19 12 18 13 17 14 16 15 )
( )
( 6 5 7 8 9 )
( )
@@ -0,0 +1,77 @@
/*
igraph library.
Copyright (C) 2009-2021 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_t vids, layers, parents;
igraph_vector_int_init(&vids, 0);
igraph_vector_int_init(&layers, 0);
igraph_vector_int_init(&parents, 0);
/* Test a ring graph */
igraph_ring(&g, 10, IGRAPH_UNDIRECTED, 0, 0);
igraph_bfs_simple(&g, 0, IGRAPH_ALL, &vids, &layers, &parents);
print_vector_int(&vids);
print_vector_int(&layers);
print_vector_int(&parents);
igraph_destroy(&g);
/* Test a tree graph */
igraph_kary_tree(&g, 20, 2, IGRAPH_TREE_UNDIRECTED);
igraph_bfs_simple(&g, 0, IGRAPH_ALL, &vids, &layers, &parents);
print_vector_int(&vids);
print_vector_int(&layers);
print_vector_int(&parents);
igraph_destroy(&g);
/* Test th same graph with all arguments as nulls to see if we tolerate that */
igraph_kary_tree(&g, 20, 2, IGRAPH_TREE_UNDIRECTED);
igraph_bfs_simple(&g, 0, IGRAPH_ALL, 0, 0, 0);
igraph_destroy(&g);
/* Also test the case when 'layers' is not null and 'vids' is null to ensure
* that we don't need 'vids' in the internal implementation to populate
* 'layers' */
igraph_kary_tree(&g, 20, 2, IGRAPH_TREE_UNDIRECTED);
igraph_bfs_simple(&g, 0, IGRAPH_ALL, 0, &layers, 0);
print_vector_int(&layers);
igraph_destroy(&g);
/* Test directed graph where not all nodes are reachable */
igraph_kary_tree(&g, 20, 2, IGRAPH_TREE_OUT);
igraph_bfs_simple(&g, 7, IGRAPH_OUT, 0, &layers, &parents);
print_vector_int(&layers);
print_vector_int(&parents);
igraph_destroy(&g);
igraph_vector_int_destroy(&vids);
igraph_vector_int_destroy(&layers);
igraph_vector_int_destroy(&parents);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,9 @@
( 0 1 2 3 4 5 6 7 8 9 )
( 0 1 2 3 4 5 6 7 8 9 10 )
( -1 0 1 2 3 4 5 6 7 8 )
( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 )
( 0 1 3 7 15 20 )
( -1 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 )
( 0 1 3 7 15 20 )
( 0 1 3 )
( -2 -2 -2 -2 -2 -2 -2 -1 -2 -2 -2 -2 -2 -2 -2 7 7 -2 -2 -2 )
@@ -0,0 +1,26 @@
*Vertices 13 8
1 "A"
2 "B"
3 "C"
4 "D"
5 "E"
6 "F"
7 "G"
8 "H"
9 "x-1"
10 "x-2"
11 "x-3"
12 "x-4"
13 "x-5"
*Edges
1 10
1 13
2 12
3 10
3 11
4 11
5 12
5 13
6 12
8 11
8 13
+403
View File
@@ -0,0 +1,403 @@
/*
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 "test_utilities.h"
int main(void) {
igraph_bitset_t v1, v2, v3;
igraph_int_t n;
printf("Initialise empty bitset\n");
n = 0;
igraph_bitset_init(&v1, n);
IGRAPH_ASSERT(igraph_bitset_size(&v1) == n);
igraph_bitset_destroy(&v1);
printf("\n");
printf("Initialise bitset of length 32\n");
n = 32;
igraph_bitset_init(&v1, n);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
printf("\n");
printf("Initialise bitset of length 64\n");
n = 64;
igraph_bitset_init(&v1, n);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
printf("\n");
printf("Initialise bitset of length 75\n");
n = 75;
igraph_bitset_init(&v1, n);
print_bitset(&v1);
IGRAPH_ASSERT(igraph_bitset_size(&v1) == n);
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test IGRAPH_BIT_SET\n");
n = 35;
igraph_bitset_init(&v1, n);
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 24);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 13);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 17);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 34);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 13);
print_bitset(&v1);
printf("\n");
printf("Test IGRAPH_BIT_CLEAR\n");
IGRAPH_BIT_CLEAR(v1, 33);
print_bitset(&v1);
IGRAPH_BIT_CLEAR(v1, 34);
print_bitset(&v1);
IGRAPH_BIT_CLEAR(v1, 17);
print_bitset(&v1);
printf("\n");
printf("Test printing\n");
igraph_bitset_print(&v1);
printf("\n\n");
printf("Test bitset copy constructor\n");
igraph_bitset_init_copy(&v2, &v1);
print_bitset(&v2);
igraph_bitset_destroy(&v1);
igraph_bitset_destroy(&v2);
printf("\n");
printf("Test bitset resize\n");
igraph_bitset_init(&v1, 0);
print_bitset(&v1);
IGRAPH_ASSERT(igraph_bitset_size(&v1) == 0);
igraph_bitset_resize(&v1, 10);
print_bitset(&v1);
IGRAPH_ASSERT(igraph_bitset_size(&v1) == 10);
IGRAPH_BIT_SET(v1, 3);
print_bitset(&v1);
igraph_bitset_resize(&v1, 64);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 63);
print_bitset(&v1);
igraph_bitset_resize(&v1, 70);
print_bitset(&v1);
IGRAPH_BIT_SET(v1, 64);
print_bitset(&v1);
igraph_bitset_resize(&v1, 64);
print_bitset(&v1);
igraph_bitset_resize(&v1, 63);
print_bitset(&v1);
IGRAPH_ASSERT(igraph_bitset_size(&v1) == 63);
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test OR\n");
n = 7;
igraph_bitset_init(&v1, n);
igraph_bitset_init(&v2, n);
igraph_bitset_init(&v3, n);
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
IGRAPH_BIT_SET(v2, 1);
IGRAPH_BIT_SET(v2, 2);
IGRAPH_BIT_SET(v2, 5);
print_bitset(&v2);
IGRAPH_BIT_SET(v3, 2);
IGRAPH_BIT_SET(v3, 3);
IGRAPH_BIT_SET(v3, 6);
print_bitset(&v3);
igraph_bitset_or(&v1, &v2, &v3);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
igraph_bitset_destroy(&v2);
igraph_bitset_destroy(&v3);
printf("\n");
printf("Test AND\n");
n = 7;
igraph_bitset_init(&v1, n);
igraph_bitset_init(&v2, n);
igraph_bitset_init(&v3, n);
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
IGRAPH_BIT_SET(v2, 1);
IGRAPH_BIT_SET(v2, 2);
IGRAPH_BIT_SET(v2, 5);
print_bitset(&v2);
IGRAPH_BIT_SET(v3, 2);
IGRAPH_BIT_SET(v3, 3);
IGRAPH_BIT_SET(v3, 6);
print_bitset(&v3);
igraph_bitset_and(&v1, &v2, &v3);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
igraph_bitset_destroy(&v2);
igraph_bitset_destroy(&v3);
printf("\n");
printf("Test XOR\n");
n = 7;
igraph_bitset_init(&v2, n);
igraph_bitset_init(&v1, n);
igraph_bitset_init(&v3, n);
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
IGRAPH_BIT_SET(v2, 1);
IGRAPH_BIT_SET(v2, 2);
IGRAPH_BIT_SET(v2, 5);
print_bitset(&v2);
IGRAPH_BIT_SET(v3, 2);
IGRAPH_BIT_SET(v3, 3);
IGRAPH_BIT_SET(v3, 6);
print_bitset(&v3);
igraph_bitset_xor(&v1, &v2, &v3);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
igraph_bitset_destroy(&v2);
igraph_bitset_destroy(&v3);
printf("\n");
printf("Test NOT\n");
n = 7;
igraph_bitset_init(&v1, n);
igraph_bitset_init(&v2, n);
IGRAPH_BIT_SET(v1, 1);
print_bitset(&v1);
IGRAPH_BIT_SET(v2, 1);
IGRAPH_BIT_SET(v2, 2);
IGRAPH_BIT_SET(v2, 5);
print_bitset(&v2);
igraph_bitset_not(&v1, &v2);
print_bitset(&v1);
igraph_bitset_destroy(&v1);
igraph_bitset_destroy(&v2);
printf("\n");
printf("Test popcount\n");
n = 75;
igraph_bitset_init(&v1, n);
print_bitset(&v1);
printf("Popcount: %" IGRAPH_PRId "\n", igraph_bitset_popcount(&v1));
for (igraph_int_t i = 2; i < n; i++) {
if (i == 2 || i == 3 || i == 5 || i == 7 || i == 11 || !(i%2 == 0 || i%3 == 0 || i%5 == 0 || i%7 == 0 || i%11 == 0)) {
IGRAPH_BIT_SET(v1, i);
}
}
print_bitset(&v1);
printf("Popcount: %" IGRAPH_PRId "\n", igraph_bitset_popcount(&v1));
IGRAPH_BIT_CLEAR(v1, 67);
print_bitset(&v1);
printf("Popcount: %" IGRAPH_PRId "\n", igraph_bitset_popcount(&v1));
IGRAPH_BIT_SET(v1, 9);
print_bitset(&v1);
printf("Popcount: %" IGRAPH_PRId "\n", igraph_bitset_popcount(&v1));
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Popcount: %" IGRAPH_PRId "\n", igraph_bitset_popcount(&v1));
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test count leading zeros\n");
n = 67;
igraph_bitset_init(&v1, n);
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
IGRAPH_BIT_SET(v1, 23);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
IGRAPH_BIT_CLEAR(v1, 0);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
IGRAPH_BIT_SET(v1, n - 3);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
IGRAPH_BIT_SET(v1, n - 1);
print_bitset(&v1);
printf("Leading zeros: %" IGRAPH_PRId "\n", igraph_bitset_countl_zero(&v1));
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test count leading ones\n");
n = 67;
igraph_bitset_init(&v1, n);
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
IGRAPH_BIT_CLEAR(v1, 0);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
IGRAPH_BIT_CLEAR(v1, 23);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
IGRAPH_BIT_CLEAR(v1, n - 3);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
IGRAPH_BIT_CLEAR(v1, n - 1);
print_bitset(&v1);
printf("Leading ones: %" IGRAPH_PRId "\n", igraph_bitset_countl_one(&v1));
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test count trailing zeros\n");
n = 67;
igraph_bitset_init(&v1, n);
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
IGRAPH_BIT_SET(v1, 23);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
IGRAPH_BIT_CLEAR(v1, 0);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
IGRAPH_BIT_CLEAR(v1, 23);
IGRAPH_BIT_SET(v1, n - 1);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
IGRAPH_BIT_SET(v1, 2);
print_bitset(&v1);
printf("Trailing zeros: %" IGRAPH_PRId "\n", igraph_bitset_countr_zero(&v1));
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test count trailing ones\n");
n = 67;
igraph_bitset_init(&v1, n);
igraph_bitset_not(&v1, &v1);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
IGRAPH_BIT_CLEAR(v1, 23);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
IGRAPH_BIT_CLEAR(v1, 0);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
IGRAPH_BIT_SET(v1, 0);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
IGRAPH_BIT_SET(v1, 23);
IGRAPH_BIT_CLEAR(v1, n - 1);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
IGRAPH_BIT_CLEAR(v1, 2);
print_bitset(&v1);
printf("Trailing ones: %" IGRAPH_PRId "\n", igraph_bitset_countr_one(&v1));
igraph_bitset_destroy(&v1);
printf("\n");
printf("Test checking all elements\n");
/* 0000 */
igraph_bitset_init(&v1, 4);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* 1000 */
IGRAPH_BIT_SET(v1, 3);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* 000 */
/* This resize leaves a set bit in the unused part of the last word of the.
* bitset. This helps test that masking out the unused part is working. */
igraph_bitset_resize(&v1, 3);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* 001 */
IGRAPH_BIT_SET(v1, 0);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* 111 */
IGRAPH_BIT_SET(v1, 1); IGRAPH_BIT_SET(v1, 2);
IGRAPH_ASSERT(igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_zero(&v1));
igraph_bitset_destroy(&v1);
igraph_bitset_init(&v1, 67);
/* all zeros */
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* some ones */
IGRAPH_BIT_SET(v1, 10);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
/* all ones */
igraph_bitset_fill(&v1, true);
IGRAPH_ASSERT(igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_zero(&v1));
/* some zeros */
IGRAPH_BIT_CLEAR(v1, 20);
IGRAPH_ASSERT(! igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(igraph_bitset_is_any_zero(&v1));
igraph_bitset_destroy(&v1);
/* Empty bitset */
igraph_bitset_init(&v1, 0);
IGRAPH_ASSERT(igraph_bitset_is_all_one(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_one(&v1));
IGRAPH_ASSERT(igraph_bitset_is_all_zero(&v1));
IGRAPH_ASSERT(! igraph_bitset_is_any_zero(&v1));
igraph_bitset_destroy(&v1);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,137 @@
Initialise empty bitset
Initialise bitset of length 32
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Initialise bitset of length 64
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Initialise bitset of length 75
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Test IGRAPH_BIT_SET
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Test IGRAPH_BIT_CLEAR
( 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Test printing
00000000001000000000010000000000001
Test bitset copy constructor
( 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Test bitset resize
( )
( 0 0 0 0 0 0 0 0 0 0 )
( 0 0 0 0 0 0 1 0 0 0 )
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
( 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
( 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 )
Test OR
( 0 0 0 0 0 0 1 )
( 0 1 0 0 1 1 0 )
( 1 0 0 1 1 0 0 )
( 1 1 0 1 1 1 0 )
Test AND
( 0 0 0 0 0 0 1 )
( 0 1 0 0 1 1 0 )
( 1 0 0 1 1 0 0 )
( 0 0 0 0 1 0 0 )
Test XOR
( 0 0 0 0 0 0 1 )
( 0 1 0 0 1 1 0 )
( 1 0 0 1 1 0 0 )
( 1 1 0 1 0 1 0 )
Test NOT
( 0 0 0 0 0 1 0 )
( 0 1 0 0 1 1 0 )
( 1 0 1 1 0 0 1 )
Test popcount
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Popcount: 0
( 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 1 0 0 )
Popcount: 21
( 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 1 0 0 )
Popcount: 20
( 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 )
Popcount: 21
( 1 0 1 0 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 0 1 0 1 1 1 0 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 0 1 1 )
Popcount: 54
Test count leading zeros
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Leading zeros: 0
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Leading zeros: 67
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Leading zeros: 66
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Leading zeros: 43
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Leading zeros: 43
( 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Leading zeros: 2
( 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Leading zeros: 0
Test count leading ones
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Leading ones: 67
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 )
Leading ones: 66
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 )
Leading ones: 43
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Leading ones: 43
( 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Leading ones: 2
( 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Leading ones: 0
Test count trailing zeros
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Trailing zeros: 0
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Trailing zeros: 67
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Trailing zeros: 0
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 )
Trailing zeros: 0
( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Trailing zeros: 23
( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
Trailing zeros: 66
( 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 )
Trailing zeros: 2
Test count trailing ones
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Trailing ones: 67
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Trailing ones: 23
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 )
Trailing ones: 0
( 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Trailing ones: 23
( 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 )
Trailing ones: 66
( 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 )
Trailing ones: 2
Test checking all elements
@@ -0,0 +1,57 @@
/*
igraph library.
Copyright (C) 2020-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
#define TEST_GRAPH(name) \
igraph_count_automorphisms_bliss(&graph, NULL, IGRAPH_BLISS_F, &info); \
printf("%s: %s\n", name, info.group_size); \
igraph_free(info.group_size); \
igraph_destroy(&graph);
#define TEST_FAMOUS(name) \
igraph_famous(&graph, name); \
TEST_GRAPH(name);
int main(void) {
igraph_t graph;
igraph_bliss_info_t info;
TEST_FAMOUS("Frucht");
TEST_FAMOUS("Coxeter");
TEST_FAMOUS("Petersen");
TEST_FAMOUS("Meredith");
igraph_full(&graph, 23, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
TEST_GRAPH("Complete 23");
igraph_star(&graph, 17, IGRAPH_STAR_OUT, 0);
TEST_GRAPH("Directed star 17");
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
TEST_GRAPH("Null graph");
igraph_empty(&graph, 1, IGRAPH_UNDIRECTED);
TEST_GRAPH("Singleton graph");
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,8 @@
Frucht: 1
Coxeter: 336
Petersen: 120
Meredith: 38698352640
Complete 23: 25852016738884976640000
Directed star 17: 20922789888000
Null graph: 1
Singleton graph: 1
@@ -0,0 +1,97 @@
/*
igraph library.
Copyright (C) 2010-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
static void simplify_write_destroy(igraph_t *g, igraph_attribute_combination_t *comb) {
igraph_simplify(g, /*remove_multiple=*/ true, /*remove_loops=*/ true, comb);
igraph_write_graph_graphml(g, stdout, /*prefixattr=*/ true);
igraph_attribute_combination_destroy(comb);
igraph_destroy(g);
}
static void type_test(igraph_t *g, igraph_attribute_combination_type_t type_attr) {
igraph_t g2;
igraph_attribute_combination_t comb;
igraph_copy(&g2, g);
igraph_attribute_combination(&comb,
"type", type_attr,
"", IGRAPH_ATTRIBUTE_COMBINE_IGNORE,
IGRAPH_NO_MORE_ATTRIBUTES);
simplify_write_destroy(&g2, &comb);
}
int main(void) {
igraph_t g, g2;
igraph_attribute_combination_t comb;
igraph_set_attribute_table(&igraph_cattribute_table);
igraph_small(&g, 4, IGRAPH_DIRECTED,
0, 1, 0, 1, 0, 1,
1, 2, 2, 3,
-1);
SETEAB(&g, "type", 0, 1);
SETEAB(&g, "type", 1, 1);
SETEAB(&g, "type", 2, 0);
SETEAB(&g, "type", 3, 0);
SETEAB(&g, "type", 4, 1);
/* ****************************************************** */
igraph_copy(&g2, &g);
igraph_attribute_combination(&comb,
"weight", IGRAPH_ATTRIBUTE_COMBINE_SUM,
"type", IGRAPH_ATTRIBUTE_COMBINE_FIRST,
"", IGRAPH_ATTRIBUTE_COMBINE_IGNORE,
IGRAPH_NO_MORE_ATTRIBUTES);
simplify_write_destroy(&g2, &comb);
/* ****************************************************** */
igraph_copy(&g2, &g);
igraph_attribute_combination(&comb,
"", IGRAPH_ATTRIBUTE_COMBINE_LAST,
IGRAPH_NO_MORE_ATTRIBUTES);
simplify_write_destroy(&g2, &comb);
/* ****************************************************** */
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_LAST);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_SUM);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_PROD);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_MIN);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_MAX);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_MEAN);
type_test(&g, IGRAPH_ATTRIBUTE_COMBINE_MEDIAN);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">true</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">false</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">false</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">true</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">false</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">false</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">true</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">true</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="e_type" for="edge" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="directed">
<node id="n0">
</node>
<node id="n1">
</node>
<node id="n2">
</node>
<node id="n3">
</node>
<edge source="n0" target="n1">
<data key="e_type">true</data>
</edge>
<edge source="n1" target="n2">
<data key="e_type">false</data>
</edge>
<edge source="n2" target="n3">
<data key="e_type">true</data>
</edge>
</graph>
</graphml>
@@ -0,0 +1,322 @@
/*
igraph library.
Copyright (C) 2007-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
#include <string.h>
#include <stdlib.h>
static void check_vector_queries(const igraph_t *g) {
igraph_vector_t vec;
igraph_strvector_t svec;
igraph_vector_bool_t bvec;
igraph_strvector_t vnames, enames;
igraph_vector_int_t vtypes, etypes;
igraph_int_t i, j;
igraph_vector_int_init(&vtypes, 0);
igraph_vector_int_init(&etypes, 0);
igraph_strvector_init(&vnames, 0);
igraph_strvector_init(&enames, 0);
igraph_vector_init(&vec, 0);
igraph_strvector_init(&svec, 0);
igraph_vector_bool_init(&bvec, 0);
igraph_cattribute_list(g, 0, 0, &vnames, &vtypes,
&enames, &etypes);
for (j = 0; j < igraph_strvector_size(&vnames); j++) {
if (VECTOR(vtypes)[j] == IGRAPH_ATTRIBUTE_NUMERIC) {
igraph_cattribute_VANV(g, igraph_strvector_get(&vnames, j), igraph_vss_all(), &vec);
for (i = 0; i < igraph_vcount(g); i++) {
igraph_real_t num = VAN(g, igraph_strvector_get(&vnames, j), i);
if (num != VECTOR(vec)[i] &&
(!isnan(num) || !isnan(VECTOR(vec)[i]))) {
exit(51);
}
}
} else if (VECTOR(vtypes)[j] == IGRAPH_ATTRIBUTE_STRING) {
igraph_cattribute_VASV(g, igraph_strvector_get(&vnames, j), igraph_vss_all(), &svec);
for (i = 0; i < igraph_vcount(g); i++) {
const char *str = VAS(g, igraph_strvector_get(&vnames, j), i);
if (strcmp(str, igraph_strvector_get(&svec, i))) {
exit(52);
}
}
} else {
igraph_cattribute_VABV(g, igraph_strvector_get(&vnames, j), igraph_vss_all(), &bvec);
for (i = 0; i < igraph_vcount(g); i++) {
igraph_bool_t b = VAB(g, igraph_strvector_get(&vnames, j), i);
if (b != VECTOR(bvec)[i]) {
exit(53);
}
}
}
}
for (j = 0; j < igraph_strvector_size(&enames); j++) {
if (VECTOR(etypes)[j] == IGRAPH_ATTRIBUTE_NUMERIC) {
igraph_cattribute_EANV(g, igraph_strvector_get(&enames, j),
igraph_ess_all(IGRAPH_EDGEORDER_ID), &vec);
for (i = 0; i < igraph_ecount(g); i++) {
igraph_real_t num = EAN(g, igraph_strvector_get(&enames, j), i);
if (num != VECTOR(vec)[i] &&
(!isnan(num) || !isnan(VECTOR(vec)[i]))) {
exit(54);
}
}
} else if (VECTOR(etypes)[j] == IGRAPH_ATTRIBUTE_STRING) {
igraph_cattribute_EASV(g, igraph_strvector_get(&enames, j),
igraph_ess_all(IGRAPH_EDGEORDER_ID), &svec);
for (i = 0; i < igraph_ecount(g); i++) {
const char *str = EAS(g, igraph_strvector_get(&enames, j), i);
if (strcmp(str, igraph_strvector_get(&svec, i))) {
exit(55);
}
}
} else {
igraph_cattribute_EABV(g, igraph_strvector_get(&enames, j),
igraph_ess_all(IGRAPH_EDGEORDER_ID), &bvec);
for (i = 0; i < igraph_ecount(g); i++) {
igraph_bool_t b = EAB(g, igraph_strvector_get(&enames, j), i);
if (b != VECTOR(bvec)[i]) {
exit(56);
}
}
}
}
igraph_strvector_destroy(&svec);
igraph_vector_destroy(&vec);
igraph_vector_bool_destroy(&bvec);
igraph_strvector_destroy(&enames);
igraph_strvector_destroy(&vnames);
igraph_vector_int_destroy(&etypes);
igraph_vector_int_destroy(&vtypes);
}
int main(void) {
igraph_t g, g2;
FILE *ifile;
igraph_int_t i;
igraph_vector_t y;
igraph_strvector_t name;
igraph_vector_bool_t type;
char str[21];
/* turn on attribute handling */
igraph_set_attribute_table(&igraph_cattribute_table);
ifile = fopen("links.net", "r");
IGRAPH_ASSERT(ifile != NULL);
igraph_read_graph_pajek(&g, ifile);
fclose(ifile);
SETGAB(&g, "bool_graph_attr", 1);
SETEAB(&g, "bool_edge_attr", 0, 1);
SETVAB(&g, "bool_vertex_attr", 0, 1);
print_attributes(&g);
/* Copying a graph */
igraph_copy(&g2, &g);
print_attributes(&g2);
igraph_destroy(&g2);
/* Adding vertices */
igraph_add_vertices(&g, 3, 0);
print_attributes(&g);
/* Adding edges */
igraph_add_edge(&g, 1, 1);
igraph_add_edge(&g, 2, 5);
igraph_add_edge(&g, 3, 6);
print_attributes(&g);
/* Deleting vertices */
igraph_delete_vertices(&g, igraph_vss_1(1));
igraph_delete_vertices(&g, igraph_vss_1(4));
print_attributes(&g);
/* Deleting edges */
igraph_delete_edges(&g, igraph_ess_1(igraph_ecount(&g) - 1));
igraph_delete_edges(&g, igraph_ess_1(0));
print_attributes(&g);
/* Set graph attributes */
SETGAN(&g, "id", 10);
SETGAS(&g, "name", "toy");
SETGAB(&g, "is_regular", 0);
printf("Before deleting some attributes:\n");
print_attributes(&g);
/* Delete graph attributes */
DELGA(&g, "id");
DELGA(&g, "name");
DELGA(&g, "is_regular");
/* Delete vertex attributes */
DELVA(&g, "x");
DELVA(&g, "shape");
DELVA(&g, "xfact");
DELVA(&g, "yfact");
/* Delete edge attributes */
DELEA(&g, "hook1");
DELEA(&g, "hook2");
DELEA(&g, "label");
printf("After deleting some attributes:\n");
print_attributes(&g);
/* Set vertex attributes */
SETVAN(&g, "y", 0, -1);
SETVAN(&g, "y", 1, 2.1);
SETVAS(&g, "name", 0, "foo");
SETVAS(&g, "name", 1, "bar");
SETVAB(&g, "type", 0, 1);
SETVAB(&g, "type", 1, 0);
/* Set edge attributes */
SETEAN(&g, "weight", 2, 100.0);
SETEAN(&g, "weight", 0, -100.1);
SETEAS(&g, "color", 2, "RED");
SETEAS(&g, "color", 0, "Blue");
SETEAB(&g, "type", 0, 1);
SETEAB(&g, "type", 2, 0);
printf("After setting vertex and edge attributes:\n");
print_attributes(&g);
check_vector_queries(&g);
/* Set vertex attributes as vector */
igraph_vector_init(&y, igraph_vcount(&g));
igraph_vector_fill(&y, 1.23);
SETVANV(&g, "y", &y);
igraph_vector_destroy(&y);
igraph_vector_init_range(&y, 0, igraph_vcount(&g));
SETVANV(&g, "foobar", &y);
igraph_vector_destroy(&y);
igraph_vector_bool_init(&type, igraph_vcount(&g));
for (i = 0; i < igraph_vcount(&g); i++) {
VECTOR(type)[i] = (i % 2 == 1);
}
SETVABV(&g, "type", &type);
igraph_vector_bool_destroy(&type);
igraph_strvector_init(&name, igraph_vcount(&g));
for (i = 0; i < igraph_vcount(&g); i++) {
snprintf(str, sizeof(str) - 1, "%" IGRAPH_PRId, i);
igraph_strvector_set(&name, i, str);
}
SETVASV(&g, "foo", &name);
igraph_strvector_destroy(&name);
igraph_strvector_init(&name, igraph_vcount(&g));
for (i = 0; i < igraph_vcount(&g); i++) {
snprintf(str, sizeof(str) - 1, "%" IGRAPH_PRId, i);
igraph_strvector_set(&name, i, str);
}
SETVASV(&g, "name", &name);
igraph_strvector_destroy(&name);
/* Set edge attributes as vector */
igraph_vector_init(&y, igraph_ecount(&g));
igraph_vector_fill(&y, 12.3);
SETEANV(&g, "weight", &y);
igraph_vector_destroy(&y);
igraph_vector_init_range(&y, 0, igraph_ecount(&g));
SETEANV(&g, "foobar", &y);
igraph_vector_destroy(&y);
igraph_vector_bool_init(&type, igraph_ecount(&g));
for (i = 0; i < igraph_ecount(&g); i++) {
VECTOR(type)[i] = (i % 2 == 1);
}
SETEABV(&g, "type", &type);
igraph_vector_bool_destroy(&type);
igraph_strvector_init(&name, igraph_ecount(&g));
for (i = 0; i < igraph_ecount(&g); i++) {
snprintf(str, sizeof(str) - 1, "%" IGRAPH_PRId, i);
igraph_strvector_set(&name, i, str);
}
SETEASV(&g, "foo", &name);
igraph_strvector_destroy(&name);
igraph_strvector_init(&name, igraph_ecount(&g));
for (i = 0; i < igraph_ecount(&g); i++) {
snprintf(str, sizeof(str) - 1, "%" IGRAPH_PRId, i);
igraph_strvector_set(&name, i, str);
}
SETEASV(&g, "color", &name);
igraph_strvector_destroy(&name);
printf("After setting vertex and edge attributes by vector:\n");
print_attributes(&g);
/* Delete all remaining attributes */
DELALL(&g);
printf("After deleting all attributes:\n");
print_attributes(&g);
igraph_destroy(&g);
printf("Setting attributes on vertex 0, permuting with 2\n");
{
igraph_t g2;
igraph_vector_int_t per;
igraph_vector_int_init_int(&per, 3, 2, 1, 0);
igraph_small(&g, 3, IGRAPH_DIRECTED, 0,1, 1,2, -1);
SETVAN(&g, "foo", 0, 5);
SETVAB(&g, "bar", 0, 1);
SETVAS(&g, "baz", 0, "foobar");
printf("Permuting to different graph:\n");
igraph_permute_vertices(&g, &g2, &per);
print_attributes(&g2);
printf("Permuting to same graph:\n");
igraph_cattribute_table.permute_vertices(&g, &g, &per);
print_attributes(&g);
igraph_destroy(&g);
igraph_destroy(&g2);
igraph_vector_int_destroy(&per);
}
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,152 @@
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="2" x=0.8188 y=0.2458 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Edge 0 (0-0): weight=1 hook2=0 edgewidth=3 color="Blue" arrowsize=3 angle1=-130 velocity1=0.6 angle2=-130 velocity2=0.6 arrowpos=0.5 label="Bezier loop" labelcolor="BlueViolet" fontsize=20 labelangle=58 labelpos=0.3 labeldegree=360 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=1
Edge 1 (1-0): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=120 velocity1=1.3 angle2=-120 velocity2=0.3 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=19 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=0 bool_edge_attr=0
Edge 2 (0-1): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=40 velocity1=2.8 angle2=30 velocity2=0.8 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=10 labelpos=0.65 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 3 (3-1): weight=-1 hook2=0 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=250 arrowpos=25 label="Circular arc" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 4 (2-3): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 5 (0-2): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 6 (2-2): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="2" x=0.8188 y=0.2458 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Edge 0 (0-0): weight=1 hook2=0 edgewidth=3 color="Blue" arrowsize=3 angle1=-130 velocity1=0.6 angle2=-130 velocity2=0.6 arrowpos=0.5 label="Bezier loop" labelcolor="BlueViolet" fontsize=20 labelangle=58 labelpos=0.3 labeldegree=360 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=1
Edge 1 (1-0): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=120 velocity1=1.3 angle2=-120 velocity2=0.3 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=19 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=0 bool_edge_attr=0
Edge 2 (0-1): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=40 velocity1=2.8 angle2=30 velocity2=0.8 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=10 labelpos=0.65 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 3 (3-1): weight=-1 hook2=0 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=250 arrowpos=25 label="Circular arc" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 4 (2-3): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 5 (0-2): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 6 (2-2): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="2" x=0.8188 y=0.2458 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 4: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 5: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 6: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Edge 0 (0-0): weight=1 hook2=0 edgewidth=3 color="Blue" arrowsize=3 angle1=-130 velocity1=0.6 angle2=-130 velocity2=0.6 arrowpos=0.5 label="Bezier loop" labelcolor="BlueViolet" fontsize=20 labelangle=58 labelpos=0.3 labeldegree=360 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=1
Edge 1 (1-0): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=120 velocity1=1.3 angle2=-120 velocity2=0.3 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=19 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=0 bool_edge_attr=0
Edge 2 (0-1): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=40 velocity1=2.8 angle2=30 velocity2=0.8 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=10 labelpos=0.65 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 3 (3-1): weight=-1 hook2=0 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=250 arrowpos=25 label="Circular arc" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 4 (2-3): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 5 (0-2): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 6 (2-2): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="2" x=0.8188 y=0.2458 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 4: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 5: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 6: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Edge 0 (0-0): weight=1 hook2=0 edgewidth=3 color="Blue" arrowsize=3 angle1=-130 velocity1=0.6 angle2=-130 velocity2=0.6 arrowpos=0.5 label="Bezier loop" labelcolor="BlueViolet" fontsize=20 labelangle=58 labelpos=0.3 labeldegree=360 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=1
Edge 1 (1-0): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=120 velocity1=1.3 angle2=-120 velocity2=0.3 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=19 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=0 bool_edge_attr=0
Edge 2 (0-1): weight=1 hook2=0 edgewidth=2 color="" arrowsize=1 angle1=40 velocity1=2.8 angle2=30 velocity2=0.8 arrowpos=25 label="Bezier arc" labelcolor="" fontsize=15 labelangle=10 labelpos=0.65 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 3 (3-1): weight=-1 hook2=0 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=250 arrowpos=25 label="Circular arc" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=0
Edge 4 (2-3): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 5 (0-2): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 6 (2-2): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
Edge 7 (1-1): weight=NaN hook2=NaN edgewidth=NaN color="" arrowsize=NaN angle1=NaN velocity1=NaN angle2=NaN velocity2=NaN arrowpos=NaN label="" labelcolor="" fontsize=NaN labelangle=NaN labelpos=NaN labeldegree=NaN labelangle2=NaN linepattern="" hook1=NaN bool_edge_attr=0
Edge 8 (2-5): weight=NaN hook2=NaN edgewidth=NaN color="" arrowsize=NaN angle1=NaN velocity1=NaN angle2=NaN velocity2=NaN arrowpos=NaN label="" labelcolor="" fontsize=NaN labelangle=NaN labelpos=NaN labeldegree=NaN labelangle2=NaN linepattern="" hook1=NaN bool_edge_attr=0
Edge 9 (3-6): weight=NaN hook2=NaN edgewidth=NaN color="" arrowsize=NaN angle1=NaN velocity1=NaN angle2=NaN velocity2=NaN arrowpos=NaN label="" labelcolor="" fontsize=NaN labelangle=NaN labelpos=NaN labeldegree=NaN labelangle2=NaN linepattern="" hook1=NaN bool_edge_attr=0
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 4: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Edge 0 (0-0): weight=1 hook2=0 edgewidth=3 color="Blue" arrowsize=3 angle1=-130 velocity1=0.6 angle2=-130 velocity2=0.6 arrowpos=0.5 label="Bezier loop" labelcolor="BlueViolet" fontsize=20 labelangle=58 labelpos=0.3 labeldegree=360 labelangle2=90 linepattern="" hook1=0 bool_edge_attr=1
Edge 1 (1-2): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 2 (0-1): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 3 (1-1): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
Edge 4 (2-4): weight=NaN hook2=NaN edgewidth=NaN color="" arrowsize=NaN angle1=NaN velocity1=NaN angle2=NaN velocity2=NaN arrowpos=NaN label="" labelcolor="" fontsize=NaN labelangle=NaN labelpos=NaN labeldegree=NaN labelangle2=NaN linepattern="" hook1=NaN bool_edge_attr=0
bool_graph_attr=1
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 4: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Edge 0 (1-2): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 1 (0-1): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 2 (1-1): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
Before deleting some attributes:
bool_graph_attr=1 id=10 name="toy" is_regular=0
Vertex 0: name="1" x=0.0938 y=0.0896 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=1
Vertex 1: name="3" x=0.3688 y=0.7792 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 2: name="4" x=0.9583 y=0.8563 shape="ellipse" xfact=1 yfact=1 bool_vertex_attr=0
Vertex 3: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Vertex 4: name="" x=NaN y=NaN shape="" xfact=NaN yfact=NaN bool_vertex_attr=0
Edge 0 (1-2): weight=1 hook2=0 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 label="Straight arc" labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 1 (0-1): weight=1 hook2=0 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 label="Oval arc" labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" hook1=0 bool_edge_attr=0
Edge 2 (1-1): weight=-1 hook2=12 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 label="Circular loop" labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" hook1=6 bool_edge_attr=0
After deleting some attributes:
bool_graph_attr=1
Vertex 0: name="1" y=0.0896 bool_vertex_attr=1
Vertex 1: name="3" y=0.7792 bool_vertex_attr=0
Vertex 2: name="4" y=0.8563 bool_vertex_attr=0
Vertex 3: name="" y=NaN bool_vertex_attr=0
Vertex 4: name="" y=NaN bool_vertex_attr=0
Edge 0 (1-2): weight=1 edgewidth=2 color="OliveGreen" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0
Edge 1 (0-1): weight=1 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0
Edge 2 (1-1): weight=-1 edgewidth=1 color="Red" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" bool_edge_attr=0
After setting vertex and edge attributes:
bool_graph_attr=1
Vertex 0: name="foo" y=-1 bool_vertex_attr=1 type=1
Vertex 1: name="bar" y=2.1 bool_vertex_attr=0 type=0
Vertex 2: name="4" y=0.8563 bool_vertex_attr=0 type=0
Vertex 3: name="" y=NaN bool_vertex_attr=0 type=0
Vertex 4: name="" y=NaN bool_vertex_attr=0 type=0
Edge 0 (1-2): weight=-100.1 edgewidth=2 color="Blue" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0 type=1
Edge 1 (0-1): weight=1 edgewidth=5 color="Brown" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0 type=0
Edge 2 (1-1): weight=100 edgewidth=1 color="RED" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" bool_edge_attr=0 type=0
After setting vertex and edge attributes by vector:
bool_graph_attr=1
Vertex 0: name="0" y=1.23 bool_vertex_attr=1 type=0 foobar=0 foo="0"
Vertex 1: name="1" y=1.23 bool_vertex_attr=0 type=1 foobar=1 foo="1"
Vertex 2: name="2" y=1.23 bool_vertex_attr=0 type=0 foobar=2 foo="2"
Vertex 3: name="3" y=1.23 bool_vertex_attr=0 type=1 foobar=3 foo="3"
Vertex 4: name="4" y=1.23 bool_vertex_attr=0 type=0 foobar=4 foo="4"
Edge 0 (1-2): weight=12.3 edgewidth=2 color="0" arrowsize=1 angle1=0 velocity1=1 angle2=0 velocity2=1 arrowpos=25 labelcolor="PineGreen" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0 type=0 foobar=0 foo="0"
Edge 1 (0-1): weight=12.3 edgewidth=5 color="1" arrowsize=1 angle1=0 velocity1=-1 angle2=0 velocity2=-20 arrowpos=25 labelcolor="Black" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=0 labelangle2=90 linepattern="Dashed" bool_edge_attr=0 type=1 foobar=1 foo="1"
Edge 2 (1-1): weight=12.3 edgewidth=1 color="2" arrowsize=1 angle1=0 velocity1=-2 angle2=0 velocity2=-15 arrowpos=0.5 labelcolor="OrangeRed" fontsize=15 labelangle=10 labelpos=0.5 labeldegree=180 labelangle2=270 linepattern="" bool_edge_attr=0 type=0 foobar=2 foo="2"
After deleting all attributes:
Vertex 0:
Vertex 1:
Vertex 2:
Vertex 3:
Vertex 4:
Edge 0 (1-2):
Edge 1 (0-1):
Edge 2 (1-1):
Setting attributes on vertex 0, permuting with 2
Permuting to different graph:
Vertex 0: foo=NaN bar=0 baz=""
Vertex 1: foo=NaN bar=0 baz=""
Vertex 2: foo=5 bar=1 baz="foobar"
Edge 0 (2-1):
Edge 1 (1-0):
Permuting to same graph:
Vertex 0: foo=NaN bar=0 baz=""
Vertex 1: foo=NaN bar=0 baz=""
Vertex 2: foo=5 bar=1 baz="foobar"
Edge 0 (0-1):
Edge 1 (1-2):
@@ -0,0 +1,73 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_real_t cent;
igraph_arpack_options_t arpack_options;
igraph_star(&g, 10, IGRAPH_STAR_IN, /*center=*/ 0);
igraph_centralization_degree(&g,
/*res=*/ NULL,
/*mode=*/ IGRAPH_IN, IGRAPH_NO_LOOPS,
&cent, /*theoretical_max=*/ NULL,
/*normalized=*/ true);
printf("in-star, degree: %g\n", cent);
igraph_centralization_betweenness(&g, /*res=*/ NULL,
IGRAPH_UNDIRECTED, &cent,
/*theoretical_max=*/ NULL,
/*normalized=*/ true);
printf("in-star, betweenness: %g\n", cent);
igraph_destroy(&g);
igraph_star(&g, 10, IGRAPH_STAR_OUT, /*center=*/ 0);
igraph_centralization_degree(&g, /*res=*/ NULL,
/*mode=*/ IGRAPH_OUT, IGRAPH_NO_LOOPS,
&cent, /*theoretical_max=*/ NULL,
/*normalized=*/ true);
printf("out-star, degree: %g\n", cent);
igraph_centralization_betweenness(&g, /*res=*/ NULL,
IGRAPH_UNDIRECTED, &cent,
/*theoretical_max=*/ NULL,
/*normalized=*/ true);
printf("out-star, betweenness: %g\n", cent);
igraph_destroy(&g);
igraph_small(&g, /*n=*/ 10, /*directed=*/ 0, 0, 1, -1);
igraph_arpack_options_init(&arpack_options);
igraph_centralization_eigenvector_centrality(
&g,
/*vector=*/ NULL,
/*value=*/ NULL,
/*mode=*/ IGRAPH_OUT,
&arpack_options, &cent,
/*theoretical_max=*/ NULL,
/*normalized=*/ true);
printf("dyad, eigenvector centrality, not scaled: %g\n", cent);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,5 @@
in-star, degree: 1
in-star, betweenness: 1
out-star, degree: 1
out-star, betweenness: 1
dyad, eigenvector centrality, not scaled: 1
@@ -0,0 +1,77 @@
/*
igraph library.
Copyright (C) 2023 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 <float.h>
#include "test_utilities.h"
int main(void) {
/* Test "normal" cases */
IGRAPH_ASSERT(igraph_cmp_epsilon(1, 2, 0.25) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(1, 2, 0.5) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(2, 1, 0.25) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(2, 1, 0.5) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(10, 11, 0.25) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(10, 11, 0.5) == 0);
/* Test infinities. Infinities are not equal to finite numbers with any
* tolerance */
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, 2, 0.5) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, 2, 20) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, 2, 200) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, 2, 0.5) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, 2, 20) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, 2, 200) < 0);
/* Infinities may be equal, though */
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, IGRAPH_INFINITY, 0.5) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, IGRAPH_INFINITY, 0.1) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, IGRAPH_INFINITY, 1e-7) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, -IGRAPH_INFINITY, 0.5) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, -IGRAPH_INFINITY, 0.1) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, -IGRAPH_INFINITY, 1e-7) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, IGRAPH_INFINITY, 0.5) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, IGRAPH_INFINITY, 0.1) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, IGRAPH_INFINITY, 1e-7) < 0);
/* NaNs are not equal to anything, not even each other. Sign of the result
* is not guaranteed */
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, IGRAPH_NAN, 0.1) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, IGRAPH_NAN, 0.1) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(0, IGRAPH_NAN, 1e-7) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, 0, 1e-7) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, IGRAPH_NAN, 1e-7) != 0);
/* Comparison with zero tolerance should be a "strict" comparison */
IGRAPH_ASSERT(igraph_cmp_epsilon(1, 2, 0) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(2, 1, 0) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(2, 2, 0) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(0, DBL_MIN, 0) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(DBL_MIN, 0, 0) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, 0, 0) < 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(-IGRAPH_INFINITY, -IGRAPH_INFINITY, 0) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, 0, 0) > 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_INFINITY, IGRAPH_INFINITY, 0) == 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, 0, 0) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, IGRAPH_NAN, 0) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, IGRAPH_INFINITY, 0) != 0);
IGRAPH_ASSERT(igraph_cmp_epsilon(IGRAPH_NAN, -IGRAPH_INFINITY, 0) != 0);
return 0;
}
@@ -0,0 +1,229 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/* Verify that the colouring is valid, i.e. no two adjacent vertices have the same colour. */
void verify_coloring(igraph_t *graph, const igraph_vector_int_t *colors) {
igraph_int_t no_of_edges = igraph_ecount(graph);
igraph_int_t no_of_nodes = igraph_vcount(graph);
for (igraph_int_t i = 0; i < no_of_edges; ++i) {
if (IGRAPH_FROM(graph, i) == IGRAPH_TO(graph, i)) {
continue;
}
if ( VECTOR(*colors)[ IGRAPH_FROM(graph, i) ] == VECTOR(*colors)[ IGRAPH_TO(graph, i) ] ) {
IGRAPH_FATALF("Inconsistent coloring! Vertices %" IGRAPH_PRId " and %" IGRAPH_PRId " are adjacent but have the same color.\n",
IGRAPH_FROM(graph, i), IGRAPH_TO(graph, i));
}
}
for (igraph_int_t i = 0; i < no_of_nodes; i++) {
igraph_int_t color = VECTOR(*colors)[i];
if (color < 0 || color >= no_of_nodes) {
IGRAPH_FATALF("The vertex %" IGRAPH_PRId " has invalid color %" IGRAPH_PRId "\n", i, color);
}
}
}
void print_result(
const char* result_name, const igraph_vector_int_t *colors,
igraph_bool_t print_color_vector
) {
printf("%s", result_name);
if (!igraph_vector_int_empty(colors)) {
printf("Number of colors used: %" IGRAPH_PRId "\n", igraph_vector_int_max(colors) + 1);
}
if (print_color_vector) {
print_vector_int(colors);
}
}
void run_tests(igraph_t *graph, igraph_bool_t print_color_vector) {
igraph_vector_int_t colors;
igraph_vector_int_init(&colors, 0);
igraph_vector_int_fill(&colors, -1);
igraph_vertex_coloring_greedy(graph, &colors, IGRAPH_COLORING_GREEDY_COLORED_NEIGHBORS);
verify_coloring(graph, &colors);
print_result("testing greedy coloring with COLORED_NEIGHBORS heuristic\n", &colors, print_color_vector);
igraph_vector_int_fill(&colors, -1);
igraph_vertex_coloring_greedy(graph, &colors, IGRAPH_COLORING_GREEDY_DSATUR);
verify_coloring(graph, &colors);
print_result("testing greedy coloring with DSATUR heuristic\n", &colors, print_color_vector);
printf("\n");
igraph_vector_int_destroy(&colors);
}
void test_null_graph(void) {
igraph_t graph;
/* run it on the null graph */
igraph_empty(&graph, 0, IGRAPH_DIRECTED);
printf("Testing null graph\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
void test_graph_1_vertex(void) {
igraph_t graph;
igraph_empty(&graph, 1, IGRAPH_DIRECTED);
printf("Testing singleton graph\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
void test_graph_large(void) {
igraph_t graph;
/* simple large undirected graph */
igraph_erdos_renyi_game_gnm(&graph, 1000, 10000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
printf("Testing large simple graph\n");
run_tests(&graph, false);
/* graph with loops and parallel edges */
igraph_rewire_edges(&graph, 1.0, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW);
printf("Testing large graph with loops and multi-edges\n");
run_tests(&graph, false);
igraph_destroy(&graph);
}
// This graph has chromatic number of 3.
void test_graph_small(void) {
igraph_t graph;
igraph_small(&graph, 8, IGRAPH_UNDIRECTED,
0, 3, 0, 4, 1, 4, 2, 4, 1, 5, 2, 5, 3, 5, 0, 6, 1, 6, 2, 6, 3, 6, 0, 7, 1, 7, 2, 7, 4, 7, 5, 7,
-1);
printf("Testing small simple graph\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
// Same as the graph above with multi-edges and self-loops added
void test_graph_small_multi(void) {
igraph_t graph;
igraph_small(&graph, 8, IGRAPH_UNDIRECTED,
0, 3, 0, 4, 1, 4, 2, 4, 1, 5, 2, 5, 3, 5, 0, 6, 1, 6, 2, 6, 3, 6, 0, 7, 1, 7, 2, 7, 4, 7, 5, 7,
0, 4, 0, 4, 3, 5, 3, 5, 3, 5, 0, 0, 0, 0, 1, 1,
-1);
printf("Testing small multigraph\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
// Note: This graph has chromatic number 4.
// Currently implemented greedy heuristics don't produce an exact result.
void test_graph_lcf(void) {
igraph_t graph;
igraph_lcf_small(&graph, /* n= */ 8, /* shifts= */ 2, /* repeats= */ 8, 0);
printf("Testing small LCF graph\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
// Isolated vertices must be assigned color 0.
void test_isolated_vertices(void) {
igraph_t graph;
igraph_small(&graph, 4, IGRAPH_UNDIRECTED, 0, 1, -1);
printf("Testing graph with isolated vertices\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
// Isolated vertices must be assigned color 0.
void test_isolated_vertices_with_loops(void) {
igraph_t graph;
igraph_small(&graph, 3, IGRAPH_UNDIRECTED,
0,0, 2,2, 2,2,
-1);
printf("Testing graph with isolated vertices and self-loops\n");
run_tests(&graph, true);
igraph_destroy(&graph);
}
// Wheel graphs on odd/even number of vertices have chromatic number of 3/4.
// DSatur is expected to find an exact minimum coloring.
void test_wheel_graph(void) {
igraph_t graph_odd, graph_even;
igraph_wheel(&graph_odd, 11, IGRAPH_WHEEL_UNDIRECTED, 0);
printf("Testing wheel graph with odd number of vertices\n");
run_tests(&graph_odd, true);
igraph_wheel(&graph_even, 12, IGRAPH_WHEEL_UNDIRECTED, 0);
printf("Testing wheel graph with even number of vertices\n");
run_tests(&graph_even, true);
igraph_destroy(&graph_odd);
igraph_destroy(&graph_even);
}
// Bipartite graphs have a chromatic number of 2 (by definition).
// DSatur is expected to find an exact minimum coloring.
void test_bipartite_graph(void) {
igraph_t graph_1, graph_2;
igraph_bipartite_game_gnm(&graph_1, 0, 100, 100, 10000, IGRAPH_UNDIRECTED, IGRAPH_ALL, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
printf("Testing complete bipartite graph\n");
run_tests(&graph_1, false);
igraph_bipartite_game_gnm(&graph_2, 0, 100, 100, 10000 - 100, IGRAPH_UNDIRECTED, IGRAPH_ALL, IGRAPH_SIMPLE_SW,
false);
printf("Testing large bipartite graph\n");
run_tests(&graph_2, false);
igraph_destroy(&graph_1);
igraph_destroy(&graph_2);
}
int main(void) {
igraph_rng_seed(igraph_rng_default(), 42);
test_null_graph();
test_graph_1_vertex();
test_graph_large();
test_graph_small();
test_graph_small_multi();
test_graph_lcf();
test_isolated_vertices();
test_isolated_vertices_with_loops();
test_wheel_graph();
test_bipartite_graph();
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,109 @@
/*
igraph library.
Copyright (C) 2022-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 "test_utilities.h"
/* This test verifies that the membership vectors returns by community detection
* functions are properly indexed, i.e. there are no negative indices and there
* are no empty communities. */
void check(const igraph_vector_int_t *m) {
igraph_vector_int_t m2;
igraph_vector_int_init_copy(&m2, m);
igraph_reindex_membership(&m2, NULL, NULL);
IGRAPH_ASSERT(igraph_vector_int_min(m) == 0);
IGRAPH_ASSERT(igraph_vector_int_max(m) == igraph_vector_int_max(&m2));
igraph_vector_int_destroy(&m2);
}
int main(void) {
igraph_t graph;
igraph_vector_int_t membership;
igraph_real_t m;
igraph_error_handler_t *handler;
igraph_error_t ret;
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&membership, 0);
igraph_grg_game(&graph, 100, 0.2, false, NULL, NULL);
igraph_community_fastgreedy(&graph, NULL, NULL, NULL, &membership);
check(&membership);
igraph_community_label_propagation(&graph, &membership, IGRAPH_ALL, NULL, NULL, NULL, IGRAPH_LPA_DOMINANCE);
check(&membership);
igraph_community_walktrap(&graph, NULL, 4, NULL, NULL, &membership);
check(&membership);
igraph_community_edge_betweenness(&graph, NULL, NULL, NULL, NULL, NULL, &membership, IGRAPH_UNDIRECTED, NULL, NULL);
check(&membership);
igraph_community_leading_eigenvector(&graph, NULL, NULL, &membership, igraph_vcount(&graph), NULL, NULL, false, NULL, NULL, NULL, NULL, NULL);
check(&membership);
igraph_community_leiden(&graph, NULL, NULL, NULL, 1, 0.01, 1, false, &membership, NULL, NULL);
check(&membership);
igraph_community_multilevel(&graph, NULL, 1, &membership, NULL, NULL);
check(&membership);
igraph_community_fluid_communities(&graph, 10, &membership);
check(&membership);
igraph_community_voronoi(&graph, &membership, NULL, NULL, NULL, NULL, IGRAPH_ALL, -1);
check(&membership);
igraph_community_spinglass(&graph, NULL, &m, NULL, &membership, NULL, 5, false, 1.0, 0.01, 0.99, IGRAPH_SPINCOMM_UPDATE_SIMPLE, 1, IGRAPH_SPINCOMM_IMP_ORIG, 1);
check(&membership);
igraph_community_spinglass(&graph, NULL, &m, NULL, &membership, NULL, 5, false, 1.0, 0.01, 0.99, IGRAPH_SPINCOMM_UPDATE_SIMPLE, 1, IGRAPH_SPINCOMM_IMP_NEG, 1);
check(&membership);
handler = igraph_set_error_handler(&igraph_error_handler_ignore);
ret = igraph_community_infomap(&graph, NULL, NULL, 1, false, 0, &membership, NULL);
igraph_set_error_handler(handler);
if (ret != IGRAPH_UNIMPLEMENTED) {
IGRAPH_ASSERT(ret == IGRAPH_SUCCESS);
check(&membership);
}
igraph_destroy(&graph);
igraph_grg_game(&graph, 20, 0.5, false, NULL, NULL);
handler = igraph_set_error_handler(&igraph_error_handler_ignore);
ret = igraph_community_optimal_modularity(&graph, NULL, 1, NULL, &membership);
igraph_set_error_handler(handler);
if (ret != IGRAPH_UNIMPLEMENTED) { /* Test only when GLPK is available */
IGRAPH_ASSERT(ret == IGRAPH_SUCCESS);
check(&membership);
}
igraph_destroy(&graph);
igraph_vector_int_destroy(&membership);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,157 @@
/*
igraph library.
Copyright (C) 2007-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_t membership;
igraph_vector_t weights;
igraph_vector_int_t initial;
igraph_vector_bool_t fixed;
igraph_int_t i, j, k;
/* Simple triangle graph, the output should be always one community */
igraph_small(&g, 0, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 1, 2, -1);
igraph_vector_int_init(&membership, 0);
igraph_lpa_variant_t variants[3] = {IGRAPH_LPA_DOMINANCE, IGRAPH_LPA_RETENTION, IGRAPH_LPA_FAST};
for (i = 0; i < 3; i++) {
for (j = 0; j < 100; j++) {
/* label propagation is a stochastic method */
igraph_rng_seed(igraph_rng_default(), j);
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, NULL, NULL, NULL, variants[i]);
for (k = 0; k < 3; k++) {
IGRAPH_ASSERT(VECTOR(membership)[k] == VECTOR(membership)[0]);
}
}
}
igraph_destroy(&g);
/* label propagation is a stochastic method */
igraph_rng_seed(igraph_rng_default(), 765);
/* Zachary Karate club -- this is just a quick smoke test */
igraph_small(&g, 0, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
0, 6, 0, 7, 0, 8, 0, 10, 0, 11,
0, 12, 0, 13, 0, 17, 0, 19, 0, 21,
0, 31, 1, 2, 1, 3, 1, 7, 1, 13,
1, 17, 1, 19, 1, 21, 1, 30, 2, 3,
2, 7, 2, 8, 2, 9, 2, 13, 2, 27,
2, 28, 2, 32, 3, 7, 3, 12, 3, 13,
4, 6, 4, 10, 5, 6, 5, 10, 5, 16,
6, 16, 8, 30, 8, 32, 8, 33, 9, 33,
13, 33, 14, 32, 14, 33, 15, 32, 15, 33,
18, 32, 18, 33, 19, 33, 20, 32, 20, 33,
22, 32, 22, 33, 23, 25, 23, 27, 23, 29,
23, 32, 23, 33, 24, 25, 24, 27, 24, 31,
25, 31, 26, 29, 26, 33, 27, 33, 28, 31,
28, 33, 29, 32, 29, 33, 30, 32, 30, 33,
31, 32, 31, 33, 32, 33,
-1);
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, NULL, NULL, NULL, IGRAPH_LPA_DOMINANCE);
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, NULL, NULL, NULL, IGRAPH_LPA_RETENTION);
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, NULL, NULL, NULL, IGRAPH_LPA_FAST);
igraph_destroy(&g);
/* Simple star graph to test weights */
igraph_small(&g, 0, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
2, 3, 2, 4, 3, 4, 3, 5, 4, 5, -1);
igraph_vector_init_int_end(&weights, -1, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1);
igraph_vector_int_init_int_end(&initial, -1, 0, 0, 1, 1, 1, 1, -1);
igraph_vector_bool_init(&fixed, 6);
VECTOR(fixed)[3] = 1;
VECTOR(fixed)[4] = 1;
VECTOR(fixed)[5] = 1;
for (i = 0; i < 3; i++) {
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, &weights,
&initial, &fixed, variants[i]);
for (j = 0; j < igraph_vcount(&g); j++) {
IGRAPH_ASSERT(VECTOR(membership)[j] == (j < 2 ? 0 : 1));
}
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, 0,
&initial, &fixed, variants[i]);
for (j = 0; j < igraph_vcount(&g); j++) {
IGRAPH_ASSERT(VECTOR(membership)[j] == 0);
}
/* Check whether it works with no fixed vertices at all
* while an initial configuration is given -- see bug
* #570902 in Launchpad. This is a simple smoke test only. */
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, &weights,
&initial, NULL, variants[i]);
}
igraph_vector_bool_destroy(&fixed);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&initial);
igraph_destroy(&g);
/* Test line graph with fixed and initial memberships */
igraph_small(&g, 3, IGRAPH_UNDIRECTED, 0, 1, 1, 2, 2, 3, -1);
igraph_vector_init(&weights, 3);
VECTOR(weights)[0] = 2;
VECTOR(weights)[1] = 1;
VECTOR(weights)[2] = 2;
igraph_vector_int_init(&initial, 4);
VECTOR(initial)[0] = 0;
VECTOR(initial)[1] = -1;
VECTOR(initial)[2] = -1;
VECTOR(initial)[3] = 1;
igraph_vector_bool_init(&fixed, 4);
VECTOR(fixed)[0] = 1;
VECTOR(fixed)[1] = 0;
VECTOR(fixed)[2] = 0;
VECTOR(fixed)[3] = 1;
igraph_community_label_propagation(&g, &membership, IGRAPH_ALL, &weights,
&initial, &fixed, IGRAPH_LPA_DOMINANCE);
igraph_vector_int_print(&membership);
IGRAPH_ASSERT(VECTOR(membership)[0] == 0);
IGRAPH_ASSERT(VECTOR(membership)[3] == 1);
igraph_vector_bool_destroy(&fixed);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&initial);
igraph_destroy(&g);
igraph_vector_int_destroy(&membership);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,86 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/* Test case for bug #1852 */
int main(void) {
igraph_t graph;
igraph_vector_int_t membership, initial_labels;
igraph_rng_seed(igraph_rng_default(), 42);
/* Undirected graph with unlabelled components */
igraph_small(&graph, 4, IGRAPH_UNDIRECTED,
1, 2, -1);
igraph_vector_int_init(&membership, 0);
igraph_vector_int_init(&initial_labels, igraph_vcount(&graph));
VECTOR(initial_labels)[0] = 1;
VECTOR(initial_labels)[1] = -1;
VECTOR(initial_labels)[2] = -1;
VECTOR(initial_labels)[3] = -1;
igraph_community_label_propagation(&graph, &membership, IGRAPH_ALL, NULL, &initial_labels, NULL, IGRAPH_LPA_DOMINANCE);
print_vector_int(&membership);
igraph_destroy(&graph);
/* Directed graph with unlabelled nodes not reachable from any labelled ones. */
igraph_small(&graph, 8, IGRAPH_DIRECTED,
0, 1, 1, 2, 3, 1, 2, 4, 4, 5, 5, 2, 4, 6,
-1);
igraph_vector_int_resize(&initial_labels, igraph_vcount(&graph));
igraph_vector_int_null(&initial_labels);
VECTOR(initial_labels)[0] = -1;
VECTOR(initial_labels)[1] = -1;
VECTOR(initial_labels)[2] = 1;
VECTOR(initial_labels)[3] = -1;
VECTOR(initial_labels)[4] = 2;
VECTOR(initial_labels)[6] = -1;
VECTOR(initial_labels)[7] = -1;
igraph_community_label_propagation(&graph, &membership, IGRAPH_OUT, NULL, &initial_labels, NULL, IGRAPH_LPA_DOMINANCE);
print_vector_int(&membership);
igraph_destroy(&graph);
/* None of the nodes are labelled initially */
igraph_full(&graph, 5, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_vector_int_resize(&initial_labels, igraph_vcount(&graph));
igraph_vector_int_fill(&initial_labels, -1);
igraph_community_label_propagation(&graph, &membership, IGRAPH_OUT, NULL, &initial_labels, NULL, IGRAPH_LPA_DOMINANCE);
print_vector_int(&membership);
igraph_destroy(&graph);
igraph_vector_int_destroy(&initial_labels);
igraph_vector_int_destroy(&membership);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,3 @@
( 0 2 2 1 )
( 2 2 0 3 0 0 0 1 )
( 0 0 0 0 0 )
@@ -0,0 +1,73 @@
/*
igraph library.
Copyright (C) 2007-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_t membership, initial;
igraph_vector_bool_t fixed;
igraph_int_t i;
/* label propagation is a stochastic method */
igraph_rng_seed(igraph_rng_default(), 765);
/* Zachary Karate club -- does not matter, we are simply interested in
* whether the system handles it correctly if a fixed node is unlabeled */
igraph_famous(&g, "zachary");
igraph_vector_int_init(&initial, igraph_vcount(&g));
igraph_vector_int_fill(&initial, -1);
igraph_vector_bool_init(&fixed, igraph_vcount(&g));
igraph_vector_bool_fill(&fixed, 0);
VECTOR(fixed)[7] = 1;
VECTOR(fixed)[13] = 1;
igraph_vector_int_init(&membership, 0);
igraph_community_label_propagation(&g, &membership, IGRAPH_OUT, NULL, &initial, &fixed, IGRAPH_LPA_DOMINANCE);
for (i = 0; i < igraph_vcount(&g); i++) {
/* Check that the "fixed" vector has not been changed */
if (i == 7 || i == 13) {
IGRAPH_ASSERT(VECTOR(fixed)[i]);
} else {
IGRAPH_ASSERT(!VECTOR(fixed)[i]);
}
/* Check that no vertex remained unlabeled */
IGRAPH_ASSERT(VECTOR(membership)[i] >= 0);
}
igraph_vector_bool_destroy(&fixed);
igraph_vector_int_destroy(&initial);
igraph_vector_int_destroy(&membership);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,313 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
#define TOL (1e-15)
void run_leiden_CPM(const igraph_t *graph, const igraph_vector_t *edge_weights, const igraph_real_t resolution) {
igraph_vector_int_t membership;
igraph_int_t nb_clusters = igraph_vcount(graph);
igraph_real_t quality, quality2;
/* Initialize with singleton partition. */
igraph_vector_int_init(&membership, igraph_vcount(graph));
/* Use same seed as for the simplified interface below, to ensure the same result. */
igraph_rng_seed(igraph_rng_default(), 123);
igraph_community_leiden(graph,
edge_weights, NULL, NULL,
resolution, 0.01, false, 2, &membership,
&nb_clusters,
&quality);
/* Handle negative zeros. */
if (fabs(quality) < TOL) quality = 0.0;
printf("Leiden found %" IGRAPH_PRId " clusters using CPM (resolution parameter=%.2f), quality is %.5f.\n", nb_clusters, resolution, quality);
printf("Membership: ");
igraph_vector_int_print(&membership);
printf("\n");
quality2 = quality;
/* Use same seed as for the generic interface above, to ensure the same result. */
igraph_rng_seed(igraph_rng_default(), 123);
igraph_community_leiden_simple(graph,
edge_weights,
IGRAPH_LEIDEN_OBJECTIVE_CPM,
resolution, 0.01, false, 2, &membership,
NULL,
&quality);
if (fabs(quality) < TOL) quality = 0.0;
IGRAPH_ASSERT((isnan(quality) && isnan(quality2)) ||
igraph_almost_equals(quality, quality2, TOL));
igraph_vector_int_destroy(&membership);
}
void run_leiden_modularity(igraph_t *graph, igraph_vector_t *edge_weights) {
const igraph_bool_t directed = igraph_is_directed(graph);
igraph_vector_int_t membership;
igraph_vector_t out_strength, in_strength;
igraph_int_t nb_clusters = igraph_vcount(graph);
igraph_real_t quality, quality2;
const igraph_real_t directed_multiplier = directed ? 1.0 : 2.0;
igraph_real_t m;
igraph_vector_init(&out_strength, igraph_vcount(graph));
igraph_strength(graph, &out_strength, igraph_vss_all(), IGRAPH_OUT, IGRAPH_LOOPS, edge_weights);
if (directed) {
igraph_vector_init(&in_strength, igraph_vcount(graph));
igraph_strength(graph, &in_strength, igraph_vss_all(), IGRAPH_IN, IGRAPH_LOOPS, edge_weights);
}
m = edge_weights ? igraph_vector_sum(edge_weights) : igraph_ecount(graph);
/* Initialize with singleton partition. */
igraph_vector_int_init(&membership, igraph_vcount(graph));
/* Use same seed as for the simplified interface below, to ensure the same result. */
igraph_rng_seed(igraph_rng_default(), 123);
igraph_community_leiden(graph,
edge_weights, &out_strength, directed ? &in_strength : NULL,
1.0 / (directed_multiplier * m), 0.01, false, 2, &membership, &nb_clusters,
&quality);
igraph_modularity(graph, &membership, edge_weights, 1.0, IGRAPH_DIRECTED, &quality2);
if (isnan(quality)) {
printf("Leiden found %" IGRAPH_PRId " clusters using modularity, %s, quality is nan.\n", nb_clusters, directed ? "directed" : "undirected");
IGRAPH_ASSERT(isnan(quality2));
} else {
/* It is necessary to not only use igraph_almost_equals(), but also check
* if the values are both very close to zero due to roundoff errors. */
if (fabs(quality) < TOL) quality = 0.0;
if (fabs(quality2) < TOL) quality2 = 0.0;
printf("Leiden found %" IGRAPH_PRId " clusters using modularity, %s, quality is %.5f.\n", nb_clusters, directed ? "directed" : "undirected", quality);
IGRAPH_ASSERT(igraph_almost_equals(quality, quality2, TOL));
}
printf("Membership: ");
igraph_vector_int_print(&membership);
printf("\n");
/* Use same seed as for the generic interface above, to ensure the same result. */
igraph_rng_seed(igraph_rng_default(), 123);
igraph_community_leiden_simple(graph,
edge_weights,
IGRAPH_LEIDEN_OBJECTIVE_MODULARITY,
1.0, 0.01, false, 2, &membership, NULL, &quality);
if (fabs(quality) < TOL) quality = 0.0;
IGRAPH_ASSERT((isnan(quality) && isnan(quality2)) ||
igraph_almost_equals(quality, quality2, TOL));
igraph_vector_int_destroy(&membership);
if (directed) igraph_vector_destroy(&in_strength);
igraph_vector_destroy(&out_strength);
}
int main(void) {
igraph_t graph;
igraph_vector_t weights;
igraph_vector_init(&weights, 0);
/* Set default seed to get reproducible results */
igraph_rng_seed(igraph_rng_default(), 0);
/* Simple unweighted graph */
igraph_small(&graph, 10, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 0, 3, 0, 4, 1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4,
5, 6, 5, 7, 5, 8, 5, 9, 6, 7, 6, 8, 6, 9, 7, 8, 7, 9, 8, 9,
0, 5, -1);
run_leiden_modularity(&graph, NULL);
/* Same simple graph, with uniform edge weights */
igraph_vector_resize(&weights, igraph_ecount(&graph));
igraph_vector_fill(&weights, 2);
run_leiden_modularity(&graph, &weights);
/* Same simple graph, but directed with reciprocal edges */
igraph_to_directed(&graph, IGRAPH_TO_DIRECTED_MUTUAL);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* Tiny directed graph; optimal community structure is different if
* ignoring edge directions. */
igraph_small(&graph, 4, IGRAPH_DIRECTED, 0, 2, 0, 3, 1, 2, 3, 1, 3, 2, -1);
run_leiden_modularity(&graph, NULL);
igraph_to_undirected(&graph, IGRAPH_TO_UNDIRECTED_EACH, NULL);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* Larger directed graph; optimal community structure is different if
* ignoring edge directions. */
igraph_small(
&graph, 10, IGRAPH_DIRECTED,
0, 3, 0, 4, 1, 0, 1, 4, 2, 1, 3, 0, 3, 2, 4, 0, 4, 3, 4, 7, 5, 0, 5,
1, 5, 3, 5, 6, 5, 8, 5, 9, 7, 0, 8, 2, 8, 3, 9, 1, 9, 3, 9, 8,
-1);
run_leiden_modularity(&graph, NULL);
igraph_to_undirected(&graph, IGRAPH_TO_UNDIRECTED_EACH, NULL);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* Simple nonuniform weighted graph, with and without weights */
igraph_small(&graph, 6, IGRAPH_UNDIRECTED,
0, 1, 1, 2, 2, 3, 2, 4, 2, 5, 3, 4, 3, 5, 4, 5, -1);
igraph_vector_resize(&weights, 8);
igraph_vector_fill(&weights, 1);
VECTOR(weights)[0] = 10;
VECTOR(weights)[1] = 10;
run_leiden_modularity(&graph, NULL);
run_leiden_modularity(&graph, &weights);
igraph_destroy(&graph);
/* Zachary Karate club */
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
0, 6, 0, 7, 0, 8, 0, 10, 0, 11,
0, 12, 0, 13, 0, 17, 0, 19, 0, 21,
0, 31, 1, 2, 1, 3, 1, 7, 1, 13,
1, 17, 1, 19, 1, 21, 1, 30, 2, 3,
2, 7, 2, 8, 2, 9, 2, 13, 2, 27,
2, 28, 2, 32, 3, 7, 3, 12, 3, 13,
4, 6, 4, 10, 5, 6, 5, 10, 5, 16,
6, 16, 8, 30, 8, 32, 8, 33, 9, 33,
13, 33, 14, 32, 14, 33, 15, 32, 15, 33,
18, 32, 18, 33, 19, 33, 20, 32, 20, 33,
22, 32, 22, 33, 23, 25, 23, 27, 23, 29,
23, 32, 23, 33, 24, 25, 24, 27, 24, 31,
25, 31, 26, 29, 26, 33, 27, 33, 28, 31,
28, 33, 29, 32, 29, 33, 30, 32, 30, 33,
31, 32, 31, 33, 32, 33,
-1);
run_leiden_modularity(&graph, NULL);
run_leiden_CPM(&graph, NULL, 0.06);
igraph_destroy(&graph);
/* Simple disconnected graph with isolates */
igraph_small(&graph, 9, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 0, 3, 1, 2, 1, 3, 2, 3,
4, 5, 4, 6, 4, 7, 5, 6, 5, 7, 6, 7,
-1);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* Disjoint union of two rings */
igraph_small(&graph, 20, IGRAPH_UNDIRECTED,
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 0, 9,
10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 10, 19, -1);
run_leiden_modularity(&graph, NULL);
run_leiden_CPM(&graph, NULL, 0.05);
igraph_destroy(&graph);
/* Completely empty graph */
igraph_small(&graph, 10, IGRAPH_UNDIRECTED, -1);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* Set default seed to get reproducible results */
igraph_rng_seed(igraph_rng_default(), 0);
/* Ring graph without loop edges */
igraph_small(&graph, 6, IGRAPH_UNDIRECTED,
0,1, 1,2, 2,3, 3,4, 4,5, 5,0, -1);
run_leiden_CPM(&graph, NULL, 0.4);
igraph_destroy(&graph);
/* Set default seed to get reproducible results */
igraph_rng_seed(igraph_rng_default(), 0);
/* Ring graph with loop edges */
igraph_small(&graph, 6, IGRAPH_UNDIRECTED,
0,1, 1,2, 2,3, 3,4, 4,5, 5,0,
0,0, 1,1, 2,2, 3,3, 4,4, 5,5,
-1);
run_leiden_CPM(&graph, NULL, 0.4);
igraph_destroy(&graph);
/* Regression test -- graph with two vertices and two edges */
igraph_small(&graph, 2, IGRAPH_UNDIRECTED, 0, 0, 1, 1, -1);
run_leiden_modularity(&graph, NULL);
igraph_destroy(&graph);
/* The next two tests need an empty weight vector. */
igraph_vector_clear(&weights);
/* Null graph */
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
run_leiden_modularity(&graph, &weights);
igraph_destroy(&graph);
/* Edgeless graph */
igraph_empty(&graph, 5, IGRAPH_UNDIRECTED);
run_leiden_modularity(&graph, &weights);
igraph_destroy(&graph);
/* Check that the input is validated properly. */
/* Small test graph. */
igraph_small(&graph, 4, IGRAPH_UNDIRECTED,
0,1, 1,2, 2,0, 0,3, 3,3,
-1);
igraph_vector_range(&weights, 1, igraph_ecount(&graph) + 1);
/* Omitting membership should raise no error. */
igraph_community_leiden_simple(&graph, &weights, IGRAPH_LEIDEN_OBJECTIVE_MODULARITY,
1.0, 0.01, false, 1, NULL, NULL, NULL);
/* Negative weight. */
VECTOR(weights)[0] = -1;
CHECK_ERROR(igraph_community_leiden_simple(&graph, &weights, IGRAPH_LEIDEN_OBJECTIVE_MODULARITY,
1.0, 0.01, false, 1, NULL, NULL, NULL), IGRAPH_EINVAL);
CHECK_ERROR(igraph_community_leiden_simple(&graph, &weights, IGRAPH_LEIDEN_OBJECTIVE_ER,
1.0, 0.01, false, 1, NULL, NULL, NULL), IGRAPH_EINVAL);
/* NaN weight. */
VECTOR(weights)[0] = IGRAPH_NAN;
CHECK_ERROR(igraph_community_leiden_simple(&graph, &weights, IGRAPH_LEIDEN_OBJECTIVE_CPM,
1.0, 0.01, false, 1, NULL, NULL, NULL), IGRAPH_EINVAL);
/* Invalid weight vector length. */
igraph_vector_range(&weights, 1, igraph_ecount(&graph) + 2);
CHECK_ERROR(igraph_community_leiden_simple(&graph, &weights, IGRAPH_LEIDEN_OBJECTIVE_MODULARITY,
1.0, 0.01, false, 1, NULL, NULL, NULL), IGRAPH_EINVAL);
igraph_destroy(&graph);
igraph_vector_destroy(&weights);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,60 @@
Leiden found 2 clusters using modularity, undirected, quality is 0.45238.
Membership: 0 0 0 0 0 1 1 1 1 1
Leiden found 2 clusters using modularity, undirected, quality is 0.45238.
Membership: 0 0 0 0 0 1 1 1 1 1
Leiden found 2 clusters using modularity, directed, quality is 0.45238.
Membership: 0 0 0 0 0 1 1 1 1 1
Leiden found 2 clusters using modularity, directed, quality is 0.08000.
Membership: 0 1 1 0
Leiden found 1 clusters using modularity, undirected, quality is 0.00000.
Membership: 0 0 0 0
Leiden found 3 clusters using modularity, directed, quality is 0.20868.
Membership: 0 1 1 0 0 2 2 0 2 2
Leiden found 2 clusters using modularity, undirected, quality is 0.18079.
Membership: 0 1 1 0 0 1 1 0 1 1
Leiden found 2 clusters using modularity, undirected, quality is 0.17969.
Membership: 0 0 1 1 1 1
Leiden found 2 clusters using modularity, undirected, quality is 0.17086.
Membership: 0 0 0 1 1 1
Leiden found 4 clusters using modularity, undirected, quality is 0.41979.
Membership: 0 0 0 0 1 1 1 0 2 2 1 0 0 0 2 2 1 0 2 0 2 0 2 3 3 3 2 3 3 2 2 3 2 2
Leiden found 2 clusters using CPM (resolution parameter=0.06), quality is 0.64949.
Membership: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1
Leiden found 3 clusters using modularity, undirected, quality is 0.50000.
Membership: 0 0 0 0 1 1 1 1 2
Leiden found 4 clusters using modularity, undirected, quality is 0.55000.
Membership: 0 0 0 1 1 1 1 1 0 0 2 2 2 2 2 3 3 3 3 3
Leiden found 2 clusters using CPM (resolution parameter=0.05), quality is 0.75000.
Membership: 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
Leiden found 10 clusters using modularity, undirected, quality is nan.
Membership: 0 1 2 3 4 5 6 7 8 9
Leiden found 2 clusters using CPM (resolution parameter=0.40), quality is 0.06667.
Membership: 0 0 1 1 1 0
Leiden found 2 clusters using CPM (resolution parameter=0.40), quality is 0.53333.
Membership: 0 0 1 1 1 0
Leiden found 2 clusters using modularity, undirected, quality is 0.50000.
Membership: 0 1
Leiden found 0 clusters using modularity, undirected, quality is nan.
Membership:
Leiden found 5 clusters using modularity, undirected, quality is nan.
Membership: 0 1 2 3 4
@@ -0,0 +1,187 @@
/*
igraph library.
Copyright (C) 2006-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 "test_utilities.h"
int main(void) {
igraph_t graph;
igraph_matrix_int_t merges;
igraph_vector_t modularity;
igraph_vector_int_t membership;
igraph_vector_t weights;
/* Set default seed to get reproducible results */
igraph_rng_seed(igraph_rng_default(), 42);
printf("Basic test\n\n");
/* Simple unweighted graph */
igraph_small(&graph, 3, IGRAPH_UNDIRECTED,
0,1, 1,2, 2,0, -1);
igraph_matrix_int_init(&merges, 0, 0);
igraph_vector_init(&modularity, 0);
igraph_vector_int_init(&membership, 0);
igraph_community_walktrap(&graph, NULL, 4, &merges, &modularity, &membership);
printf("Merges:\n");
print_matrix_int(&merges);
/* We replace modularity values which are very close to zero
* by exact zeros, so that we can have consistent test outputs
* across platforms. */
printf("Modularity: ");
igraph_vector_zapsmall(&modularity, 1e-15);
print_vector(&modularity);
printf("Membership: ");
print_vector_int(&membership);
igraph_vector_int_destroy(&membership);
igraph_vector_destroy(&modularity);
igraph_matrix_int_destroy(&merges);
/* Test the case when modularity=NULL and membership=NULL as this caused a crash in
* the R interface, see https://github.com/igraph/rigraph/issues/289 */
printf("\nWithout modularity and membership calculation\n\n");
igraph_matrix_int_init(&merges, 0, 0);
igraph_community_walktrap(&graph, NULL, 4, &merges, NULL, NULL);
printf("Merges:\n");
print_matrix_int(&merges);
igraph_matrix_int_destroy(&merges);
/* Test the case when merges=NULL but modularity is requested,
* as the result was previously invalid due to not incrementing
* the "merge index" during computation. */
printf("\nWithout merges matrix calculation\n\n");
igraph_vector_init(&modularity, 0);
igraph_community_walktrap(&graph, NULL, 4, NULL, &modularity, NULL);
printf("Modularity:\n");
igraph_vector_zapsmall(&modularity, 1e-15);
print_vector(&modularity);
igraph_vector_destroy(&modularity);
igraph_destroy(&graph);
/* Test for bug https://github.com/igraph/igraph/issues/2042 */
printf("\nBug 2042\n\n");
igraph_small(&graph, 3, IGRAPH_UNDIRECTED,
0,1, -1);
igraph_matrix_int_init(&merges, 0, 0);
igraph_vector_init(&modularity, 0);
igraph_vector_int_init(&membership, 0);
igraph_vector_init_real(&weights, 1, 0.2);
igraph_community_walktrap(&graph, &weights, 4, &merges, &modularity, &membership);
printf("Merges:\n");
print_matrix_int(&merges);
printf("Modularity: ");
igraph_vector_zapsmall(&modularity, 1e-15);
print_vector(&modularity);
printf("Membership: ");
print_vector_int(&membership);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&membership);
igraph_vector_destroy(&modularity);
igraph_matrix_int_destroy(&merges);
igraph_destroy(&graph);
printf("\nSmall weighted graph\n\n");
igraph_ring(&graph, 6, IGRAPH_UNDIRECTED, 0, 1);
igraph_matrix_int_init(&merges, 0, 0);
igraph_vector_init(&modularity, 0);
igraph_vector_int_init(&membership, 0);
igraph_vector_init_real(&weights, 6,
1.0, 0.5, 0.25, 0.75, 1.25, 1.5);
igraph_community_walktrap(&graph, &weights, 4, &merges, &modularity, &membership);
printf("Merges:\n");
print_matrix_int(&merges);
printf("Modularity: ");
igraph_vector_zapsmall(&modularity, 1e-15);
print_vector(&modularity);
printf("Membership: ");
print_vector_int(&membership);
/* Negative weights are not allowed */
VECTOR(weights)[0] = -0.1;
CHECK_ERROR(igraph_community_walktrap(&graph, &weights, 4, &merges, &modularity, &membership), IGRAPH_EINVAL);
/* Invalid weight vector size */
VECTOR(weights)[0] = 0.1;
igraph_vector_pop_back(&weights);
CHECK_ERROR(igraph_community_walktrap(&graph, &weights, 4, &merges, &modularity, &membership), IGRAPH_EINVAL);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&membership);
igraph_vector_destroy(&modularity);
igraph_matrix_int_destroy(&merges);
igraph_destroy(&graph);
printf("\nIsolated vertices\n\n");
igraph_empty(&graph, 5, IGRAPH_UNDIRECTED);
igraph_matrix_int_init(&merges, 0, 0);
igraph_vector_init(&modularity, 0);
igraph_vector_int_init(&membership, 0);
igraph_community_walktrap(&graph, NULL, 4, &merges, &modularity, &membership);
printf("Merges:\n");
print_matrix_int(&merges);
printf("Modularity: ");
igraph_vector_zapsmall(&modularity, 1e-15);
print_vector(&modularity);
printf("Membership: ");
print_vector_int(&membership);
igraph_vector_destroy(&weights);
igraph_vector_int_destroy(&membership);
igraph_vector_destroy(&modularity);
igraph_matrix_int_destroy(&merges);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,43 @@
Basic test
Merges:
[ 1 2
0 3 ]
Modularity: ( -0.333333 -0.222222 0 )
Membership: ( 0 0 0 )
Without modularity and membership calculation
Merges:
[ 1 2
0 3 ]
Without merges matrix calculation
Modularity:
( -0.333333 -0.222222 0 )
Bug 2042
Merges:
[ 0 1 ]
Modularity: ( -0.5 0 )
Membership: ( 0 0 1 )
Small weighted graph
Merges:
[ 3 4
1 2
0 5
7 8
6 9 ]
Modularity: ( -0.196145 -0.0895692 -0.0147392 0.146259 0.122449 0 )
Membership: ( 0 1 1 2 2 0 )
Isolated vertices
Merges:
[ 0-by-2 ]
Modularity: ( NaN )
Membership: ( 0 1 2 3 4 )
@@ -0,0 +1,97 @@
/*
igraph library.
Copyright (C) 2023 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void compute_and_print(const igraph_t *g, igraph_connectedness_t mode) {
igraph_vector_int_t membership, csize;
igraph_int_t no;
igraph_vector_int_init(&membership, 1);
igraph_vector_int_init(&csize, 1);
igraph_connected_components(g, &membership, &csize, &no, mode);
/* Canonicalize membership representation */
igraph_reindex_membership(&membership, NULL, NULL);
printf("Mode: %s\n", mode == IGRAPH_STRONG ? "strong" : "weak");
print_vector_int(&membership);
print_vector_int(&csize);
printf("No. of components: %" IGRAPH_PRId "\n", no);
igraph_vector_int_destroy(&csize);
igraph_vector_int_destroy(&membership);
}
int main(void) {
igraph_t g;
/* Component calculations are run twice to exercise the cache */
printf("\nNull graph (not connected)\n");
igraph_empty(&g, 0, IGRAPH_DIRECTED);
compute_and_print(&g, IGRAPH_STRONG);
compute_and_print(&g, IGRAPH_STRONG);
igraph_invalidate_cache(&g);
compute_and_print(&g, IGRAPH_WEAK);
compute_and_print(&g, IGRAPH_WEAK);
igraph_destroy(&g);
printf("\nSingleton graph (connected)\n");
igraph_empty(&g, 1, IGRAPH_DIRECTED);
compute_and_print(&g, IGRAPH_STRONG);
compute_and_print(&g, IGRAPH_STRONG);
igraph_invalidate_cache(&g);
compute_and_print(&g, IGRAPH_WEAK);
compute_and_print(&g, IGRAPH_WEAK);
igraph_destroy(&g);
printf("\nKautz graph (connected)\n");
igraph_kautz(&g, 2, 2);
compute_and_print(&g, IGRAPH_STRONG);
compute_and_print(&g, IGRAPH_STRONG);
igraph_invalidate_cache(&g);
compute_and_print(&g, IGRAPH_WEAK);
compute_and_print(&g, IGRAPH_WEAK);
igraph_destroy(&g);
printf("\nDirected 2-path\n");
igraph_small(&g, 2, IGRAPH_DIRECTED, 0,1, -1);
compute_and_print(&g, IGRAPH_STRONG);
compute_and_print(&g, IGRAPH_STRONG);
igraph_invalidate_cache(&g);
compute_and_print(&g, IGRAPH_WEAK);
compute_and_print(&g, IGRAPH_WEAK);
igraph_destroy(&g);
printf("\nTwo disjoint 3-cycles\n");
igraph_small(&g, 6, IGRAPH_DIRECTED, 0,1, 1,2, 2,0, 3,4, 4,5, 5,3, -1);
compute_and_print(&g, IGRAPH_STRONG);
compute_and_print(&g, IGRAPH_STRONG);
igraph_invalidate_cache(&g);
compute_and_print(&g, IGRAPH_WEAK);
compute_and_print(&g, IGRAPH_WEAK);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,90 @@
Null graph (not connected)
Mode: strong
( )
( )
No. of components: 0
Mode: strong
( )
( )
No. of components: 0
Mode: weak
( )
( )
No. of components: 0
Mode: weak
( )
( )
No. of components: 0
Singleton graph (connected)
Mode: strong
( 0 )
( 1 )
No. of components: 1
Mode: strong
( 0 )
( 1 )
No. of components: 1
Mode: weak
( 0 )
( 1 )
No. of components: 1
Mode: weak
( 0 )
( 1 )
No. of components: 1
Kautz graph (connected)
Mode: strong
( 0 0 0 0 0 0 0 0 0 0 0 0 )
( 12 )
No. of components: 1
Mode: strong
( 0 0 0 0 0 0 0 0 0 0 0 0 )
( 12 )
No. of components: 1
Mode: weak
( 0 0 0 0 0 0 0 0 0 0 0 0 )
( 12 )
No. of components: 1
Mode: weak
( 0 0 0 0 0 0 0 0 0 0 0 0 )
( 12 )
No. of components: 1
Directed 2-path
Mode: strong
( 0 1 )
( 1 1 )
No. of components: 2
Mode: strong
( 0 1 )
( 1 1 )
No. of components: 2
Mode: weak
( 0 0 )
( 2 )
No. of components: 1
Mode: weak
( 0 0 )
( 2 )
No. of components: 1
Two disjoint 3-cycles
Mode: strong
( 0 0 0 1 1 1 )
( 3 3 )
No. of components: 2
Mode: strong
( 0 0 0 1 1 1 )
( 3 3 )
No. of components: 2
Mode: weak
( 0 0 0 1 1 1 )
( 3 3 )
No. of components: 2
Mode: weak
( 0 0 0 1 1 1 )
( 3 3 )
No. of components: 2
@@ -0,0 +1,202 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/* This test attempts to verify that when adding vertices or edges to a graph fails,
* the graph, as well as its attribute table, are left in a consistent state.
* This test operates with the C attribute handler. Since this attribute table is
* not directly accessible, only limited checks are done to verify its consistency.
*
* We use the printignore() error handler insted of ignore() as this eases debugging.
* Thus, this test has not corresponding expected output file. All checks are done
* directly in the code.
*/
/* Check that the graph stays in a consistent state upon failure.
* This macro does not destroy the graph. */
#define CHECK1(funcall) \
do { \
igraph_int_t vcount = igraph_vcount(&graph); \
igraph_int_t ecount = igraph_ecount(&graph); \
igraph_error_handler_t *handler; \
handler = igraph_set_error_handler(igraph_error_handler_printignore); \
IGRAPH_ASSERT(funcall != IGRAPH_SUCCESS); \
igraph_set_error_handler(handler); \
verify_graph(&graph, vcount, ecount); \
} while (0)
/* Check that there is no invalid memory access if the graph is on the finally
* stack when failure occurs. This macro unrolls the finally stack and destroys
* the graph. */
#define CHECK2(funcall) \
do { \
igraph_error_handler_t *handler; \
IGRAPH_FINALLY(igraph_destroy, &graph); \
handler = igraph_set_error_handler(igraph_error_handler_printignore); \
IGRAPH_ASSERT(funcall != IGRAPH_SUCCESS); \
igraph_set_error_handler(handler); \
} while (0)
/* Do both checks, destroying the graph and resetting the finally stack in the process. */
#define CHECK_DESTROY(funcall) \
do { CHECK1(funcall); CHECK2(funcall); } while (0)
void verify_graph(const igraph_t *graph, igraph_int_t vcount, igraph_int_t ecount) {
IGRAPH_ASSERT(igraph_vector_int_size(&graph->from) == ecount);
IGRAPH_ASSERT(igraph_vector_int_size(&graph->to) == ecount);
IGRAPH_ASSERT(igraph_vector_int_size(&graph->oi) == ecount);
IGRAPH_ASSERT(igraph_vector_int_size(&graph->ii) == ecount);
IGRAPH_ASSERT(igraph_vector_int_size(&graph->os) == vcount + 1);
IGRAPH_ASSERT(igraph_vector_int_size(&graph->is) == vcount + 1);
}
int main(void) {
igraph_t graph;
/* Enable attribute handler */
igraph_set_attribute_table(&igraph_cattribute_table);
/* Helper vectors */
igraph_vector_t nvalues;
igraph_vector_init(&nvalues, 0);
igraph_strvector_t svalues;
igraph_strvector_init(&svalues, 0);
igraph_vector_bool_t bvalues;
igraph_vector_bool_init(&bvalues, 0);
const igraph_vector_int_t edges = IGRAPH_VECTOR_NULL; /* 2 edges */
igraph_vector_int_init_int((igraph_vector_int_t *) &edges, 4, 0,1, 1,2);
/* attr1, numeric, 3 values */
igraph_attribute_record_list_t attr1;
igraph_attribute_record_list_init(&attr1, 1);
igraph_attribute_record_t* a1 = igraph_attribute_record_list_get_ptr(&attr1, 0);
igraph_attribute_record_set_name(a1, "foo");
igraph_attribute_record_set_type(a1, IGRAPH_ATTRIBUTE_NUMERIC);
igraph_vector_t vec_a1;
igraph_vector_init_int(&vec_a1, 3, 1, 2, 3);
igraph_vector_update(a1->value.as_vector, &vec_a1);
igraph_vs_t vs1;
igraph_vs_vector_small(&vs1, 0, 1, 2, -1);
/* attr2, string, 2 values */
igraph_attribute_record_list_t attr2;
igraph_attribute_record_list_init(&attr2, 1);
igraph_attribute_record_t* a2 = igraph_attribute_record_list_get_ptr(&attr2, 0);
igraph_attribute_record_set_name(a2, "bar");
igraph_attribute_record_set_type(a2, IGRAPH_ATTRIBUTE_STRING);
igraph_strvector_t vec_a2;
igraph_strvector_init(&vec_a2, 2);
igraph_strvector_set(&vec_a2, 0, "one");
igraph_strvector_set(&vec_a2, 1, "two");
igraph_strvector_update(a2->value.as_strvector, &vec_a2);
/* attr3, boolean, 2 values */
igraph_attribute_record_list_t attr3;
igraph_attribute_record_list_init(&attr3, 1);
igraph_attribute_record_t* a3 = igraph_attribute_record_list_get_ptr(&attr3, 0);
igraph_attribute_record_set_name(a3, "baz");
igraph_attribute_record_set_type(a3, IGRAPH_ATTRIBUTE_BOOLEAN);
igraph_vector_bool_t vec_a3;
igraph_vector_bool_init_int(&vec_a3, 2, 1, 0);
igraph_vector_bool_update(a3->value.as_vector_bool, &vec_a3);
igraph_vs_t vs3;
igraph_vs_vector_small(&vs3, 3, 4, -1);
/* Perform tests */
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
CHECK_DESTROY(igraph_add_vertices(&graph, 2, &attr1)); /* wrong number of vertices */
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
igraph_add_vertices(&graph, 3, &attr1);
CHECK_DESTROY(igraph_add_edges(&graph, &edges, &attr1)); /* wrong number of edges */
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
igraph_add_vertices(&graph, 3, &attr1);
igraph_add_edges(&graph, &edges, &attr2);
igraph_add_vertices(&graph, 2, &attr3);
CHECK1(igraph_add_vertices(&graph, 2, &attr1)); /* wrong number of vertices */
/* Attribute handling still works and graph has correct attributes after failure to add vertices? */
IGRAPH_ASSERT(igraph_cattribute_VANV(&graph, a1->name, vs1, &nvalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vector_all_e(&vec_a1, &nvalues));
IGRAPH_ASSERT(igraph_cattribute_EASV(&graph, a2->name, igraph_ess_all(IGRAPH_EDGEORDER_ID), &svalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_strvector_size(&svalues) == igraph_strvector_size(&vec_a2));
for (igraph_int_t i=0; i < igraph_strvector_size(&svalues); ++i) {
IGRAPH_ASSERT(strcmp(igraph_strvector_get(&vec_a2, i), igraph_strvector_get(&svalues, i)) == 0);
}
IGRAPH_ASSERT(igraph_cattribute_VABV(&graph, a3->name, vs3, &bvalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vector_bool_all_e(&vec_a3, &bvalues));
CHECK1(igraph_add_edges(&graph, &edges, &attr1)); /* wrong number of edges */
/* Attribute handling still works and graph has correct attributes after failure to add vertices? */
IGRAPH_ASSERT(igraph_cattribute_VANV(&graph, a1->name, vs1, &nvalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vector_all_e(&vec_a1, &nvalues));
IGRAPH_ASSERT(igraph_cattribute_EASV(&graph, a2->name, igraph_ess_all(IGRAPH_EDGEORDER_ID), &svalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_strvector_size(&svalues) == igraph_strvector_size(&vec_a2));
for (igraph_int_t i=0; i < igraph_strvector_size(&svalues); ++i) {
IGRAPH_ASSERT(strcmp(igraph_strvector_get(&vec_a2, i), igraph_strvector_get(&svalues, i)) == 0);
}
IGRAPH_ASSERT(igraph_cattribute_VABV(&graph, a3->name, vs3, &bvalues) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vector_bool_all_e(&vec_a3, &bvalues));
igraph_destroy(&graph);
/* Release attr1 */
igraph_attribute_record_list_destroy(&attr1);
igraph_vs_destroy(&vs1);
/* Release attr2 */
igraph_attribute_record_list_destroy(&attr2);
/* Release attr3 */
igraph_attribute_record_list_destroy(&attr3);
igraph_vs_destroy(&vs3);
/* Release helpers */
igraph_vector_destroy(&vec_a1);
igraph_strvector_destroy(&vec_a2);
igraph_vector_bool_destroy(&vec_a3);
igraph_vector_int_destroy((igraph_vector_int_t *) &edges);
igraph_strvector_destroy(&svalues);
igraph_vector_destroy(&nvalues);
igraph_vector_bool_destroy(&bvalues);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,224 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void validate_coreness(
const igraph_t* graph, const igraph_vector_int_t* coreness,
igraph_neimode_t mode
) {
igraph_int_t i, j, min_coreness, max_coreness;
igraph_int_t nv = igraph_vcount(graph);
igraph_t subgraph;
igraph_vs_t vs;
igraph_vector_int_t vids, degree;
IGRAPH_ASSERT(igraph_vector_int_size(coreness) == nv);
if (igraph_vcount(graph) < 1) {
return;
}
min_coreness = igraph_vector_int_min(coreness);
max_coreness = igraph_vector_int_max(coreness);
IGRAPH_ASSERT(min_coreness >= 0);
igraph_vector_int_init(&vids, 0);
igraph_vector_int_init(&degree, 0);
for (i = max_coreness; i >= 0; i--) {
igraph_vector_int_clear(&vids);
for (j = 0; j < nv; j++) {
if (VECTOR(*coreness)[j] >= i) {
igraph_vector_int_push_back(&vids, j);
}
}
igraph_vs_vector(&vs, &vids);
igraph_induced_subgraph(graph, &subgraph, vs, IGRAPH_SUBGRAPH_AUTO);
igraph_vs_destroy(&vs);
igraph_degree(&subgraph, &degree, igraph_vss_all(), mode, IGRAPH_LOOPS_TWICE);
for (j = 0; j < igraph_vcount(&subgraph); j++) {
IGRAPH_ASSERT(VECTOR(degree)[j] >= i);
}
igraph_destroy(&subgraph);
}
igraph_vector_int_destroy(&degree);
igraph_vector_int_destroy(&vids);
}
void test_graph(const igraph_t* graph, igraph_bool_t print) {
igraph_vector_int_t coreness;
igraph_vector_int_init(&coreness, 0);
if (igraph_is_directed(graph)) {
igraph_coreness(graph, &coreness, IGRAPH_ALL);
validate_coreness(graph, &coreness, IGRAPH_ALL);
if (print) {
printf("mode = ALL: ");
print_vector_int(&coreness);
}
igraph_coreness(graph, &coreness, IGRAPH_OUT);
validate_coreness(graph, &coreness, IGRAPH_OUT);
if (print) {
printf("mode = OUT: ");
print_vector_int(&coreness);
}
igraph_coreness(graph, &coreness, IGRAPH_IN);
validate_coreness(graph, &coreness, IGRAPH_IN);
if (print) {
printf("mode = IN: ");
print_vector_int(&coreness);
}
} else {
igraph_coreness(graph, &coreness, IGRAPH_ALL);
validate_coreness(graph, &coreness, IGRAPH_ALL);
if (print) {
print_vector_int(&coreness);
}
}
igraph_vector_int_destroy(&coreness);
}
void add_loop_and_multiple_edges(igraph_t* graph, igraph_real_t loop_prob, igraph_real_t multi_prob) {
igraph_int_t i, n, from, to;
igraph_vector_int_t extra_edges;
igraph_vector_int_init(&extra_edges, 0);
n = igraph_vcount(graph);
for (i = 0; i < n; i++) {
if (RNG_UNIF01() < loop_prob) {
igraph_vector_int_push_back(&extra_edges, i);
igraph_vector_int_push_back(&extra_edges, i);
}
}
n = igraph_ecount(graph);
for (i = 0; i < n; i++) {
if (RNG_UNIF01() < multi_prob) {
igraph_edge(graph, i, &from, &to);
igraph_vector_int_push_back(&extra_edges, from);
igraph_vector_int_push_back(&extra_edges, to);
}
}
igraph_add_edges(graph, &extra_edges, 0);
igraph_vector_int_destroy(&extra_edges);
}
void remove_some_edges(igraph_t* graph, igraph_real_t prob) {
igraph_int_t i, n;
igraph_vector_int_t to_remove;
igraph_vector_int_init(&to_remove, 0);
n = igraph_ecount(graph);
for (i = 0; i < n; i++) {
if (igraph_rng_get_unif01(igraph_rng_default()) < prob) {
igraph_vector_int_push_back(&to_remove, i);
}
}
igraph_delete_edges(graph, igraph_ess_vector(&to_remove));
igraph_vector_int_destroy(&to_remove);
}
int main(void) {
igraph_t g;
igraph_rng_seed(igraph_rng_default(), 137);
/* Empty and singleton graph */
printf("Empty graph.\n");
igraph_empty(&g, 0, IGRAPH_UNDIRECTED);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
printf("Singleton graph.\n");
igraph_empty(&g, 1, IGRAPH_UNDIRECTED);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Simple full graph */
printf("Full graph.\n");
igraph_full(&g, 5, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Full graph with loops */
printf("Full graph with loops.\n");
igraph_full(&g, 5, IGRAPH_UNDIRECTED, IGRAPH_LOOPS);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Full directed graph */
printf("Full directed graph.\n");
igraph_full(&g, 5, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Full directed graph */
printf("Full directed graph with loops.\n");
igraph_full(&g, 5, IGRAPH_DIRECTED, IGRAPH_LOOPS);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Zachary karate club */
printf("Zachary karate club.\n");
igraph_famous(&g, "zachary");
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Zachary karate club, randomly directed edges */
printf("Zachary karate club, directed edges.\n");
igraph_famous(&g, "zachary");
igraph_to_directed(&g, IGRAPH_TO_DIRECTED_MUTUAL);
remove_some_edges(&g, 0.2);
test_graph(&g, /* print = */ 1);
igraph_destroy(&g);
/* Zachary karate club with random loops and multi-edges */
printf("Zachary karate club with loops and multi-edges.\n");
for (int i = 0; i < 20; i++) {
igraph_famous(&g, "zachary");
add_loop_and_multiple_edges(&g, 0.5, 0.2);
test_graph(&g, /* print = */ 0);
igraph_destroy(&g);
}
/* Geometric random graph */
printf("Geometric random graph.\n");
igraph_grg_game(&g, 100, 0.2, /* torus = */ 0, /* x = */ 0, /* y = */ 0);
test_graph(&g, /* print = */ 0);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,24 @@
Empty graph.
( )
Singleton graph.
( 0 )
Full graph.
( 4 4 4 4 4 )
Full graph with loops.
( 6 6 6 6 6 )
Full directed graph.
mode = ALL: ( 8 8 8 8 8 )
mode = OUT: ( 4 4 4 4 4 )
mode = IN: ( 4 4 4 4 4 )
Full directed graph with loops.
mode = ALL: ( 10 10 10 10 10 )
mode = OUT: ( 5 5 5 5 5 )
mode = IN: ( 5 5 5 5 5 )
Zachary karate club.
( 4 4 4 4 3 3 3 4 4 2 3 1 2 4 2 2 2 2 2 3 2 2 2 3 3 3 2 3 3 3 4 3 4 4 )
Zachary karate club, directed edges.
mode = ALL: ( 6 6 6 6 4 4 4 6 6 2 4 2 3 6 4 2 3 3 4 4 1 0 2 5 4 4 3 4 3 5 6 5 6 5 )
mode = OUT: ( 3 3 3 3 2 2 2 3 3 1 2 1 1 3 2 2 1 2 2 2 1 0 1 2 2 2 1 2 2 2 3 2 3 2 )
mode = IN: ( 3 3 3 3 2 2 2 3 3 1 2 1 2 3 2 0 2 1 2 2 0 0 1 3 2 1 2 2 1 3 3 2 3 3 )
Zachary karate club with loops and multi-edges.
Geometric random graph.
@@ -0,0 +1,49 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard st, Cambridge MA, 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "core/cutheap.h"
#include "test_utilities.h"
int main(void) {
igraph_i_cutheap_t ch;
igraph_int_t i;
igraph_i_cutheap_init(&ch, 10);
for (i = 0; i < 10; i++) {
igraph_i_cutheap_update(&ch, i, i);
}
while (!igraph_i_cutheap_empty(&ch)) {
igraph_int_t idx = igraph_i_cutheap_popmax(&ch);
printf("%" IGRAPH_PRId " ", idx);
}
printf("\n");
igraph_i_cutheap_destroy(&ch);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1 @@
9 8 7 6 5 4 3 2 1 0
@@ -0,0 +1,184 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void print_check_destroy(igraph_t *graph, igraph_vector_int_list_t *result) {
igraph_int_t i, rank = igraph_vector_int_list_size(result);
igraph_int_t ecount = igraph_ecount(graph), vcount = igraph_vcount(graph);
igraph_int_t ccount;
for (i=0; i < rank; ++i) {
igraph_vector_int_t *cycle = igraph_vector_int_list_get_ptr(result, i);
IGRAPH_ASSERT(igraph_vector_int_size(cycle) > 0);
igraph_int_t first_edge = VECTOR(*cycle)[0];
igraph_int_t last_edge = VECTOR(*cycle)[igraph_vector_int_size(cycle) - 1];
/* Verify that first and last edges of the cycle share a vertex */
IGRAPH_ASSERT(
(IGRAPH_FROM(graph, first_edge) == IGRAPH_FROM(graph, last_edge) ||
IGRAPH_FROM(graph, first_edge) == IGRAPH_TO(graph, last_edge)) ||
(IGRAPH_TO(graph, first_edge) == IGRAPH_FROM(graph, last_edge) ||
IGRAPH_TO(graph, first_edge) == IGRAPH_TO(graph, last_edge))
);
print_vector_int(cycle);
}
igraph_connected_components(graph, NULL, NULL, &ccount, IGRAPH_WEAK);
IGRAPH_ASSERT(rank == ecount - vcount + ccount);
igraph_destroy(graph);
}
int main(void) {
igraph_t graph;
igraph_vector_int_list_t result;
igraph_int_t rank;
igraph_vector_int_list_init(&result, 0);
printf("FUNDAMENTAL CYCLE BASIS\n");
printf("\nNull graph\n");
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\nSingleton graph\n");
igraph_empty(&graph, 1, IGRAPH_UNDIRECTED);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\nSingle vertex with loop\n");
igraph_small(&graph, 1, IGRAPH_UNDIRECTED,
0,0,
-1);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\nTree\n");
igraph_kary_tree(&graph, 3, 2, IGRAPH_TREE_UNDIRECTED);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\n2-cycle\n");
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
0,1, 0,1,
-1);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\nDisconnected\n");
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
1,2, 2,3, 3,1,
4,5, 5,4, 4,5,
6,7, 7,8, 8,9, 9,6, 6,8,
10,10, 10,11,
12,12,
-1);
igraph_fundamental_cycles(&graph, NULL, &result, -1, -1);
print_check_destroy(&graph, &result);
printf("\nMINIMUM WEIGHT CYCLE BASIS\n");
printf("\nNull graph\n");
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\nSingleton graph\n");
igraph_empty(&graph, 1, IGRAPH_UNDIRECTED);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\nSingle vertex with loop\n");
igraph_small(&graph, 1, IGRAPH_UNDIRECTED,
0,0,
-1);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\nTree\n");
igraph_kary_tree(&graph, 3, 2, IGRAPH_TREE_UNDIRECTED);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\n2-cycle\n");
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
0,1, 0,1,
-1);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\nDisconnected\n");
igraph_small(&graph, 0, IGRAPH_UNDIRECTED,
1,2, 2,3, 3,1,
4,5, 5,4, 4,5,
6,7, 7,8, 8,9, 9,6, 6,8,
10,10, 10,11,
12,12,
-1);
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
print_check_destroy(&graph, &result);
printf("\nPeriodic (5,6)-grid\n");
{
igraph_vector_int_t dimvec;
igraph_vector_bool_t periodic;
igraph_vector_int_init_int_end(&dimvec, -1,
1, 5, 6, -1);
igraph_vector_bool_init(&periodic, igraph_vector_int_size(&dimvec));
igraph_vector_bool_fill(&periodic, 1);
igraph_square_lattice(&graph, &dimvec, 1, IGRAPH_ADJ_UNDIRECTED, /* mutual */ false, &periodic);
igraph_vector_bool_destroy(&periodic);
igraph_vector_int_destroy(&dimvec);
}
igraph_minimum_cycle_basis(&graph, NULL, &result, /* cutoff */ -1, /* complete */ true, /* ordered */ true);
rank = igraph_vector_int_list_size(&result);
/* In a periodic grid graph, all elements in the minimum basis have size 4,
* except two, which have size equal to the grid dimensions. */
IGRAPH_ASSERT(igraph_vector_int_size(&VECTOR(result)[0]) == 4);
IGRAPH_ASSERT(igraph_vector_int_size(&VECTOR(result)[rank-1]) == 6);
IGRAPH_ASSERT(igraph_vector_int_size(&VECTOR(result)[rank-2]) == 5);
IGRAPH_ASSERT(igraph_vector_int_size(&VECTOR(result)[rank-3]) == 4);
print_check_destroy(&graph, &result);
#if 0
/* This is for benchmarking */
igraph_rng_seed(igraph_rng_default(), 42);
igraph_watts_strogatz_game(&graph, 3, 10, 2, 0.1, 0, 0);
igraph_minimum_cycle_basis(&graph, /* cutoff */ -1, /* complete */ true, * ordered */ true, &result);
print_check_destroy(&graph, &result);
#endif
igraph_vector_int_list_destroy(&result);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,78 @@
FUNDAMENTAL CYCLE BASIS
Null graph
Singleton graph
Single vertex with loop
( 0 )
Tree
2-cycle
( 0 1 )
Disconnected
( 1 0 2 )
( 4 5 )
( 3 5 )
( 7 6 10 )
( 8 10 9 )
( 11 )
( 13 )
MINIMUM WEIGHT CYCLE BASIS
Null graph
Singleton graph
Single vertex with loop
( 0 )
Tree
2-cycle
( 0 1 )
Disconnected
( 11 )
( 13 )
( 3 5 )
( 4 5 )
( 0 1 2 )
( 6 7 10 )
( 8 9 10 )
Periodic (5,6)-grid
( 0 1 10 3 )
( 0 51 50 53 )
( 1 8 9 18 )
( 2 3 12 5 )
( 2 53 52 55 )
( 4 5 14 7 )
( 4 55 54 57 )
( 6 7 16 9 )
( 6 57 56 59 )
( 8 59 58 51 )
( 10 11 20 13 )
( 11 18 19 28 )
( 12 13 22 15 )
( 14 15 24 17 )
( 16 17 26 19 )
( 20 21 30 23 )
( 21 28 29 38 )
( 22 23 32 25 )
( 24 25 34 27 )
( 26 27 36 29 )
( 30 31 40 33 )
( 31 38 39 48 )
( 32 33 42 35 )
( 34 35 44 37 )
( 36 37 46 39 )
( 40 41 50 43 )
( 41 48 49 58 )
( 42 43 52 45 )
( 44 45 54 47 )
( 0 8 6 4 2 )
( 1 51 41 31 21 11 )
@@ -0,0 +1,102 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "core/indheap.h"
#include "test_utilities.h"
int main(void) {
igraph_d_indheap_t h;
igraph_int_t idx1, idx2;
/* igraph_d_indheap_init, igraph_d_indheap_destroy */
igraph_d_indheap_init(&h, 0);
igraph_d_indheap_destroy(&h);
igraph_d_indheap_init(&h, 100);
igraph_d_indheap_destroy(&h);
/* igraph_d_indheap_empty, igraph_d_indheap_size */
igraph_d_indheap_init(&h, 10);
if (!igraph_d_indheap_empty(&h)) {
return 1;
}
if (igraph_d_indheap_size(&h) != 0) {
return 2;
}
igraph_d_indheap_push(&h, 10, 0, 0);
if (igraph_d_indheap_empty(&h)) {
return 3;
}
if (igraph_d_indheap_size(&h) != 1) {
return 4;
}
/* igraph_d_indheap_push */
igraph_d_indheap_push(&h, 9, 9, 8);
igraph_d_indheap_push(&h, 3, 3, 2);
igraph_d_indheap_push(&h, 2, 2, 1);
igraph_d_indheap_push(&h, 1, 1, 0);
igraph_d_indheap_push(&h, 7, 7, 6);
igraph_d_indheap_push(&h, 4, 4, 3);
igraph_d_indheap_push(&h, 0, 0, 1);
igraph_d_indheap_push(&h, 6, 6, 5);
igraph_d_indheap_push(&h, 5, 5, 4);
igraph_d_indheap_push(&h, 8, 8, 7);
/* igraph_d_indheap_max, igraph_d_indheap_delete_max */
while (!igraph_d_indheap_empty(&h)) {
printf("% " IGRAPH_PRId , (igraph_int_t)igraph_d_indheap_max(&h));
printf("% " IGRAPH_PRId "\n", (igraph_int_t)igraph_d_indheap_delete_max(&h));
}
/* igraph_d_indheap_reserve */
igraph_d_indheap_reserve(&h, 5);
igraph_d_indheap_reserve(&h, 20);
igraph_d_indheap_reserve(&h, 0);
igraph_d_indheap_reserve(&h, 3);
/* igraph_d_indheap_max_index */
igraph_d_indheap_push(&h, 0, 0, 1);
igraph_d_indheap_push(&h, 8, 8, 7);
igraph_d_indheap_push(&h, 2, 2, 1);
igraph_d_indheap_push(&h, 7, 7, 6);
igraph_d_indheap_push(&h, 9, 9, 8);
igraph_d_indheap_push(&h, 4, 4, 3);
igraph_d_indheap_push(&h, 3, 3, 2);
igraph_d_indheap_push(&h, 5, 5, 4);
igraph_d_indheap_push(&h, 1, 1, 0);
igraph_d_indheap_push(&h, 6, 6, 5);
while (!igraph_d_indheap_empty(&h)) {
igraph_d_indheap_max_index(&h, &idx1, &idx2);
printf(" %" IGRAPH_PRId " %" IGRAPH_PRId, idx1, idx2);
igraph_d_indheap_delete_max(&h);
}
printf("\n");
igraph_d_indheap_destroy(&h);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,12 @@
10 10
9 9
8 8
7 7
6 6
5 5
4 4
3 3
2 2
1 1
0 0
9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 1
+103
View File
@@ -0,0 +1,103 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/* Matrix-vector multiplication: y = A.x */
void matmul(const igraph_matrix_t *A, const igraph_vector_t *x, igraph_vector_t *y, igraph_real_t beta) {
igraph_int_t i, j, nr = igraph_matrix_nrow(A), nc = igraph_matrix_ncol(A);
IGRAPH_ASSERT(nc == igraph_vector_size(x));
IGRAPH_ASSERT(nr == igraph_vector_size(y));
igraph_vector_scale(y, beta);
for (i=0; i < nr; ++i) {
for (j=0; j < nc; ++j) {
VECTOR(*y)[i] += MATRIX(*A, i, j) * VECTOR(*x)[j];
}
}
}
int main(void) {
igraph_matrix_t A;
igraph_vector_t x, y1, y2;
igraph_int_t i, j;
const igraph_int_t nr = 5, nc = 8;
igraph_rng_seed(igraph_rng_default(), 54632);
igraph_matrix_init(&A, nr, nc);
igraph_vector_init(&x, nc);
/* Fill with arbitrary values. Should be zeroes by beta. */
igraph_vector_init_range(&y1, 1, nr + 1);
igraph_vector_init_copy(&y2, &y1);
for (i=0; i < nr; ++i) {
for (j=0; j < nc; ++j) {
MATRIX(A, i, j) = (igraph_real_t) RNG_INTEGER(-10, 10);
}
}
for (j=0; j < nc; ++j) {
VECTOR(x)[j] = (igraph_real_t) RNG_INTEGER(-10, 10);
}
printf("Input matrix A:\n");
print_matrix(&A);
printf("\nInput vector x:\n");
print_vector(&x);
igraph_blas_dgemv(0, 1, &A, &x, 0, &y1);
matmul(&A, &x, &y2, 0);
printf("\nResult vector DGEMV:\n");
print_vector(&y1);
printf("\nResult vector naive:\n");
print_vector(&y2);
/* Results should be exact since all values are integers */
IGRAPH_ASSERT(igraph_vector_all_e(&y1, &y2));
printf("\nAdding to previous result with beta=2:\n");
igraph_blas_dgemv(0, 1, &A, &x, 2, &y1);
matmul(&A, &x, &y2, 2);
printf("\nResult vector DGEMV:\n");
print_vector(&y1);
printf("\nResult vector naive:\n");
print_vector(&y2);
IGRAPH_ASSERT(igraph_vector_all_e(&y1, &y2));
igraph_vector_destroy(&y2);
igraph_vector_destroy(&y1);
igraph_vector_destroy(&x);
igraph_matrix_destroy(&A);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,23 @@
Input matrix A:
[ -8 -3 6 -8 1 6 -10 -6
5 9 0 0 -10 10 7 -6
-6 -9 5 7 -10 -7 -10 -10
-7 -7 -5 0 6 10 5 2
10 2 -6 4 -2 -4 -8 -2 ]
Input vector x:
( -1 -9 -5 -5 -6 -8 3 2 )
Result vector DGEMV:
( -51 -97 93 -2 -2 )
Result vector naive:
( -51 -97 93 -2 -2 )
Adding to previous result with beta=2:
Result vector DGEMV:
( -153 -291 279 -6 -6 )
Result vector naive:
( -153 -291 279 -6 -6 )
@@ -0,0 +1,143 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void check(igraph_t *graph, igraph_es_t *es) {
igraph_eit_t eit;
igraph_int_t edge;
IGRAPH_ASSERT(igraph_eit_create(graph, *es, &eit) == IGRAPH_SUCCESS);
for (; !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) {
edge = IGRAPH_EIT_GET(eit);
printf("%" IGRAPH_PRId " %" IGRAPH_PRId "\n", IGRAPH_FROM(graph, edge), IGRAPH_TO(graph, edge));
}
igraph_eit_destroy(&eit);
}
int main(void) {
igraph_t g, g_no_vertices, g_no_edges;
igraph_es_t es, es_copy;
igraph_vector_int_t v, check_as_vector;
igraph_eit_t eit;
igraph_small(&g, 5, IGRAPH_DIRECTED, 0,1, 0,2, 1,1, 1,3, 2,0, 2,3, 3,4, -1);
igraph_small(&g_no_vertices, 0, IGRAPH_UNDIRECTED, -1);
igraph_small(&g_no_edges, 5, IGRAPH_UNDIRECTED, -1);
printf("Checking es_vector:\n");
igraph_vector_int_init_int(&v, 3, 2, 3, 4);
igraph_es_vector(&es, &v);
check(&g, &es);
CHECK_ERROR(igraph_eit_create(&g_no_edges, es, &eit), IGRAPH_EINVEID);
CHECK_ERROR(igraph_eit_create(&g_no_vertices, es, &eit), IGRAPH_EINVEID);
printf("es_vector_copy\n");
igraph_es_vector_copy(&es, &v);
check(&g, &es);
printf("es_copy\n");
igraph_es_copy(&es_copy, &es);
check(&g, &es);
igraph_es_destroy(&es_copy);
printf("es_as_vector\n");
igraph_vector_int_clear(&v);
igraph_es_as_vector(&g, es, &v);
igraph_vector_int_print(&v);
igraph_es_destroy(&es);
igraph_vector_int_destroy(&v);
printf("es_vector with negative entry should fail.\n");
igraph_vector_int_init_int(&v, 3, -2, 3, 4);
igraph_es_vector(&es, &v);
CHECK_ERROR(igraph_eit_create(&g, es, &eit), IGRAPH_EINVEID);
igraph_vector_int_destroy(&v);
printf("Checking es_range:\n");
igraph_es_range(&es, 2, 5);
check(&g, &es);
CHECK_ERROR(igraph_eit_create(&g_no_edges, es, &eit), IGRAPH_EINVEID);
CHECK_ERROR(igraph_eit_create(&g_no_vertices, es, &eit), IGRAPH_EINVEID);
printf("Checking eit_as_vector using seq:\n");
igraph_eit_create(&g, es, &eit);
igraph_vector_int_init_int(&check_as_vector, 0);
igraph_eit_as_vector(&eit, &check_as_vector);
igraph_vector_int_print(&check_as_vector);
igraph_vector_int_destroy(&check_as_vector);
printf("Checking ess_range using es_range parameters:\n");
es = igraph_ess_range(2, 5);
check(&g, &es);
CHECK_ERROR(igraph_eit_create(&g_no_edges, es, &eit), IGRAPH_EINVEID);
CHECK_ERROR(igraph_eit_create(&g_no_vertices, es, &eit), IGRAPH_EINVEID);
printf("Checking whether ess_range accepts an empty range.\n");
es = igraph_ess_range(2, 2);
check(&g, &es);
CHECK_ERROR(igraph_eit_create(&g_no_edges, es, &eit), IGRAPH_EINVEID);
CHECK_ERROR(igraph_eit_create(&g_no_vertices, es, &eit), IGRAPH_EINVEID);
printf("Checking es_path:\n");
igraph_vector_int_init_int(&v, 3, 4, 3, 2);
igraph_es_path(&es, &v, /*directed*/0);
check(&g, &es);
CHECK_ERROR(igraph_eit_create(&g_no_vertices, es, &eit), IGRAPH_EINVVID);
CHECK_ERROR(igraph_eit_create(&g_no_edges, es, &eit), IGRAPH_EINVAL);
igraph_es_destroy(&es);
igraph_es_path(&es, &v, /*directed*/1);
CHECK_ERROR(igraph_eit_create(&g, es, &eit), IGRAPH_EINVAL);
igraph_vector_int_destroy(&v);
igraph_es_destroy(&es);
printf("es_path with negative entry should fail.\n");
igraph_vector_int_init_int(&v, 3, -4, 3, 2);
igraph_es_path(&es, &v, /*directed*/0);
CHECK_ERROR(igraph_eit_create(&g, es, &eit), IGRAPH_EINVVID);
printf("Checking es_type.\n");
IGRAPH_ASSERT(igraph_es_type(&es) == IGRAPH_ES_PATH);
igraph_es_destroy(&es);
printf("Checking es_none.\n");
igraph_es_none(&es);
check(&g, &es);
printf("es_pairs:\n");
igraph_vector_int_destroy(&v);
igraph_vector_int_init_int(&v, 4, 1,1, 2,0);
igraph_es_pairs(&es, &v, IGRAPH_DIRECTED);
check(&g, &es);
igraph_es_destroy(&es);
printf("es_pairs for nonexistent pair should fail.\n");
igraph_vector_int_destroy(&v);
igraph_vector_int_init_int(&v, 4, 6,1, 2,0);
igraph_es_pairs(&es, &v, IGRAPH_DIRECTED);
CHECK_ERROR(igraph_eit_create(&g, es, &eit), IGRAPH_EINVVID);
igraph_vector_int_destroy(&v);
igraph_destroy(&g);
igraph_destroy(&g_no_vertices);
igraph_destroy(&g_no_edges);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,36 @@
Checking es_vector:
1 1
1 3
2 0
es_vector_copy
1 1
1 3
2 0
es_copy
1 1
1 3
2 0
es_as_vector
2 3 4
es_vector with negative entry should fail.
Checking es_range:
1 1
1 3
2 0
Checking eit_as_vector using seq:
2 3 4
Checking ess_range using es_range parameters:
1 1
1 3
2 0
Checking whether ess_range accepts an empty range.
Checking es_path:
3 4
2 3
es_path with negative entry should fail.
Checking es_type.
Checking es_none.
es_pairs:
1 1
2 0
es_pairs for nonexistent pair should fail.
@@ -0,0 +1,152 @@
/*
igraph library.
Copyright (C) 2020-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int test_graph(const char* name, const igraph_t* graph, const igraph_real_t* weights_array) {
igraph_real_t eff;
igraph_vector_t eff_vec;
printf("###### Testing graph: %s ######\n\n", name);
igraph_vector_init(&eff_vec, 0);
if (weights_array) {
printf("UNWEIGHTED CASE:\n\n");
}
igraph_global_efficiency(graph, NULL, &eff, IGRAPH_UNDIRECTED);
printf("Global efficiency, undirected: %f\n", eff);
igraph_global_efficiency(graph, NULL, &eff, IGRAPH_DIRECTED);
printf("Global efficiency, directed: %f\n", eff);
igraph_average_local_efficiency(graph, NULL, &eff, IGRAPH_UNDIRECTED, IGRAPH_ALL);
printf("Average local efficiency, undirected: %f\n", eff);
igraph_average_local_efficiency(graph, NULL, &eff, IGRAPH_DIRECTED, IGRAPH_ALL);
printf("Average local efficiency, directed, all neighbors: %f\n", eff);
igraph_average_local_efficiency(graph, NULL, &eff, IGRAPH_DIRECTED, IGRAPH_IN);
printf("Average local efficiency, directed, in-neighbors: %f\n", eff);
igraph_average_local_efficiency(graph, NULL, &eff, IGRAPH_DIRECTED, IGRAPH_OUT);
printf("Average local efficiency, directed, out-neighbors: %f\n", eff);
printf("\nLocal efficiency, undirected:\n");
igraph_local_efficiency(graph, NULL, &eff_vec, igraph_vss_all(), IGRAPH_UNDIRECTED, IGRAPH_ALL);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, all neighbors:\n");
igraph_local_efficiency(graph, NULL, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_ALL);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, in-neighbors:\n");
igraph_local_efficiency(graph, NULL, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_IN);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, out-neighbors:\n");
igraph_local_efficiency(graph, NULL, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_OUT);
print_vector(&eff_vec);
if (weights_array) {
const igraph_vector_t weights = igraph_vector_view(weights_array, igraph_ecount(graph));
printf("\nWEIGHTED CASE:\n\n");
igraph_global_efficiency(graph, &weights, &eff, IGRAPH_UNDIRECTED);
printf("Global efficiency, undirected: %f\n", eff);
igraph_global_efficiency(graph, &weights, &eff, IGRAPH_DIRECTED);
printf("Global efficiency, directed: %f\n", eff);
igraph_average_local_efficiency(graph, &weights, &eff, IGRAPH_UNDIRECTED, IGRAPH_ALL);
printf("Average local efficiency, undirected: %f\n", eff);
igraph_average_local_efficiency(graph, &weights, &eff, IGRAPH_DIRECTED, IGRAPH_ALL);
printf("Average local efficiency, directed, all neighbors: %f\n", eff);
igraph_average_local_efficiency(graph, &weights, &eff, IGRAPH_DIRECTED, IGRAPH_IN);
printf("Average local efficiency, directed, in-neighbors: %f\n", eff);
igraph_average_local_efficiency(graph, &weights, &eff, IGRAPH_DIRECTED, IGRAPH_OUT);
printf("Average local efficiency, directed, out-neighbors: %f\n", eff);
printf("\nLocal efficiency, undirected:\n");
igraph_local_efficiency(graph, &weights, &eff_vec, igraph_vss_all(), IGRAPH_UNDIRECTED, IGRAPH_ALL);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, all neighbors:\n");
igraph_local_efficiency(graph, &weights, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_ALL);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, in-neighbors:\n");
igraph_local_efficiency(graph, &weights, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_IN);
print_vector(&eff_vec);
printf("\nLocal efficiency, directed, out-neighbors:\n");
igraph_local_efficiency(graph, &weights, &eff_vec, igraph_vss_all(), IGRAPH_DIRECTED, IGRAPH_OUT);
print_vector(&eff_vec);
}
printf("\n\n");
igraph_vector_destroy(&eff_vec);
return 0;
}
int test_ring(void) {
int result;
igraph_t graph;
const igraph_real_t weights_array[] = {1, 1, 1, 1};
igraph_ring(&graph, 4, IGRAPH_DIRECTED, /* mutual = */ false, /* circular = */ true);
result = test_graph("Ring graph", &graph, weights_array);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return result;
}
int test_small_graph(void) {
int result;
igraph_t graph;
const igraph_real_t weights_array[] = {4, 4, 4, 3, 1, 5, 1, 2, 4, 5, 3, 5, 5, 4, 1, 1, 5, 4, 1, 1, 2, 1, 3, 5};
igraph_small(&graph, 13, IGRAPH_DIRECTED,
0,8, 1,3, 1,4, 1,5, 1,8, 1,10, 2,0, 2,1, 2,4, 3,5, 4,2, 4,7,
4,9, 5,3, 5,10, 6,7, 8,2, 8,3, 8,4, 8,9, 9,3, 9,4, 11,9, 11,3,
-1);
result = test_graph("Small test graph", &graph, weights_array);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
return result;
}
int main(void) {
RUN_TEST(test_ring);
RUN_TEST(test_small_graph);
return 0;
}
@@ -0,0 +1,90 @@
###### Testing graph: Ring graph ######
UNWEIGHTED CASE:
Global efficiency, undirected: 0.833333
Global efficiency, directed: 0.611111
Average local efficiency, undirected: 0.500000
Average local efficiency, directed, all neighbors: 0.250000
Average local efficiency, directed, in-neighbors: 0.000000
Average local efficiency, directed, out-neighbors: 0.000000
Local efficiency, undirected:
( 0.5 0.5 0.5 0.5 )
Local efficiency, directed, all neighbors:
( 0.25 0.25 0.25 0.25 )
Local efficiency, directed, in-neighbors:
( 0 0 0 0 )
Local efficiency, directed, out-neighbors:
( 0 0 0 0 )
WEIGHTED CASE:
Global efficiency, undirected: 0.833333
Global efficiency, directed: 0.611111
Average local efficiency, undirected: 0.500000
Average local efficiency, directed, all neighbors: 0.250000
Average local efficiency, directed, in-neighbors: 0.000000
Average local efficiency, directed, out-neighbors: 0.000000
Local efficiency, undirected:
( 0.5 0.5 0.5 0.5 )
Local efficiency, directed, all neighbors:
( 0.25 0.25 0.25 0.25 )
Local efficiency, directed, in-neighbors:
( 0 0 0 0 )
Local efficiency, directed, out-neighbors:
( 0 0 0 0 )
###### Testing graph: Small test graph ######
UNWEIGHTED CASE:
Global efficiency, undirected: 0.509615
Global efficiency, directed: 0.274786
Average local efficiency, undirected: 0.605769
Average local efficiency, directed, all neighbors: 0.329936
Average local efficiency, directed, in-neighbors: 0.212115
Average local efficiency, directed, out-neighbors: 0.149466
Local efficiency, undirected:
( 1 0.633333 0.833333 0.641667 0.5 0.833333 0 0 0.711111 0.722222 1 1 0 )
Local efficiency, directed, all neighbors:
( 0.75 0.401111 0.375 0.340833 0.316667 0.333333 0 0 0.466667 0.305556 0.5 0.5 0 )
Local efficiency, directed, in-neighbors:
( 0 0 0.5 0.340833 0.527778 0.5 0 0 0.166667 0.222222 0.5 0 0 )
Local efficiency, directed, out-neighbors:
( 0 0.3875 0.25 0 0.0555556 0 0 0 0.583333 0.166667 0 0.5 0 )
WEIGHTED CASE:
Global efficiency, undirected: 0.247686
Global efficiency, directed: 0.125356
Average local efficiency, undirected: 0.281019
Average local efficiency, directed, all neighbors: 0.150368
Average local efficiency, directed, in-neighbors: 0.122897
Average local efficiency, directed, out-neighbors: 0.068520
Local efficiency, undirected:
( 0.333333 0.306219 0.525 0.419167 0.358333 0.187037 0 0 0.380635 0.310185 0.333333 0.5 0 )
Local efficiency, directed, all neighbors:
( 0.291667 0.16403 0.245833 0.207976 0.204643 0.075 0 0 0.204987 0.143981 0.166667 0.25 0 )
Local efficiency, directed, in-neighbors:
( 0 0 0.5 0.207976 0.341071 0.125 0 0 0.0625 0.194444 0.166667 0 0 )
Local efficiency, directed, out-neighbors:
( 0 0.180711 0.116667 0 0.0416667 0 0 0 0.246164 0.0555556 0 0.25 0 )
@@ -0,0 +1,106 @@
/*
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 "test_utilities.h"
#define CHECK_PRINT(expr) \
do { \
igraph_error_t err = expr; \
if (err != IGRAPH_SUCCESS) { \
fprintf(stderr, "FAILED on the following graph at line %d:\n", __LINE__); \
fprintf(stderr, "directed: %d, vcount: %d, ecount: %d\n", \
(int) igraph_is_directed(&g), (int) igraph_vcount(&g), (int) igraph_ecount(&g)); \
igraph_write_graph_edgelist(&g, stderr); \
abort(); \
} \
} while (0)
int main(void) {
igraph_vector_t vec;
igraph_real_t val;
igraph_rng_seed(igraph_rng_default(), 987);
igraph_set_warning_handler(&igraph_warning_handler_ignore);
igraph_set_error_handler(&igraph_error_handler_printignore);
igraph_vector_init(&vec, 0);
for (igraph_int_t i=0; i < 1252; i++) {
igraph_t g;
igraph_atlas(&g, i);
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_ALL, NULL, NULL));
CHECK_PRINT(igraph_hub_and_authority_scores(&g, &vec, NULL, &val, NULL, NULL));
igraph_to_directed(&g, IGRAPH_TO_DIRECTED_RANDOM);
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_OUT, NULL, NULL));
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_IN, NULL, NULL));
CHECK_PRINT(igraph_hub_and_authority_scores(&g, &vec, NULL, &val, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.85, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.99, NULL, NULL));
igraph_destroy(&g);
}
for (igraph_int_t i=3; i < 100; i++) {
igraph_t g;
igraph_ring(&g, i, true, false, true);
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, NULL, IGRAPH_OUT, NULL, NULL));
igraph_destroy(&g);
}
{
// A <--> C, D <--> E, B
igraph_t g;
igraph_small(&g, 5, true,
0,2, 2,0, 3,4, 4,2,
-1);
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_OUT, NULL, NULL));
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_IN, NULL, NULL));
CHECK_PRINT(igraph_hub_and_authority_scores(&g, &vec, NULL, &val, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.85, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.99, NULL, NULL));
igraph_destroy(&g);
}
for (igraph_int_t n=4; n <= 7; n++) {
for (igraph_int_t i=0; i < 100; i++) {
igraph_t g;
igraph_erdos_renyi_game_gnp(&g, n, 0.5, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_OUT, NULL, NULL));
CHECK_PRINT(igraph_eigenvector_centrality(&g, &vec, &val, IGRAPH_IN, NULL, NULL));
CHECK_PRINT(igraph_hub_and_authority_scores(&g, &vec, NULL, &val, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.85, NULL, NULL));
CHECK_PRINT(igraph_pagerank(&g, IGRAPH_PAGERANK_ALGO_ARPACK, &vec, &val, igraph_vss_all(), true, 0.99, NULL, NULL));
igraph_destroy(&g);
}
}
igraph_vector_destroy(&vec);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,328 @@
/*
igraph library.
Copyright (C) 2006-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 "test_utilities.h"
int test_no_multiple(void) {
igraph_t g;
igraph_bool_t simple, has_multi;
/* Ensure that the test is deterministic */
igraph_rng_seed(igraph_rng_default(), 137);
/* null graph */
igraph_erdos_renyi_game_gnm(&g, 0, 0, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 0);
IGRAPH_ASSERT(igraph_ecount(&g) == 0);
IGRAPH_ASSERT(! igraph_is_directed(&g));
igraph_destroy(&g);
/* singleton */
igraph_erdos_renyi_game_gnm(&g, 1, 0, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 1);
IGRAPH_ASSERT(igraph_ecount(&g) == 0);
IGRAPH_ASSERT(! igraph_is_directed(&g));
igraph_destroy(&g);
/* singleton with loop */
igraph_erdos_renyi_game_gnm(&g, 1, 1, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 1);
IGRAPH_ASSERT(igraph_ecount(&g) == 1);
IGRAPH_ASSERT(! igraph_is_directed(&g));
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 1, 1, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 1);
IGRAPH_ASSERT(igraph_ecount(&g) == 1);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_destroy(&g);
/* directed with loops */
igraph_erdos_renyi_game_gnm(&g, 10, 10 * 10 - 1, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 10);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 10 - 1);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_has_multiple(&g, &has_multi); IGRAPH_ASSERT(! has_multi);
igraph_simplify(&g, /*remove_multiple=*/ false, /*remove_loops=*/ true, /*edge_comb=*/ NULL);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 9 || igraph_ecount(&g) == 10 * 9 - 1);
igraph_destroy(&g);
/* directed without loops */
igraph_erdos_renyi_game_gnm(&g, 10, 10 * 9 - 1, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 10);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 9 - 1);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED); IGRAPH_ASSERT(simple);
igraph_destroy(&g);
/* undirected with loops */
igraph_erdos_renyi_game_gnm(&g, 10, 10 * 11 / 2 - 1, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 10);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 11 / 2 - 1);
IGRAPH_ASSERT(! igraph_is_directed(&g));
igraph_has_multiple(&g, &has_multi); IGRAPH_ASSERT(! has_multi);
igraph_simplify(&g, /*remove_multiple=*/ false, /*remove_loops=*/ true, /*edge_comb=*/ NULL);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 9 / 2 || igraph_ecount(&g) == 10 * 9 / 2 - 1);
igraph_destroy(&g);
/* undirected without loops */
igraph_erdos_renyi_game_gnm(&g, 10, 10 * 9 / 2 - 1, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 10);
IGRAPH_ASSERT(igraph_ecount(&g) == 10 * 9 / 2 - 1);
IGRAPH_ASSERT(! igraph_is_directed(&g));
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED); IGRAPH_ASSERT(simple);
igraph_destroy(&g);
/* Create a couple of large graphs too */
igraph_erdos_renyi_game_gnm(&g, 100000, 200000, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 100000);
IGRAPH_ASSERT(igraph_ecount(&g) == 200000);
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED); IGRAPH_ASSERT(simple);
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 100000, 200000, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 100000);
IGRAPH_ASSERT(igraph_ecount(&g) == 200000);
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED); IGRAPH_ASSERT(simple);
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 100000, 200000, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 100000);
IGRAPH_ASSERT(igraph_ecount(&g) == 200000);
igraph_has_multiple(&g, &has_multi); IGRAPH_ASSERT(! has_multi);
igraph_simplify(&g, false, true, /*edge_comb=*/ NULL); /* only remove loops */
igraph_destroy(&g);
igraph_erdos_renyi_game_gnm(&g, 100000, 200000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&g) == 100000);
IGRAPH_ASSERT(igraph_ecount(&g) == 200000);
igraph_has_multiple(&g, &has_multi); IGRAPH_ASSERT(! has_multi);
igraph_destroy(&g);
return 0;
}
int test_multiple(void) {
igraph_t graph1, graph2;
igraph_bool_t same, has_loop;
igraph_rng_seed(igraph_rng_default(), 137); /* Makes test deterministic */
/* null graph */
igraph_erdos_renyi_game_gnm(&graph1, 0, 0, IGRAPH_UNDIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 0);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 0);
print_graph(&graph1);
igraph_destroy(&graph1);
/* null graph with more than zero edges is invalid */
CHECK_ERROR(
igraph_erdos_renyi_game_gnm(&graph1, 0, 1, IGRAPH_UNDIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED),
IGRAPH_EINVAL
);
/* singleton with no loops and more than zero edges is invalid */
CHECK_ERROR(
igraph_erdos_renyi_game_gnm(&graph1, 1, 1, IGRAPH_UNDIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED),
IGRAPH_EINVAL
);
/* singleton with multiple loops */
igraph_erdos_renyi_game_gnm(&graph1, 1, 2, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED); /* undirected with loops */
IGRAPH_ASSERT(igraph_vcount(&graph1) == 1);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 2);
print_graph(&graph1);
igraph_destroy(&graph1);
igraph_erdos_renyi_game_gnm(&graph1, 1, 3, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED); /* undirected with loops */
IGRAPH_ASSERT(igraph_vcount(&graph1) == 1);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 3);
print_graph(&graph1);
igraph_destroy(&graph1);
/* directed with loops */
igraph_erdos_renyi_game_gnm(&graph1, 10, 560, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 10);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 560);
IGRAPH_ASSERT(igraph_is_directed(&graph1));
igraph_simplify(&graph1, true, false, NULL);
IGRAPH_ASSERT(igraph_ecount(&graph1) <= 100);
igraph_destroy(&graph1);
/* directed without loops */
igraph_erdos_renyi_game_gnm(&graph1, 10, 890, IGRAPH_DIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 10);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 890);
IGRAPH_ASSERT(igraph_is_directed(&graph1));
igraph_has_loop(&graph1, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_simplify(&graph1, true, false, NULL);
IGRAPH_ASSERT(igraph_ecount(&graph1) <= 90);
igraph_destroy(&graph1);
/* undirected with loops */
igraph_erdos_renyi_game_gnm(&graph1, 10, 540, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 10);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 540);
IGRAPH_ASSERT(!igraph_is_directed(&graph1));
igraph_simplify(&graph1, true, false, NULL);
IGRAPH_ASSERT(igraph_ecount(&graph1) <= 55);
igraph_destroy(&graph1);
/* undirected without loops */
igraph_erdos_renyi_game_gnm(&graph1, 10, 440, IGRAPH_UNDIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 10);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 440);
IGRAPH_ASSERT(!igraph_is_directed(&graph1));
igraph_has_loop(&graph1, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_copy(&graph2, &graph1);
igraph_simplify(&graph1, true, true, NULL);
igraph_simplify(&graph2, true, false, NULL);
igraph_isomorphic(&graph1, &graph2, &same);
IGRAPH_ASSERT(same);
igraph_destroy(&graph1);
igraph_destroy(&graph2);
/* large graphs */
igraph_erdos_renyi_game_gnm(&graph1, 1000, 200000, IGRAPH_UNDIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 1000);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 200000);
igraph_has_loop(&graph1, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_destroy(&graph1);
igraph_erdos_renyi_game_gnm(&graph1, 100000, 200000, IGRAPH_DIRECTED, IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 100000);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 200000);
igraph_has_loop(&graph1, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_destroy(&graph1);
igraph_erdos_renyi_game_gnm(&graph1, 100000, 200000, IGRAPH_UNDIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 100000);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 200000);
igraph_destroy(&graph1);
igraph_erdos_renyi_game_gnm(&graph1, 100000, 200000, IGRAPH_DIRECTED, IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW, IGRAPH_EDGE_UNLABELED);
IGRAPH_ASSERT(igraph_vcount(&graph1) == 100000);
IGRAPH_ASSERT(igraph_ecount(&graph1) == 200000);
igraph_destroy(&graph1);
return 0;
}
int test_iea(void) {
igraph_t g;
igraph_bool_t has_loop;
/* null graph */
igraph_iea_game(&g, 0, 0, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 0);
IGRAPH_ASSERT(igraph_ecount(&g) == 0);
IGRAPH_ASSERT(!igraph_is_directed(&g));
igraph_destroy(&g);
/* null graph with more than zero edges is invalid */
CHECK_ERROR(
igraph_iea_game(&g, 0, 1, IGRAPH_UNDIRECTED, IGRAPH_LOOPS),
IGRAPH_EINVAL
);
/* singleton with no loops and more than zero edges is invalid */
CHECK_ERROR(
igraph_iea_game(&g, 1, 1, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS),
IGRAPH_EINVAL
);
/* singleton with loop */
igraph_iea_game(&g, 1, 1, IGRAPH_UNDIRECTED, IGRAPH_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 1);
IGRAPH_ASSERT(igraph_ecount(&g) == 1);
IGRAPH_ASSERT(!igraph_is_directed(&g));
igraph_destroy(&g);
/* singleton with three loops */
igraph_iea_game(&g, 1, 3, IGRAPH_DIRECTED, IGRAPH_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 1);
IGRAPH_ASSERT(igraph_ecount(&g) == 3);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_destroy(&g);
/* larger undirected */
igraph_iea_game(&g, 5, 10, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 5);
IGRAPH_ASSERT(igraph_ecount(&g) == 10);
IGRAPH_ASSERT(!igraph_is_directed(&g));
igraph_has_loop(&g, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_destroy(&g);
igraph_iea_game(&g, 5, 10, IGRAPH_UNDIRECTED, IGRAPH_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 5);
IGRAPH_ASSERT(igraph_ecount(&g) == 10);
IGRAPH_ASSERT(!igraph_is_directed(&g));
igraph_destroy(&g);
/* larger directed */
igraph_iea_game(&g, 4, 11, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 4);
IGRAPH_ASSERT(igraph_ecount(&g) == 11);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_has_loop(&g, &has_loop); IGRAPH_ASSERT(! has_loop);
igraph_destroy(&g);
igraph_iea_game(&g, 4, 11, IGRAPH_DIRECTED, IGRAPH_LOOPS);
IGRAPH_ASSERT(igraph_vcount(&g) == 4);
IGRAPH_ASSERT(igraph_ecount(&g) == 11);
IGRAPH_ASSERT(igraph_is_directed(&g));
igraph_destroy(&g);
return 0;
}
int main(void) {
RUN_TEST(test_no_multiple);
RUN_TEST(test_multiple);
RUN_TEST(test_iea);
}
@@ -0,0 +1,260 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
/* Helper functions for hypothesis testing for binomial and negative binomial distr. */
igraph_real_t log_binom_prob(igraph_int_t n, igraph_real_t p, igraph_int_t k) {
return lgamma(1+n) - lgamma(1+k) - lgamma(1 - k + n) +
k * log(p) + (n-k) * log(1-p);
}
igraph_real_t log_neg_binom_prob(igraph_int_t n, igraph_real_t p, igraph_int_t k) {
return lgamma(k + n) - lgamma(1+k) - lgamma(n) +
k * log(1-p) + n * log(p);
}
igraph_real_t binom_test(igraph_int_t n, igraph_real_t p, igraph_int_t k0) {
igraph_real_t res = 0;
igraph_real_t lP0 = log_binom_prob(n, p, k0);
igraph_real_t last_lP = -IGRAPH_INFINITY;
for (igraph_int_t k=0; k < n; k++) {
igraph_real_t lP = log_binom_prob(n, p, k);
if (lP <= lP0) {
res += exp(lP);
/* stop when relative change to 'res' is < 10^-12 */
if (lP < last_lP && lP - log(res) < -12.0 * log(10)) break;
}
last_lP = lP;
}
return res;
}
igraph_real_t neg_binom_test(igraph_int_t n, igraph_real_t p, igraph_int_t k0) {
igraph_real_t res = 0;
igraph_real_t lP0 = log_neg_binom_prob(n, p, k0);
igraph_real_t last_lP = -IGRAPH_INFINITY;
for (igraph_int_t k=0; ; k++) {
igraph_real_t lP = log_neg_binom_prob(n, p, k);
if (lP <= lP0) {
res += exp(lP);
/* stop when relative change to 'res' is < 10^-12 */
if (lP < last_lP && lP - log(res) < -12.0 * log(10)) break;
}
last_lP = lP;
}
return res;
}
void stress_test(void) {
igraph_rng_seed(igraph_rng_default(), 137);
for (igraph_int_t size=2; size < 5; size++) {
for (igraph_int_t i=0; i < 100; i++) {
igraph_t g;
igraph_bool_t simple;
igraph_erdos_renyi_game_gnp(&g, size, 0.5, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED);
if (! simple) {
printf("Erdos-Renyi GNP graph is not simple! size=%" IGRAPH_PRId ", i=%" IGRAPH_PRId ".\n",
size, i);
print_graph(&g);
}
IGRAPH_ASSERT(simple);
igraph_destroy(&g);
}
}
for (igraph_int_t size=2; size < 5; size++) {
for (igraph_int_t i=0; i < 100; i++) {
igraph_t g;
igraph_bool_t simple;
igraph_erdos_renyi_game_gnp(&g, size, 0.5, IGRAPH_UNDIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_is_simple(&g, &simple, IGRAPH_DIRECTED);
if (! simple) {
printf("Erdos-Renyi GNP graph is not simple! size=%" IGRAPH_PRId ", i=%" IGRAPH_PRId ".\n",
size, i);
print_graph(&g);
}
IGRAPH_ASSERT(simple);
igraph_destroy(&g);
}
}
VERIFY_FINALLY_STACK();
}
void check_gnp(
igraph_int_t n, igraph_real_t p,
igraph_bool_t directed,
igraph_bool_t loops, igraph_bool_t multiple,
igraph_bool_t edge_labeled) {
igraph_t graph;
igraph_bool_t has_loop, has_multi;
igraph_edge_type_sw_t allowed_edge_types;
allowed_edge_types = IGRAPH_SIMPLE_SW;
if (loops) allowed_edge_types |= IGRAPH_LOOPS_SW;
if (multiple) allowed_edge_types |= IGRAPH_MULTI_SW;
igraph_erdos_renyi_game_gnp(&graph, n, p, directed, allowed_edge_types, edge_labeled);
IGRAPH_ASSERT(igraph_is_directed(&graph) == directed);
IGRAPH_ASSERT(igraph_vcount(&graph) == n);
igraph_has_loop(&graph, &has_loop);
igraph_has_multiple(&graph, &has_multi);
if (!multiple) IGRAPH_ASSERT(!has_multi);
if (!loops) IGRAPH_ASSERT(!has_loop);
igraph_real_t complete_ecount;
if (directed) {
complete_ecount = loops ? (igraph_real_t) n * n : (igraph_real_t) n * (n-1.0);
} else {
complete_ecount = loops ? (igraph_real_t) n * (n+1.0) / 2.0 : (igraph_real_t) n * (n-1) / 2.0;
}
if (p == 0 || complete_ecount == 0) {
IGRAPH_ASSERT(igraph_ecount(&graph) == 0);
} else if (!multiple && p == 1) {
IGRAPH_ASSERT(igraph_ecount(&graph) == complete_ecount);
} else {
/* Edge count check using hypothesis testing.
* With simple graphs, the edge count follows a binomial distribution,
* with multigraphs, a negative binomial distribution. In both cases,
* we perform an exact two-tailed test unless the graph is too large.
*/
igraph_real_t pval = 1;
igraph_real_t m = complete_ecount * p;
igraph_real_t sd = multiple ? sqrt(m * (1+p)) : sqrt(m * (1-p));
igraph_real_t dev = (m - igraph_ecount(&graph)) / sd;
igraph_bool_t do_test = m < 10000 && ! edge_labeled;
if (do_test) {
if (multiple) {
pval = neg_binom_test(complete_ecount, 1 / (1 + p), igraph_ecount(&graph));
} else {
pval = binom_test(complete_ecount, p, igraph_ecount(&graph));
}
printf("p-value=%.3f ", pval);
} else {
printf("p-value= ? ");
}
/* Output stats, including the actual and expected edge counts,
* as well as their difference in standard deviations. */
printf("for n=%6" IGRAPH_PRId ", p=%5g, %s, %s, %s; "
"ecount: %6" IGRAPH_PRId ", expected: %8.1f, % .2f SD\n",
n, p,
directed ? " directed" : "undirected",
loops ? " loops" : "no-loops",
multiple ? " multi" : "no-multi",
igraph_ecount(&graph),
m, dev);
/* Failure is unlikely, but possible. If it happens, check manually. */
if (do_test) {
IGRAPH_ASSERT(pval > 0.01);
} else if (!edge_labeled) {
/* If the graph is too large for the exact test to run efficiently,
* use a normal approximation, even though this is inaccurate with
* small p. */
IGRAPH_ASSERT(fabs(dev) < 2.576);
}
}
igraph_destroy(&graph);
}
/* Check all parameter combinations */
void check_all_gnp(igraph_int_t n, igraph_real_t p) {
if (p <= 1) {
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS, IGRAPH_NO_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_LOOPS, IGRAPH_NO_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_LOOPS, IGRAPH_NO_MULTIPLE, IGRAPH_EDGE_UNLABELED);
}
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_UNLABELED);
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_LABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_LABELED);
check_gnp(n, p, IGRAPH_UNDIRECTED, IGRAPH_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_LABELED);
check_gnp(n, p, IGRAPH_DIRECTED, IGRAPH_LOOPS, IGRAPH_MULTIPLE, IGRAPH_EDGE_LABELED);
}
void test_examples(void) {
/* Ensure that the test is deterministic */
igraph_rng_seed(igraph_rng_default(), 42);
check_all_gnp(0, 0.0);
/* Empty graph */
check_all_gnp(10, 0.0);
/* Singleton, with loop if allowed */
check_all_gnp(1, 1.0);
check_all_gnp(1, 5.0);
/* Complete graph */
check_all_gnp(10, 1.0);
/* Random graph */
check_all_gnp(10, 0.5);
check_all_gnp(10, 12.0);
/* Create a couple of larger graphs too */
check_all_gnp(100, 1.0 / 100);
check_all_gnp(100, 2.0 / 100);
check_all_gnp(100, 80.0 / 100);
check_all_gnp(1000, 2.0 / 1000);
check_all_gnp(100000, 2.0 / 100000);
VERIFY_FINALLY_STACK();
}
int main(void) {
test_examples();
stress_test();
return 0;
}
@@ -0,0 +1,71 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph_error.h>
#include <stdio.h>
#include <stdlib.h>
int cause_error(void) {
IGRAPH_ERRORF("%d %f %ld %c", IGRAPH_EINVAL, 1, 1.0, 1L, 'a');
return IGRAPH_SUCCESS;
}
int cause_warning(void) {
IGRAPH_WARNINGF("%d %f %ld %c", 1, 1.0, 1L, 'a');
return IGRAPH_SUCCESS;
}
int cause_fatal(void) {
IGRAPH_FATALF("%d %f %ld %c", 1, 1.0, 1L, 'a');
}
void error_handler(const char *reason, const char *file, int line, igraph_error_t igraph_errno) {
IGRAPH_UNUSED(file);
IGRAPH_UNUSED(line);
printf("Error. Reason: %s\nErrno: %d\n", reason, igraph_errno);
}
void warning_handler(const char *reason, const char *file, int line) {
IGRAPH_UNUSED(file);
IGRAPH_UNUSED(line);
printf("Warning. Reason: %s\n", reason);
}
void fatal_handler(const char *reason, const char *file, int line) {
IGRAPH_UNUSED(file);
IGRAPH_UNUSED(line);
printf("Fatal. Reason: %s\n", reason);
exit(0);
}
int main(void) {
igraph_set_error_handler(&error_handler);
igraph_set_warning_handler(&warning_handler);
igraph_set_fatal_handler(&fatal_handler);
IGRAPH_ASSERT(cause_error() == IGRAPH_EINVAL);
IGRAPH_ASSERT(cause_warning() == IGRAPH_SUCCESS);
cause_fatal();
/* The igraph_fatal() call must not return, so the following lines should not run. */
printf("This should not be printed.");
return 1;
}
@@ -0,0 +1,4 @@
Error. Reason: 1 1.000000 1 a
Errno: 4
Warning. Reason: 1 1.000000 1 a
Fatal. Reason: 1 1.000000 1 a
@@ -0,0 +1,61 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph_paths.h>
#include "test_utilities.h"
igraph_error_t test_path_expansion(void) {
igraph_vector_int_t path;
igraph_vector_int_init(&path, 0);
IGRAPH_CHECK(igraph_expand_path_to_pairs(&path));
print_vector_int(&path);
igraph_vector_int_destroy(&path);
igraph_vector_int_init(&path, 0);
igraph_vector_int_push_back(&path, 0);
IGRAPH_CHECK(igraph_expand_path_to_pairs(&path));
print_vector_int(&path);
igraph_vector_int_destroy(&path);
igraph_vector_int_init(&path, 0);
igraph_vector_int_push_back(&path, 0);
igraph_vector_int_push_back(&path, 1);
IGRAPH_CHECK(igraph_expand_path_to_pairs(&path));
print_vector_int(&path);
igraph_vector_int_destroy(&path);
igraph_vector_int_init(&path, 0);
igraph_vector_int_push_back(&path, 2);
igraph_vector_int_push_back(&path, 3);
igraph_vector_int_push_back(&path, 5);
igraph_vector_int_push_back(&path, 7);
IGRAPH_CHECK(igraph_expand_path_to_pairs(&path));
print_vector_int(&path);
igraph_vector_int_destroy(&path);
return IGRAPH_SUCCESS;
}
int main(void) {
IGRAPH_ASSERT(test_path_expansion() == IGRAPH_SUCCESS);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,4 @@
( )
( )
( 0 1 )
( 2 3 3 5 5 7 )
@@ -0,0 +1,39 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
igraph_fatal_handler_t hanlder;
void handler(const char *reason, const char *file, int line) {
printf("Reason: %s\nFile: %s\nLine: %d\n", reason, file, line);
exit(0); /* We use exit(0) instead of abort() to allow the test to succeed. */
}
int main(void) {
igraph_set_fatal_handler(&handler);
igraph_fatal("REASON", "FILENAME", 123);
/* The igraph_fatal() call must not return, so the following lines should not run. */
printf("This should not be printed.");
return 0;
}
@@ -0,0 +1,3 @@
Reason: REASON
File: FILENAME
Line: 123
@@ -0,0 +1,91 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include <stdio.h>
#include "test_utilities.h"
/* This test verifies that trying to read an empty file does not cause
* a crash or fatal error in any of the file format readers. */
int main(void) {
igraph_t graph;
FILE *file;
file = fopen("empty", "r");
IGRAPH_ASSERT(file != NULL);
/* Formats for which an emtpy file is valid */
/* Edge list */
IGRAPH_ASSERT(igraph_read_graph_edgelist(&graph, file, 0, IGRAPH_UNDIRECTED) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vcount(&graph) == 0);
igraph_destroy(&graph);
rewind(file);
VERIFY_FINALLY_STACK();
/* NCOL */
IGRAPH_ASSERT(igraph_read_graph_ncol(&graph, file, NULL, 1, IGRAPH_ADD_WEIGHTS_IF_PRESENT, IGRAPH_UNDIRECTED) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vcount(&graph) == 0);
igraph_destroy(&graph);
rewind(file);
VERIFY_FINALLY_STACK();
/* LGL */
IGRAPH_ASSERT(igraph_read_graph_lgl(&graph, file, 1, IGRAPH_ADD_WEIGHTS_IF_PRESENT, IGRAPH_UNDIRECTED) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_vcount(&graph) == 0);
igraph_destroy(&graph);
rewind(file);
VERIFY_FINALLY_STACK();
/* Formats for which an empty file is invalid */
igraph_set_error_handler(&igraph_error_handler_printignore);
/* GraphML */
IGRAPH_ASSERT(igraph_read_graph_graphml(&graph, file, 0) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
/* Pajek */
IGRAPH_ASSERT(igraph_read_graph_pajek(&graph, file) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
/* DL */
IGRAPH_ASSERT(igraph_read_graph_dl(&graph, file, IGRAPH_UNDIRECTED) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
/* GML */
IGRAPH_ASSERT(igraph_read_graph_gml(&graph, file) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
/* graphdb */
IGRAPH_ASSERT(igraph_read_graph_graphdb(&graph, file, IGRAPH_UNDIRECTED) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
/* DIMACS flow problem */
IGRAPH_ASSERT(igraph_read_graph_dimacs_flow(&graph, file, NULL, NULL, NULL, NULL, NULL, IGRAPH_DIRECTED) != IGRAPH_SUCCESS);
rewind(file);
VERIFY_FINALLY_STACK();
return 0;
}
+67
View File
@@ -0,0 +1,67 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard st, Cambridge MA, 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_int_t n_vertices = 10;
printf("Null graph\n");
igraph_full(&g, 0, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Singleton graph, no loops\n");
igraph_full(&g, 1, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Singleton graph, loops\n");
igraph_full(&g, 1, IGRAPH_UNDIRECTED, IGRAPH_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Undirected, no loops\n");
igraph_full(&g, n_vertices, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Directed, no loops\n");
igraph_full(&g, n_vertices, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Undirected, with loops\n");
igraph_full(&g, n_vertices, IGRAPH_UNDIRECTED, IGRAPH_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
printf("Directed, with loops\n");
igraph_full(&g, n_vertices, IGRAPH_DIRECTED, IGRAPH_LOOPS);
print_graph_canon(&g);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
+326
View File
@@ -0,0 +1,326 @@
Null graph
directed: false
vcount: 0
edges: {
}
Singleton graph, no loops
directed: false
vcount: 1
edges: {
}
Singleton graph, loops
directed: false
vcount: 1
edges: {
0 0
}
Undirected, no loops
directed: false
vcount: 10
edges: {
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 4
3 5
3 6
3 7
3 8
3 9
4 5
4 6
4 7
4 8
4 9
5 6
5 7
5 8
5 9
6 7
6 8
6 9
7 8
7 9
8 9
}
Directed, no loops
directed: true
vcount: 10
edges: {
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 0
3 1
3 2
3 4
3 5
3 6
3 7
3 8
3 9
4 0
4 1
4 2
4 3
4 5
4 6
4 7
4 8
4 9
5 0
5 1
5 2
5 3
5 4
5 6
5 7
5 8
5 9
6 0
6 1
6 2
6 3
6 4
6 5
6 7
6 8
6 9
7 0
7 1
7 2
7 3
7 4
7 5
7 6
7 8
7 9
8 0
8 1
8 2
8 3
8 4
8 5
8 6
8 7
8 9
9 0
9 1
9 2
9 3
9 4
9 5
9 6
9 7
9 8
}
Undirected, with loops
directed: false
vcount: 10
edges: {
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 3
3 4
3 5
3 6
3 7
3 8
3 9
4 4
4 5
4 6
4 7
4 8
4 9
5 5
5 6
5 7
5 8
5 9
6 6
6 7
6 8
6 9
7 7
7 8
7 9
8 8
8 9
9 9
}
Directed, with loops
directed: true
vcount: 10
edges: {
0 0
0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 0
2 1
2 2
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 0
3 1
3 2
3 3
3 4
3 5
3 6
3 7
3 8
3 9
4 0
4 1
4 2
4 3
4 4
4 5
4 6
4 7
4 8
4 9
5 0
5 1
5 2
5 3
5 4
5 5
5 6
5 7
5 8
5 9
6 0
6 1
6 2
6 3
6 4
6 5
6 6
6 7
6 8
6 9
7 0
7 1
7 2
7 3
7 4
7 5
7 6
7 7
7 8
7 9
8 0
8 1
8 2
8 3
8 4
8 5
8 6
8 7
8 8
8 9
9 0
9 1
9 2
9 3
9 4
9 5
9 6
9 7
9 8
9 9
}
@@ -0,0 +1,123 @@
#include <igraph.h>
#include "core/genheap.h"
#include "test_utilities.h"
typedef struct intpair_t {
int x, y;
} intpair_t;
int cmp(const void *a, const void *b) {
const intpair_t *sa = a, *sb = b;
if (sa->x < sb->x) return -1;
if (sa->x > sb->x) return 1;
if (sa->y < sb->y) return -1;
if (sa->y > sb->y) return 1;
return 0;
}
void intpair_print(const intpair_t *p) {
printf("(%d, %d)", p->x, p->y);
}
int main(void) {
igraph_int_t n;
igraph_vector_int_t idx;
igraph_gen2wheap_t h;
igraph_int_t i;
intpair_t p;
igraph_rng_seed(igraph_rng_default(), 42);
n = 10;
igraph_gen2wheap_init(&h, cmp, sizeof(intpair_t), n);
IGRAPH_ASSERT(igraph_gen2wheap_max_size(&h) == n);
igraph_vector_int_init_range(&idx, 0, n);
igraph_vector_int_shuffle(&idx);
for (i=0; i < n; i++) {
igraph_int_t j = VECTOR(idx)[i];
p.x = RNG_INTEGER(1, 10);
p.y = RNG_INTEGER(1, 10);
printf("Adding %2" IGRAPH_PRId ": ", j);
intpair_print(&p);
printf("\n");
IGRAPH_ASSERT(! igraph_gen2wheap_has_elem(&h, j));
igraph_gen2wheap_push_with_index(&h, j, &p);
igraph_gen2wheap_check(&h);
IGRAPH_ASSERT(igraph_gen2wheap_has_elem(&h, j));
IGRAPH_ASSERT(igraph_gen2wheap_size(&h) == i+1);
}
printf("\n");
i = igraph_gen2wheap_size(&h);
while (!igraph_gen2wheap_empty(&h)) {
printf("Removing %2" IGRAPH_PRId ": ", igraph_gen2wheap_max_index(&h));
intpair_print(igraph_gen2wheap_max(&h));
printf("\n");
igraph_gen2wheap_delete_max(&h);
igraph_gen2wheap_check(&h);
i--;
IGRAPH_ASSERT(igraph_gen2wheap_size(&h) == i);
}
printf("\n");
n=5;
for (igraph_int_t i=0; i < n; i++) {
p.x = RNG_INTEGER(1, 10);
p.y = RNG_INTEGER(1, 10);
printf("Adding %2" IGRAPH_PRId ": ", i);
intpair_print(&p);
printf("\n");
IGRAPH_ASSERT(! igraph_gen2wheap_has_elem(&h, i));
igraph_gen2wheap_push_with_index(&h, i, &p);
igraph_gen2wheap_check(&h);
IGRAPH_ASSERT(igraph_gen2wheap_has_elem(&h, i));
IGRAPH_ASSERT(igraph_gen2wheap_size(&h) == i+1);
}
i = 1;
p.x = -1; p.y = -1;
printf("\nModifying %" IGRAPH_PRId " to ", i);
intpair_print(&p);
printf("\n");
igraph_gen2wheap_modify(&h, i, &p);
igraph_gen2wheap_check(&h);
i = igraph_gen2wheap_max_index(&h);
p = * (intpair_t *) igraph_gen2wheap_max(&h);
p.x -= 3;
printf("Modifying max to ");
intpair_print(&p);
printf("\n");
igraph_gen2wheap_modify(&h, i, &p);
igraph_gen2wheap_check(&h);
printf("\n");
i = igraph_gen2wheap_size(&h);
while (!igraph_gen2wheap_empty(&h)) {
printf("Removing %2" IGRAPH_PRId ": ", igraph_gen2wheap_max_index(&h));
intpair_print(igraph_gen2wheap_max(&h));
printf("\n");
igraph_gen2wheap_delete_max(&h);
igraph_gen2wheap_check(&h);
i--;
IGRAPH_ASSERT(igraph_gen2wheap_size(&h) == i);
}
printf("\n");
igraph_vector_int_destroy(&idx);
igraph_gen2wheap_destroy(&h);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,37 @@
Adding 9: (6, 9)
Adding 2: (10, 10)
Adding 0: (7, 4)
Adding 8: (9, 2)
Adding 3: (7, 2)
Adding 5: (7, 1)
Adding 7: (5, 1)
Adding 6: (5, 4)
Adding 4: (10, 10)
Adding 1: (6, 4)
Removing 4: (10, 10)
Removing 2: (10, 10)
Removing 8: (9, 2)
Removing 0: (7, 4)
Removing 3: (7, 2)
Removing 5: (7, 1)
Removing 9: (6, 9)
Removing 1: (6, 4)
Removing 6: (5, 4)
Removing 7: (5, 1)
Adding 0: (10, 7)
Adding 1: (6, 7)
Adding 2: (2, 5)
Adding 3: (5, 2)
Adding 4: (10, 2)
Modifying 1 to (-1, -1)
Modifying max to (7, 7)
Removing 4: (10, 2)
Removing 0: (7, 7)
Removing 3: (5, 2)
Removing 2: (2, 5)
Removing 1: (-1, -1)
@@ -0,0 +1,113 @@
/*
igraph library.
Copyright (C) 2021-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_real_t global, global2, global3;
/* Small graphs */
printf("Null graph: ");
igraph_empty(&g, 0, IGRAPH_UNDIRECTED);
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nSingleton graph: ");
igraph_empty(&g, 1, IGRAPH_UNDIRECTED);
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nTwo connected vertices: ");
igraph_small(&g, 2, IGRAPH_UNDIRECTED, 0,1, -1);
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nTriangle: ");
igraph_full(&g, 3, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nTwo-star: ");
igraph_small(&g, 3, IGRAPH_UNDIRECTED, 0,2, 0,1, -1);
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nZachary karate club: ");
igraph_famous(&g, "Zachary");
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%g");
printf("\n");
igraph_destroy(&g);
printf("\nDirected and multigraphs:\n");
igraph_small(&g, 20, IGRAPH_DIRECTED,
15, 12, 12, 10, 15, 0, 11, 10, 2, 8, 8, 6, 13, 17, 10, 10, 17, 2, 14,
0, 16, 13, 14, 14, 0, 5, 6, 4, 0, 9, 0, 6, 10, 9, 16, 4, 14, 5, 17,
15, 14, 9, 17, 17, 1, 4, 10, 16, 7, 0, 11, 12, 6, 13, 2, 17, 4, 0, 0,
14, 4, 0, 6, 16, 16, 14, 13, 13, 12, 11, 3, 11, 11, 3, 6, 7, 4, 14,
10, 8, 13, 7, 14, 2, 5, 2, 0, 14, 3, 15, 5, 5, 7, 2, 14, 15, 5, 10,
10, 16, 7, 9, 14, 0, 15, 7, 13, 1, 15, 1, 4, 5, 4, 6, 16, 13, 6, 17,
8, 6, 9, 3, 8, 6, 6, 14, 11, 14, 6, 10, 10, 5, 1, 0, 16, 17, 9, 1, 5,
0, 5, 15, 8, 0, 0, 8, 5, 3, 9, 4, 13, 12, 11, 0, 11, 0, 10, 6, 4, 13,
8, 9, 11, 11, 3, 16, 1, 2, 16, 0, 9, 8, 3, 8, 8, 7, 12, 10, 9, 3, 13,
5, 3, 9, 6, 2, 11, 10, 1, 16, 0, 2, 10, 17, 16, 8, 11, 5, 13, 0, 19, 19,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-1);
printf("\nDirected multi: ");
igraph_transitivity_undirected(&g, &global, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global, "%.10g");
printf("\n");
printf("Undirected multi: ");
igraph_to_undirected(&g, IGRAPH_TO_UNDIRECTED_COLLAPSE, NULL);
igraph_transitivity_undirected(&g, &global2, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global2, "%.10g");
printf("\n");
printf("Simple: ");
igraph_simplify(&g, true, true, NULL);
igraph_transitivity_undirected(&g, &global3, IGRAPH_TRANSITIVITY_NAN);
print_real(stdout, global3, "%.10g");
printf("\n");
IGRAPH_ASSERT(global == global2);
IGRAPH_ASSERT(global == global3);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,17 @@
Null graph: NaN
Singleton graph: NaN
Two connected vertices: NaN
Triangle: 1
Two-star: 0
Zachary karate club: 0.255682
Directed and multigraphs:
Directed multi: 0.4357541899
Undirected multi: 0.4357541899
Simple: 0.4357541899
@@ -0,0 +1,72 @@
#include <igraph.h>
#include <time.h>
#include "test_utilities.h"
static clock_t start;
/* Wait for at least a second before attempting interruption */
igraph_bool_t interruption_handler(void) {
if ( ((double) (clock() - start)) / CLOCKS_PER_SEC > 1.0 ) {
IGRAPH_FINALLY_FREE();
return true;
} else {
return false;
}
}
int main(void) {
igraph_t graph;
igraph_vector_int_t res;
igraph_error_handler_t *ehandler;
igraph_vector_int_init(&res, 0);
/* Skip test when igraph does not have GLPK support. */
igraph_small(&graph, 0, IGRAPH_DIRECTED, 0,1, -1);
ehandler = igraph_set_error_handler(igraph_error_handler_ignore);
if (igraph_feedback_arc_set(&graph, &res, NULL, IGRAPH_FAS_EXACT_IP_TI) == IGRAPH_UNIMPLEMENTED) {
igraph_destroy(&graph);
igraph_vector_int_destroy(&res);
return 77;
}
igraph_set_error_handler(ehandler);
igraph_destroy(&graph);
/* Current versions of GLPK will error if more than 100 million rows (MAX_M) are added.
The graph size of 700 is chosen to just exceed this size. If future GLPK
versions relax this restriction, the test will need to be updated accordinly. */
igraph_full(&graph, 700, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS);
ehandler = igraph_set_error_handler(igraph_error_handler_printignore);
IGRAPH_ASSERT(igraph_feedback_arc_set(&graph, &res, NULL, IGRAPH_FAS_EXACT_IP_TI) == IGRAPH_FAILURE);
igraph_set_error_handler(ehandler);
igraph_destroy(&graph);
igraph_vector_int_destroy(&res);
VERIFY_FINALLY_STACK();
igraph_rng_seed(igraph_rng_default(), 42);
igraph_vector_int_init(&res, 0);
igraph_erdos_renyi_game_gnm(&graph, 100, 200, IGRAPH_DIRECTED, IGRAPH_SIMPLE_SW, IGRAPH_EDGE_UNLABELED);
igraph_set_interruption_handler(interruption_handler);
ehandler = igraph_set_error_handler(igraph_error_handler_printignore);
start = clock();
IGRAPH_ASSERT(igraph_feedback_arc_set(&graph, &res, NULL, IGRAPH_FAS_EXACT_IP_TI) == IGRAPH_INTERRUPTED);
igraph_set_error_handler(ehandler);
igraph_set_interruption_handler(NULL);
igraph_destroy(&graph);
igraph_vector_int_destroy(&res);
VERIFY_FINALLY_STACK();
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include <stdio.h>
#include "test_utilities.h"
void test_input(const char *filename) {
igraph_t graph;
FILE *ifile;
ifile = fopen(filename, "r");
if (! ifile) {
IGRAPH_FATALF("Cannot open '%s'.\n", filename);
}
printf("===== %s =====\n", filename);
IGRAPH_ASSERT(igraph_read_graph_gml(&graph, ifile) == IGRAPH_SUCCESS);
IGRAPH_ASSERT(igraph_write_graph_gml(&graph, stdout, IGRAPH_WRITE_GML_DEFAULT_SW, NULL, "igraph") == IGRAPH_SUCCESS);
igraph_destroy(&graph);
VERIFY_FINALLY_STACK();
printf("======================\n\n");
}
int main(void) {
/* Enable attribute handling */
igraph_set_attribute_table(&igraph_cattribute_table);
test_input("graph1.gml");
test_input("graph2.gml");
test_input("graph3.gml");
return 0;
}
@@ -0,0 +1,79 @@
===== graph1.gml =====
Creator "igraph"
Version 1
graph
[
directed 1
AttOne "x"
AttTwo 3.14
node
[
id 1
b "2"
c 5.6
nan ""
]
node
[
id 2
a 2
b "asd"
d -Inf
nan "foo"
]
node
[
id 5
b ""
nan ""
]
edge
[
source 5
target 1
weight -0.45
label "-0.45"
]
edge
[
source 2
target 5
label "Tom &amp; Jerry's &quot;friendship&quot;"
num1 Inf
]
]
======================
===== graph2.gml =====
Creator "igraph"
Version 1
graph
[
directed 1
node
[
id 0
Foo ""
]
node
[
id 1
Foo ""
]
node
[
id 2
Foo "bar &amp; baz"
]
]
======================
===== graph3.gml =====
Creator "igraph"
Version 1
graph
[
directed 0
]
======================
@@ -0,0 +1,44 @@
# comment lines are ignored
Version 1
graph [
directed 1
node [
id 1
a [ b 1 ]
b +2
c 5.6
graphics [ x 0 y 0 ]
]
node [
a 1
id 2
a 2
b "asd"
d -Inf
nan "foo"
]
edge [
source 5 target 1
weight -0.45
label -0.45
num1 NAN
]
node [
id 5
c [ str "bar" ]
]
edge [
source 2 target 5
label "Tom &amp; Jerry&apos;s &quot;friendship&quot;"
# The 'sou_rce' attribute will be ignored by the GML writer as it would conflict with
# 'source' after stripping the '_' character.
sou_rce 1.0
num1 +inF
]
AttOne 1
AttOne "x"
AttTwo 3.14
]
# second graph is ignored
graph [ node [ ] ]
@@ -0,0 +1,11 @@
# This graph contains nodes with no id fields,
# as well as invalid version and directedness.
# There is no newline at the end of this file.
Version 3
graph [
directed 2
node [ ] node [ ] node [ Foo "bar & baz" ]
composite [ a 1 ]
]
@@ -0,0 +1,4 @@
# Null graph, undirected
graph []
@@ -0,0 +1,149 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
void print_cliques_and_thresholds(igraph_vector_int_list_t* cliques, igraph_vector_t* thresholds) {
printf("Cliques:\n");
print_vector_int_list(cliques);
printf("Thresholds:\n");
print_vector(thresholds);
}
void print_cliques_and_mu(igraph_vector_int_list_t* cliques, igraph_vector_t* mu) {
printf("Cliques:\n");
print_vector_int_list(cliques);
printf("Mu:\n");
print_vector_format(mu, stdout, "%.5f");
}
void test_graphlets_candidate_basis_simple(void) {
igraph_t g;
igraph_vector_int_list_t cliques;
igraph_vector_t thresholds;
igraph_vector_t weights;
igraph_int_t eid;
igraph_full(&g, 5, IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
igraph_vector_int_list_init(&cliques, 0);
igraph_vector_init(&thresholds, 0);
igraph_vector_init(&weights, igraph_ecount(&g));
igraph_vector_fill(&weights, 1);
igraph_graphlets_candidate_basis(&g, &weights, &cliques, &thresholds);
print_cliques_and_thresholds(&cliques, &thresholds);
igraph_get_eid(&g, &eid, 0, 1, IGRAPH_UNDIRECTED, /* error = */ 0);
VECTOR(weights)[eid] = 2;
igraph_graphlets_candidate_basis(&g, &weights, &cliques, &thresholds);
print_cliques_and_thresholds(&cliques, &thresholds);
igraph_vector_destroy(&weights);
igraph_vector_int_list_destroy(&cliques);
igraph_vector_destroy(&thresholds);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
}
void test_graphlets_filtering(void) {
igraph_t g;
igraph_vector_int_list_t cliques;
igraph_vector_t thresholds;
igraph_vector_t weights_vec;
igraph_real_t weights[] = { 8, 8, 8, 5, 5, 5, 5, 5 };
igraph_small(&g, 5, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4, -1);
igraph_vector_int_list_init(&cliques, 0);
igraph_vector_init(&thresholds, 0);
weights_vec = igraph_vector_view(weights, sizeof(weights) / sizeof(weights[0]));
igraph_graphlets_candidate_basis(&g, &weights_vec, &cliques, &thresholds);
print_cliques_and_thresholds(&cliques, &thresholds);
igraph_vector_int_list_destroy(&cliques);
igraph_vector_destroy(&thresholds);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
}
void test_zachary_random_weights(void) {
igraph_t g;
igraph_vector_int_list_t cliques;
igraph_vector_t thresholds;
igraph_vector_t weights_vec;
igraph_real_t weights[] = {
1, 5, 1, 1, 2, 4, 2, 2, 1, 4, 1, 5, 4, 2, 2, 3, 1, 1, 3, 4, 5, 5, 5, 4,
2, 4, 3, 2, 1, 2, 3, 2, 4, 4, 2, 5, 4, 5, 4, 2, 2, 3, 1, 5, 2, 2, 2, 4,
3, 5, 2, 2, 2, 5, 1, 1, 4, 5, 2, 1, 5, 4, 4, 1, 3, 3, 5, 5, 4, 5, 4, 2,
2, 1, 2, 5, 5, 4
};
igraph_famous(&g, "zachary");
igraph_vector_int_list_init(&cliques, 0);
igraph_vector_init(&thresholds, 0);
weights_vec = igraph_vector_view(weights, sizeof(weights) / sizeof(weights[0]));
igraph_graphlets_candidate_basis(&g, &weights_vec, &cliques, &thresholds);
print_cliques_and_thresholds(&cliques, &thresholds);
igraph_vector_int_list_destroy(&cliques);
igraph_vector_destroy(&thresholds);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
}
void test_projection(void) {
igraph_t g;
igraph_vector_int_list_t cliques;
igraph_vector_t mu;
igraph_vector_t weights_vec;
igraph_real_t weights[] = { 2, 2, 3, 1, 1, 4, 4, 4 };
igraph_small(&g, 5, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 1, 2, 1, 3, 1, 4, 2, 3, 2, 4, 3, 4, -1);
igraph_vector_int_list_init(&cliques, 0);
igraph_vector_init(&mu, 0);
weights_vec = igraph_vector_view(weights, sizeof(weights) / sizeof(weights[0]));
igraph_graphlets(&g, &weights_vec, &cliques, &mu, 1000);
print_cliques_and_mu(&cliques, &mu);
igraph_vector_int_list_destroy(&cliques);
igraph_vector_destroy(&mu);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
}
int main(void) {
test_graphlets_candidate_basis_simple();
test_graphlets_filtering();
test_zachary_random_weights();
test_projection();
return 0;
}
@@ -0,0 +1,111 @@
Cliques:
{
0: ( 0 1 2 3 4 )
}
Thresholds:
( 1 )
Cliques:
{
0: ( 0 1 2 3 4 )
1: ( 0 1 )
}
Thresholds:
( 1 2 )
Cliques:
{
0: ( 0 1 2 )
1: ( 1 2 3 4 )
}
Thresholds:
( 8 5 )
Cliques:
{
0: ( 0 11 )
1: ( 9 33 )
2: ( 2 9 )
3: ( 14 32 33 )
4: ( 15 32 33 )
5: ( 5 6 16 )
6: ( 0 1 17 )
7: ( 0 3 12 )
8: ( 26 29 33 )
9: ( 20 32 33 )
10: ( 0 1 21 )
11: ( 22 32 33 )
12: ( 18 32 33 )
13: ( 23 27 33 )
14: ( 23 29 32 33 )
15: ( 23 25 )
16: ( 24 25 31 )
17: ( 24 27 )
18: ( 2 27 )
19: ( 28 31 33 )
20: ( 2 28 )
21: ( 0 4 6 )
22: ( 0 4 10 )
23: ( 31 32 33 )
24: ( 0 31 )
25: ( 0 5 6 )
26: ( 0 5 10 )
27: ( 19 33 )
28: ( 0 1 19 )
29: ( 13 33 )
30: ( 8 30 32 33 )
31: ( 1 30 )
32: ( 0 1 2 3 7 )
33: ( 0 1 2 3 13 )
34: ( 2 8 32 )
35: ( 0 2 8 )
36: ( 14 33 )
37: ( 15 33 )
38: ( 5 6 )
39: ( 0 17 )
40: ( 1 17 )
41: ( 3 12 )
42: ( 26 33 )
43: ( 26 29 )
44: ( 20 32 )
45: ( 0 21 )
46: ( 1 21 )
47: ( 22 33 )
48: ( 27 33 )
49: ( 23 29 33 )
50: ( 29 32 33 )
51: ( 23 29 )
52: ( 23 33 )
53: ( 24 25 )
54: ( 28 31 )
55: ( 4 6 )
56: ( 4 10 )
57: ( 31 33 )
58: ( 31 32 )
59: ( 0 6 )
60: ( 5 10 )
61: ( 0 19 )
62: ( 1 19 )
63: ( 8 30 33 )
64: ( 8 30 )
65: ( 8 33 )
66: ( 1 7 )
67: ( 0 2 7 )
68: ( 2 3 7 )
69: ( 2 7 )
70: ( 3 7 )
71: ( 1 13 )
72: ( 0 2 13 )
73: ( 2 3 13 )
74: ( 0 13 )
75: ( 0 2 )
76: ( 2 8 )
}
Thresholds:
( 4 2 2 2 3 2 1 1 2 1 1 1 2 2 1 5 3 1 3 4 2 1 1 4 3 2 1 2 1 2 1 4 1 1 1 2 4 5 5 4 5 4 5 5 5 2 5 4 4 2 2 4 5 4 5 5 4 5 5 4 4 2 5 2 3 5 3 2 2 4 4 4 2 2 5 5 3 )
Cliques:
{
0: ( 2 3 4 )
1: ( 0 1 2 )
2: ( 1 2 3 4 )
3: ( 1 2 )
}
Mu:
( 1.13842 0.92554 0.86148 0.00000 )
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="type" for="node" attr.name="type" attr.type="boolean">
<default>TRUE</default>
</key>
<key id="gender" for="node" attr.name="gender" attr.type="string">
<default>male</default>
</key>
<key id="age" for="node" attr.name="age" attr.type="int">
<default>20</default>
</key>
<key id="retired" for="node" attr.name="retired" attr.type="boolean">
<default>FALSE</default>
</key>
<graph id="G" edgedefault="directed">
<node id='p1'><data key='type'>FALSE</data><data key='age'>30</data></node>
<node id='o1'><data key='gender'>female</data></node>
<node id='o2'></node>
<edge id='e1' source='p1' target='o1'></edge>
<edge id='e2' source='p1' target='o2'></edge>
</graph>
</graphml>
@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<key id="organism" for="graph" attr.name="organism" attr.type="string"/>
<key id="pathway_number" for="graph" attr.name="pathway_number" attr.type="string"/>
<key id="title" for="graph" attr.name="title" attr.type="string"/>
<key id="type" for="node" attr.name="type" attr.type="string"/>
<key id="pathway_id" for="node" attr.name="pathway_id" attr.type="string"/>
<key id="name" for="node" attr.name="name" attr.type="string"/>
<key id="title" for="node" attr.name="title" attr.type="string"/>
<key id="uniprot" for="node" attr.name="uniprot" attr.type="string"/>
<key id="gene" for="node" attr.name="gene" attr.type="string"/>
<key id="GO" for="node" attr.name="GO" attr.type="string"/>
<key id="sim_BP_resnik" for="edge" attr.name="sim_BP_resnik" attr.type="double"/>
<key id="sim_BP_lin" for="edge" attr.name="sim_BP_lin" attr.type="double"/>
<key id="sim_BP_jiang" for="edge" attr.name="sim_BP_jiang" attr.type="double"/>
<key id="sim_BP_rel" for="edge" attr.name="sim_BP_rel" attr.type="double"/>
<key id="sim_CC_resnik" for="edge" attr.name="sim_CC_resnik" attr.type="double"/>
<key id="sim_CC_lin" for="edge" attr.name="sim_CC_lin" attr.type="double"/>
<key id="sim_CC_jiang" for="edge" attr.name="sim_CC_jiang" attr.type="double"/>
<key id="sim_CC_rel" for="edge" attr.name="sim_CC_rel" attr.type="double"/>
<key id="sim_MF_resnik" for="edge" attr.name="sim_MF_resnik" attr.type="double"/>
<key id="sim_MF_lin" for="edge" attr.name="sim_MF_lin" attr.type="double"/>
<key id="sim_MF_jiang" for="edge" attr.name="sim_MF_jiang" attr.type="double"/>
<key id="sim_MF_rel" for="edge" attr.name="sim_MF_rel" attr.type="double"/>
<graph id="G" edgedefault="directed">
<data key="organism">hsa</data>
<data key="pathway_number">05010</data>
<node id="n0">
<data key="type">compound</data>
<data key="pathway_id">1</data>
<data key="name">cpd:C00027</data>
<data key="title">C00027</data>
<data key="uniprot"></data>
<data key="gene"></data>
<data key="GO"></data>
</node>
<node id="n1">
<data key="type">compound</data>
<data key="pathway_id">2</data>
<data key="name">cpd:C00070</data>
<data key="title">C00070...</data>
<data key="uniprot"></data>
<data key="gene"></data>
<data key="GO"></data>
</node>
<node id="n2">
<data key="type">compound</data>
<data key="pathway_id">2</data>
<data key="name">cpd:C14818</data>
<data key="title">C00070...</data>
<data key="uniprot"></data>
<data key="gene"></data>
<data key="GO"></data>
</node>
<node id="n3">
<data key="type">gene</data>
<data key="pathway_id">4</data>
<data key="name">hsa:51107</data>
<data key="title">APH1A</data>
<data key="uniprot">Q96BI3</data>
<data key="gene">APH1A</data>
<data key="GO">GO:0005515,GO:0016021,GO:0016485,GO:0043085</data>
</node>
<node id="n4">
<data key="type">gene</data>
<data key="pathway_id">6</data>
<data key="name">hsa:4311</data>
<data key="title">MME</data>
<data key="uniprot">P08473</data>
<data key="gene">MME</data>
<data key="GO">GO:0004245,GO:0016021,GO:0016787,GO:0008237,GO:0007267,GO:0006508,GO:0005887,GO:0005886,GO:0016020</data>
</node>
<node id="n5">
<data key="type">gene</data>
<data key="pathway_id">7</data>
<data key="name">hsa:2932</data>
<data key="title">GSK3B</data>
<data key="uniprot">P49841</data>
<data key="gene">GSK3B</data>
<data key="GO">GO:0016301,GO:0016740,GO:0005977,GO:0004696,GO:0005524,GO:0004674,GO:0006468,GO:0004672</data>
</node>
<node id="n6">
<data key="type">gene</data>
<data key="pathway_id">8</data>
<data key="name">hsa:4137</data>
<data key="title">MAPT</data>
<data key="uniprot"></data>
<data key="gene"></data>
<data key="GO"></data>
</node>
<node id="n7">
<data key="type">gene</data>
<data key="pathway_id">9</data>
<data key="name">hsa:836</data>
<data key="title">CASP3</data>
<data key="uniprot">P42574</data>
<data key="gene">CASP3</data>
<data key="GO">GO:0016787,GO:0008233,GO:0006917,GO:0030693,GO:0008234,GO:0006915,GO:0006508</data>
</node>
<node id="n8">
<data key="type">gene</data>
<data key="pathway_id">11</data>
<data key="name">hsa:840</data>
<data key="title">CASP7</data>
<data key="uniprot">P55210</data>
<data key="gene">CASP7</data>
<data key="GO">GO:0008233,GO:0016787,GO:0008632,GO:0008234,GO:0006915,GO:0005737,GO:0006508</data>
</node>
<node id="n9">
<data key="type">gene</data>
<data key="pathway_id">12</data>
<data key="name">hsa:55851</data>
<data key="title">PSENEN</data>
<data key="uniprot">Q9NZ42</data>
<data key="gene">PEN2</data>
<data key="GO"></data>
</node>
<node id="n10">
<data key="type">gene</data>
<data key="pathway_id">13</data>
<data key="name">hsa:6622</data>
<data key="title">SNCA</data>
<data key="uniprot">P37840</data>
<data key="gene">SNCA</data>
<data key="GO">GO:0005737,GO:0007417,GO:0006916</data>
</node>
<node id="n11">
<data key="type">gene</data>
<data key="pathway_id">14</data>
<data key="name">hsa:5663</data>
<data key="title">PSEN1...</data>
<data key="uniprot">P49768</data>
<data key="gene"></data>
<data key="GO">GO:0016021,GO:0007059,GO:0007001,GO:0006916,GO:0000776,GO:0000775,GO:0005639,GO:0005624,GO:0005783,GO:0007242</data>
</node>
<node id="n12">
<data key="type">gene</data>
<data key="pathway_id">14</data>
<data key="name">hsa:5664</data>
<data key="title">PSEN1...</data>
<data key="uniprot">P49810</data>
<data key="gene">PSEN2</data>
<data key="GO">GO:0016021,GO:0008632,GO:0007059,GO:0007001,GO:0000776,GO:0005639,GO:0005783,GO:0007242</data>
</node>
<node id="n13">
<data key="type">gene</data>
<data key="pathway_id">15</data>
<data key="name">hsa:836</data>
<data key="title">CASP3</data>
<data key="uniprot">P42574</data>
<data key="gene">CASP3</data>
<data key="GO">GO:0016787,GO:0008233,GO:0006917,GO:0030693,GO:0008234,GO:0006915,GO:0006508</data>
</node>
<node id="n14">
<data key="type">gene</data>
<data key="pathway_id">16</data>
<data key="name">hsa:23385</data>
<data key="title">NCSTN</data>
<data key="uniprot">Q92542</data>
<data key="gene">NCSTN</data>
<data key="GO">GO:0016021,GO:0016485,GO:0006508</data>
</node>
<node id="n15">
<data key="type">gene</data>
<data key="pathway_id">17</data>
<data key="name">hsa:2</data>
<data key="title">A2M</data>
<data key="uniprot">P01023</data>
<data key="gene">A2M</data>
<data key="GO">GO:0017114,GO:0004866,GO:0051260,GO:0019899,GO:0008320,GO:0006886,GO:0004867</data>
</node>
<node id="n16">
<data key="type">gene</data>
<data key="pathway_id">18</data>
<data key="name">hsa:3416</data>
<data key="title">IDE</data>
<data key="uniprot">P14735</data>
<data key="gene">IDE</data>
<data key="GO">GO:0004231,GO:0016787,GO:0008237,GO:0007548,GO:0007267,GO:0007165,GO:0006508,GO:0005777,GO:0005625,GO:0005615,GO:0004871,GO:0003824,GO:0004222</data>
</node>
<node id="n17">
<data key="type">gene</data>
<data key="pathway_id">19</data>
<data key="name">hsa:8883</data>
<data key="title">APPBP1</data>
<data key="uniprot">Q13564</data>
<data key="gene">APPBP1</data>
<data key="GO">GO:0007165,GO:0005737,GO:0003824</data>
</node>
<node id="n18">
<data key="type">gene</data>
<data key="pathway_id">20</data>
<data key="name">hsa:23621</data>
<data key="title">BACE1...</data>
<data key="uniprot">P56817</data>
<data key="gene">BACE1</data>
<data key="GO">GO:0004190,GO:0008233,GO:0009049,GO:0016021,GO:0016787,GO:0050435,GO:0005768,GO:0006508,GO:0005794,GO:0006509,GO:0008798,GO:0005887,GO:0004194</data>
</node>
<node id="n19">
<data key="type">gene</data>
<data key="pathway_id">20</data>
<data key="name">hsa:25825</data>
<data key="title">BACE1...</data>
<data key="uniprot">Q9Y5Z0</data>
<data key="gene"></data>
<data key="GO">GO:0004190,GO:0009049,GO:0016021,GO:0016787,GO:0009306,GO:0006464,GO:0005624,GO:0006508,GO:0004194</data>
</node>
<node id="n20">
<data key="type">gene</data>
<data key="pathway_id">22</data>
<data key="name">hsa:351</data>
<data key="title">APP, AD1</data>
<data key="uniprot">P05067</data>
<data key="gene">APP</data>
<data key="GO">GO:0008201,GO:0007155,GO:0006915,GO:0005905,GO:0006897,GO:0016021,GO:0005515,GO:0005887,GO:0005576,GO:0004867</data>
</node>
<node id="n21">
<data key="type">gene</data>
<data key="pathway_id">23</data>
<data key="name">hsa:2597</data>
<data key="title">GAPDH, GAPD</data>
<data key="uniprot">P04406</data>
<data key="gene"></data>
<data key="GO"></data>
</node>
<node id="n22">
<data key="type">gene</data>
<data key="pathway_id">24</data>
<data key="name">hsa:348</data>
<data key="title">APOE, AD2</data>
<data key="uniprot">P02649</data>
<data key="gene">APOE</data>
<data key="GO">GO:0001540,GO:0008015,GO:0007271,GO:0005737,GO:0005319,GO:0008201,GO:0006869,GO:0008289</data>
</node>
<node id="n23">
<data key="type">gene</data>
<data key="pathway_id">25</data>
<data key="name">hsa:322</data>
<data key="title">APBB1, RIR</data>
<data key="uniprot">O00213</data>
<data key="gene">APBB1</data>
<data key="GO">GO:0007165,GO:0001540,GO:0008134,GO:0045449,GO:0050821,GO:0005634,GO:0030308,GO:0045749,GO:0035035,GO:0007050,GO:0030048,GO:0045202,GO:0030027,GO:0030426,GO:0007409,GO:0050760</data>
</node>
<node id="n24">
<data key="type">gene</data>
<data key="pathway_id">26</data>
<data key="name">hsa:4023</data>
<data key="title">LPL</data>
<data key="uniprot">P06858</data>
<data key="gene">LPL</data>
<data key="GO">GO:0005319,GO:0004465,GO:0016787,GO:0016042,GO:0008201,GO:0008015,GO:0006631,GO:0005576,GO:0006629,GO:0003824</data>
</node>
<node id="n25">
<data key="type">gene</data>
<data key="pathway_id">27</data>
<data key="name">hsa:4035</data>
<data key="title">LRP1, APR, A2MR</data>
<data key="uniprot">Q07954</data>
<data key="gene">LRP1</data>
<data key="GO">GO:0016021,GO:0004872,GO:0016020,GO:0008283,GO:0008034,GO:0006629,GO:0005887,GO:0005624,GO:0005509,GO:0005319,GO:0006897,GO:0005905</data>
</node>
<edge source="n20" target="n23">
<data key="sim_BP_resnik">4.95265</data>
<data key="sim_BP_lin">0.693152</data>
<data key="sim_BP_jiang">0.185704</data>
<data key="sim_BP_rel">0.670769</data>
<data key="sim_CC_resnik">0.145403</data>
<data key="sim_CC_lin">0.05698</data>
<data key="sim_CC_jiang">0.172033</data>
<data key="sim_CC_rel">0.00546283</data>
<data key="sim_MF_resnik">2.93737</data>
<data key="sim_MF_lin">0.556617</data>
<data key="sim_MF_jiang">0.176068</data>
<data key="sim_MF_rel">0.483953</data>
</edge>
<edge source="n17" target="n20">
<data key="sim_BP_resnik">0.50493</data>
<data key="sim_BP_lin">0.112413</data>
<data key="sim_BP_jiang">0.111437</data>
<data key="sim_BP_rel">0.033196</data>
<data key="sim_CC_resnik">0.145403</data>
<data key="sim_CC_lin">0.0605613</data>
<data key="sim_CC_jiang">0.181454</data>
<data key="sim_CC_rel">0.00580618</data>
<data key="sim_MF_resnik">-0</data>
<data key="sim_MF_lin">-0</data>
<data key="sim_MF_jiang">0.171988</data>
<data key="sim_MF_rel">-0</data>
</edge>
<edge source="n20" target="n25">
<data key="sim_BP_resnik">7.8977</data>
<data key="sim_BP_lin">1</data>
<data key="sim_BP_jiang">1</data>
<data key="sim_BP_rel">0.995807</data>
<data key="sim_CC_resnik">9.64739</data>
<data key="sim_CC_lin">1</data>
<data key="sim_CC_jiang">1</data>
<data key="sim_CC_rel">0.998753</data>
<data key="sim_MF_resnik">2.93737</data>
<data key="sim_MF_lin">0.400174</data>
<data key="sim_MF_jiang">0.136512</data>
<data key="sim_MF_rel">0.347932</data>
</edge>
<edge source="n15" target="n25">
<data key="sim_BP_resnik">3.5307</data>
<data key="sim_BP_lin">0.498171</data>
<data key="sim_BP_jiang">0.123255</data>
<data key="sim_BP_rel">0.455066</data>
<data key="sim_MF_resnik">4.0529</data>
<data key="sim_MF_lin">0.366988</data>
<data key="sim_MF_jiang">0.0822633</data>
<data key="sim_MF_rel">0.344877</data>
</edge>
<edge source="n24" target="n25">
<data key="sim_BP_resnik">5.41325</data>
<data key="sim_BP_lin">1</data>
<data key="sim_BP_jiang">1</data>
<data key="sim_BP_rel">0.976533</data>
<data key="sim_CC_resnik">-0</data>
<data key="sim_CC_lin">-0</data>
<data key="sim_CC_jiang">0.151863</data>
<data key="sim_CC_rel">-0</data>
<data key="sim_MF_resnik">9.56439</data>
<data key="sim_MF_lin">1</data>
<data key="sim_MF_jiang">1</data>
<data key="sim_MF_rel">0.998679</data>
</edge>
<edge source="n20" target="n22">
<data key="sim_BP_resnik">3.20433</data>
<data key="sim_BP_lin">0.383125</data>
<data key="sim_BP_jiang">0.0883496</data>
<data key="sim_BP_rel">0.341558</data>
<data key="sim_CC_resnik">0.145403</data>
<data key="sim_CC_lin">0.0605613</data>
<data key="sim_CC_jiang">0.181454</data>
<data key="sim_CC_rel">0.00580618</data>
<data key="sim_MF_resnik">10.0077</data>
<data key="sim_MF_lin">1</data>
<data key="sim_MF_jiang">1</data>
<data key="sim_MF_rel">0.999029</data>
</edge>
<edge source="n20" target="n21">
</edge>
<edge source="n18" target="n20">
<data key="sim_BP_resnik">0.50493</data>
<data key="sim_BP_lin">0.0888891</data>
<data key="sim_BP_jiang">0.0880977</data>
<data key="sim_BP_rel">0.0262494</data>
<data key="sim_CC_resnik">5.53428</data>
<data key="sim_CC_lin">1</data>
<data key="sim_CC_jiang">1</data>
<data key="sim_CC_rel">0.978422</data>
<data key="sim_MF_resnik">-0</data>
<data key="sim_MF_lin">-0</data>
<data key="sim_MF_jiang">0.137908</data>
<data key="sim_MF_rel">-0</data>
</edge>
<edge source="n19" target="n20">
<data key="sim_BP_resnik">3.17114</data>
<data key="sim_BP_lin">0.346041</data>
<data key="sim_BP_jiang">0.0972198</data>
<data key="sim_BP_rel">0.307624</data>
<data key="sim_CC_resnik">2.60224</data>
<data key="sim_CC_lin">1</data>
<data key="sim_CC_jiang">1</data>
<data key="sim_CC_rel">0.835317</data>
<data key="sim_MF_resnik">-0</data>
<data key="sim_MF_lin">-0</data>
<data key="sim_MF_jiang">0.137908</data>
<data key="sim_MF_rel">-0</data>
</edge>
<edge source="n5" target="n6">
</edge>
</graph>
</graphml>
@@ -0,0 +1,10 @@
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<graphml>
<graph id='Barabasi-Albert-73751112' edgedefault='undirected'>
<node id='0'/>
<node id='1'/>
<node id='2'/>
<edge id='0' source='1' target='0' />
<edge id='1' source='2' target='1' />
</graph>
</graphml>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:graphml xmlns:ns2="http://www.w3.org/1999/xlink"
xmlns:ns3="http://graphml.graphdrawing.org/xmlns">
<ns3:graph id="Barabasi-Albert-73751112" edgedefault="undirected">
<ns3:node id="0"/>
<ns3:node id="1"/>
<ns3:node id="2"/>
<ns3:edge id="0" source="1" target="0" />
<ns3:edge id="1" source="2" target="1" />
</ns3:graph>
</ns3:graphml>
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<!-- Created by igraph -->
<!-- Testing the effect of whitespace on numeric, Boolean and string attribute values -->
<key id="v_weight" for="node" attr.name="weight" attr.type="float"/>
<key id="v_name" for="node" attr.name="name" attr.type="string"/>
<key id="v_type" for="node" attr.name="type" attr.type="boolean"/>
<graph id="G" edgedefault="undirected">
<!-- No whitespace -->
<node id="n0">
<data key="v_weight">1</data>
<data key="v_name">spam</data>
<data key="v_type">true</data>
</node>
<!-- Whitespace only -->
<node id="n1">
<data key="v_weight"> </data>
<data key="v_name"> </data>
<data key="v_type"> </data>
</node>
<!-- Leading whitespace -->
<node id="n2">
<data key="v_weight"> 3</data>
<data key="v_name"> ham</data>
<data key="v_type"> true</data>
</node>
<!-- Trailing whitespace -->
<node id="n3">
<data key="v_weight">4 </data>
<data key="v_name">bacon </data>
<data key="v_type">true </data>
</node>
<!-- Both leading and trailing whitespace -->
<node id="n4">
<data key="v_weight"> 5 </data>
<data key="v_name"> eggs </data>
<data key="v_type"> true </data>
</node>
<edge source="n0" target="n1">
</edge>
<edge source="n1" target="n2">
</edge>
<edge source="n1" target="n3">
</edge>
<edge source="n2" target="n3">
</edge>
</graph>
</graphml>
@@ -0,0 +1,177 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--Created by yFiles for HTML 2.0.1.4-->
<graphml xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml.html/2.0/ygraphml.xsd " xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:demostyle="http://www.yworks.com/yFilesHTML/demos/FlatDemoStyle/1.0" xmlns:bpmn="http://www.yworks.com/xml/yfiles-for-html/bpmn/2.0" xmlns:demotablestyle="http://www.yworks.com/yFilesHTML/demos/FlatDemoTableStyle/1.0" xmlns:compat="http://www.yworks.com/xml/yfiles-compat-arrows/1.0" xmlns:VuejsNodeStyle="http://www.yworks.com/demos/yfiles-vuejs-node-style/1.0" xmlns:y="http://www.yworks.com/xml/yfiles-common/3.0" xmlns:x="http://www.yworks.com/xml/yfiles-common/markup/3.0" xmlns:yjs="http://www.yworks.com/xml/yfiles-for-html/2.0/xaml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<key id="d0" for="node" attr.type="boolean" attr.name="Expanded" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/folding/Expanded">
<default>true</default>
</key>
<key id="d1" for="node" attr.name="NodeLabels" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/NodeLabels"/>
<key id="d2" for="node" attr.name="NodeGeometry" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/NodeGeometry"/>
<key id="d3" for="all" attr.name="UserTags" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/UserTags"/>
<key id="d4" for="node" attr.name="NodeStyle" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/NodeStyle"/>
<key id="d5" for="node" attr.name="NodeViewState" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/folding/1.1/NodeViewState"/>
<key id="d6" for="edge" attr.name="EdgeLabels" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/EdgeLabels"/>
<key id="d7" for="edge" attr.name="EdgeGeometry" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/EdgeGeometry"/>
<key id="d8" for="edge" attr.name="EdgeStyle" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/EdgeStyle"/>
<key id="d9" for="edge" attr.name="EdgeViewState" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/folding/1.1/EdgeViewState"/>
<key id="d10" for="port" attr.name="PortLocationParameter" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/PortLocationParameter">
<default>
<x:Static Member="y:FreeNodePortLocationModel.NodeCenterAnchored"/>
</default>
</key>
<key id="d11" for="port" attr.name="PortStyle" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/PortStyle">
<default>
<x:Static Member="y:VoidPortStyle.Instance"/>
</default>
</key>
<key id="d12" for="port" attr.name="PortViewState" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/folding/1.1/PortViewState"/>
<key id="d13" attr.name="SharedData" y:attr.uri="http://www.yworks.com/xml/yfiles-common/2.0/SharedData"/>
<data key="d13">
<y:SharedData>
<yjs:Color x:Key="1" value="#FF316C94"/>
<yjs:Color x:Key="2" value="#FF006A70"/>
<yjs:Color x:Key="3" value="#FFC9E2E2"/>
<yjs:Arrow x:Key="4" type="NONE"/>
</y:SharedData>
</data>
<graph id="G" edgedefault="directed">
<node id="n0">
<data key="d1">
<x:List>
<y:Label>
<y:Label.Text>A</y:Label.Text>
<y:Label.LayoutParameter>
<y:RatioAnchoredLabelModelParameter LayoutOffset="45.2981354349738,20.5"/>
</y:Label.LayoutParameter>
<y:Label.Style>
<yjs:DefaultLabelStyle horizontalTextAlignment="CENTER" autoFlip="false" textFill="#FFFFFFFF" textSize="16">
<yjs:DefaultLabelStyle.font>
<yjs:Font fontSize="16" fontFamily="Calibri" fontWeight="BOLD"/>
</yjs:DefaultLabelStyle.font>
</yjs:DefaultLabelStyle>
</y:Label.Style>
</y:Label>
</x:List>
</data>
<data key="d2">
<y:RectD X="1917.9576310558555" Y="2912.1062122893554" Width="214.8931458699476" Height="57"/>
</data>
<data key="d4">
<demostyle:FlowchartNodeStyle type="terminator">
<demostyle:FlowchartNodeStyle.stroke>
<yjs:Stroke fill="#FF000000" miterLimit="1.45" thickness="2"/>
</demostyle:FlowchartNodeStyle.stroke>
<demostyle:FlowchartNodeStyle.fill>
<yjs:LinearGradient spreadMethod="PAD" startPoint="0,0" endPoint="1,1">
<yjs:GradientStop color="{y:GraphMLReference 1}" offset="0"/>
<yjs:GradientStop color="{y:GraphMLReference 1}" offset="1"/>
</yjs:LinearGradient>
</demostyle:FlowchartNodeStyle.fill>
</demostyle:FlowchartNodeStyle>
</data>
<port name="p0"/>
</node>
<node id="n1">
<data key="d1">
<x:List>
<y:Label>
<y:Label.Text>B</y:Label.Text>
<y:Label.LayoutParameter>
<y:RatioAnchoredLabelModelParameter LayoutOffset="68.91532293497403,12.5"/>
</y:Label.LayoutParameter>
<y:Label.Style>
<yjs:DefaultLabelStyle horizontalTextAlignment="CENTER" autoFlip="false" textFill="#FFFFFFFF" textSize="16">
<yjs:DefaultLabelStyle.font>
<yjs:Font fontSize="16" fontFamily="Calibri" fontWeight="BOLD"/>
</yjs:DefaultLabelStyle.font>
</yjs:DefaultLabelStyle>
</y:Label.Style>
</y:Label>
</x:List>
</data>
<data key="d2">
<y:RectD X="1917.9576310558555" Y="2809.9061759957385" Width="214.89314586994806" Height="57"/>
</data>
<data key="d4">
<demostyle:FlowchartNodeStyle type="document">
<demostyle:FlowchartNodeStyle.stroke>
<yjs:Stroke fill="#FF000000" miterLimit="1.45" thickness="2"/>
</demostyle:FlowchartNodeStyle.stroke>
<demostyle:FlowchartNodeStyle.fill>
<yjs:LinearGradient spreadMethod="PAD" startPoint="0,0" endPoint="1,1">
<yjs:GradientStop color="{y:GraphMLReference 2}" offset="0"/>
<yjs:GradientStop color="{y:GraphMLReference 2}" offset="1"/>
</yjs:LinearGradient>
</demostyle:FlowchartNodeStyle.fill>
</demostyle:FlowchartNodeStyle>
</data>
<port name="p0"/>
<port name="p1"/>
<port name="p2"/>
</node>
<node id="n2">
<data key="d1">
<x:List>
<y:Label>
<y:Label.Text>X</y:Label.Text>
<y:Label.LayoutParameter>
<y:RatioAnchoredLabelModelParameter LayoutOffset="62.41922918497403,20.5"/>
</y:Label.LayoutParameter>
<y:Label.Style>
<yjs:DefaultLabelStyle horizontalTextAlignment="CENTER" autoFlip="false" textFill="#FF000000" textSize="16">
<yjs:DefaultLabelStyle.font>
<yjs:Font fontSize="16" fontFamily="Calibri" fontWeight="BOLD"/>
</yjs:DefaultLabelStyle.font>
</yjs:DefaultLabelStyle>
</y:Label.Style>
</y:Label>
</x:List>
</data>
<data key="d2">
<y:RectD X="1917.9576310558555" Y="2702.7061397021216" Width="214.89314586994806" Height="57"/>
</data>
<data key="d4">
<demostyle:FlowchartNodeStyle type="start1">
<demostyle:FlowchartNodeStyle.stroke>
<yjs:Stroke fill="#FF000000" miterLimit="1.45" thickness="2"/>
</demostyle:FlowchartNodeStyle.stroke>
<demostyle:FlowchartNodeStyle.fill>
<yjs:LinearGradient spreadMethod="PAD" startPoint="0,0" endPoint="1,1">
<yjs:GradientStop color="{y:GraphMLReference 3}" offset="0"/>
<yjs:GradientStop color="{y:GraphMLReference 3}" offset="1"/>
</yjs:LinearGradient>
</demostyle:FlowchartNodeStyle.fill>
</demostyle:FlowchartNodeStyle>
</data>
<port name="p0"/>
</node>
<edge id="e0" source="n1" target="n0" sourceport="p0" targetport="p0">
<data key="d7">
<x:List>
<y:Bend Location="2025.4042039908295,2898.850638702741"/>
</x:List>
</data>
<data key="d8">
<yjs:PolylineEdgeStyle sourceArrow="{y:GraphMLReference 4}">
<yjs:PolylineEdgeStyle.stroke>
<yjs:Stroke fill="#FF000000" miterLimit="1.45"/>
</yjs:PolylineEdgeStyle.stroke>
<yjs:PolylineEdgeStyle.targetArrow>
<yjs:Arrow stroke="#FF000000" fill="#FF000000"/>
</yjs:PolylineEdgeStyle.targetArrow>
</yjs:PolylineEdgeStyle>
</data>
</edge>
<edge id="e1" source="n2" target="n1" sourceport="p0" targetport="p2">
<data key="d8">
<yjs:PolylineEdgeStyle sourceArrow="{y:GraphMLReference 4}">
<yjs:PolylineEdgeStyle.stroke>
<yjs:Stroke fill="#FF000000" miterLimit="1.45"/>
</yjs:PolylineEdgeStyle.stroke>
<yjs:PolylineEdgeStyle.targetArrow>
<yjs:Arrow stroke="#FF000000" fill="#FF000000"/>
</yjs:PolylineEdgeStyle.targetArrow>
</yjs:PolylineEdgeStyle>
</data>
</edge>
</graph>
</graphml>
@@ -0,0 +1,138 @@
/*
igraph library.
Copyright (C) 2020-2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t graph;
igraph_vector_t res;
igraph_vector_t weights;
igraph_vector_init(&res, 0);
/* Path graph */
igraph_ring(&graph, 7, IGRAPH_DIRECTED, 0, /* circular */ 0);
printf("Unweighted undirected:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
printf("Unweighted directed:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_OUT, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
printf("Unweighted undirected, cutoff=0:\n");
igraph_harmonic_centrality_cutoff(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1, 0);
print_vector(&res);
printf("Unweighted undirected, cutoff=1:\n");
igraph_harmonic_centrality_cutoff(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1, 1);
print_vector(&res);
igraph_vector_init(&weights, igraph_ecount(&graph));
igraph_vector_fill(&weights, 1.0);
printf("Unit-weighted undirected:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
printf("Unit-weighted directed:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_OUT, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
printf("Unit-weighted undirected, cutoff=0:\n");
igraph_harmonic_centrality_cutoff(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1, 0);
print_vector(&res);
printf("Unit-weighted undirected, cutoff=1:\n");
igraph_harmonic_centrality_cutoff(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1, 1);
print_vector(&res);
igraph_vector_destroy(&weights);
igraph_vector_init_range(&weights, 1, igraph_ecount(&graph) + 1);
printf("Weighted undirected:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
printf("Weighted directed:\n");
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_OUT, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
igraph_vector_destroy(&weights);
igraph_destroy(&graph);
/* Graphs with no edges */
igraph_vector_init(&weights, 0);
/* Null graph */
printf("Null graph:\n");
igraph_empty(&graph, 0, IGRAPH_UNDIRECTED);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
igraph_destroy(&graph);
/* Singleton graph */
printf("Singleton graph:\n");
igraph_empty(&graph, 1, IGRAPH_UNDIRECTED);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
igraph_destroy(&graph);
/* Empty graph with two vertices */
printf("Empty graph with two vertices:\n");
igraph_empty(&graph, 2, IGRAPH_UNDIRECTED);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
igraph_destroy(&graph);
igraph_vector_destroy(&weights);
/* Graph with multiple connected components and isolated vertices */
printf("Multiple components, unweighted:\n");
igraph_small(&graph, 20, IGRAPH_UNDIRECTED,
1, 2, 2, 3, 1, 3, 4, 5, 5, 6, 6, 7, 5, 8, 8, 9, 6, 10, 10, 11, 7, 11,
9, 13, 9, 14, 9, 15, 9, 16, 13, 14, 13, 15, 13, 16, 14, 15, 14, 16,
15, 16, 17, 18, 4, 19, 4, 20,
-1);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ NULL, /* normalized= */ 1);
print_vector(&res);
printf("Multiple components, constant weight vector:\n");
igraph_vector_init(&weights, igraph_ecount(&graph));
igraph_vector_fill(&weights, 1.0 / 7);
igraph_harmonic_centrality(&graph, &res, igraph_vss_all(), IGRAPH_ALL, /* weights= */ &weights, /* normalized= */ 1);
print_vector(&res);
igraph_vector_destroy(&weights);
igraph_destroy(&graph);
igraph_vector_destroy(&res);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,33 @@
Unweighted undirected:
( 0.408333 0.547222 0.597222 0.611111 0.597222 0.547222 0.408333 )
Unweighted directed:
( 0.408333 0.380556 0.347222 0.305556 0.25 0.166667 0 )
Unweighted undirected, cutoff=0:
( 0 0 0 0 0 0 0 )
Unweighted undirected, cutoff=1:
( 0.166667 0.333333 0.333333 0.333333 0.333333 0.333333 0.166667 )
Unit-weighted undirected:
( 0.408333 0.547222 0.597222 0.611111 0.597222 0.547222 0.408333 )
Unit-weighted directed:
( 0.408333 0.380556 0.347222 0.305556 0.25 0.166667 0 )
Unit-weighted undirected, cutoff=0:
( 0 0 0 0 0 0 0 )
Unit-weighted undirected, cutoff=1:
( 0.166667 0.333333 0.333333 0.333333 0.333333 0.333333 0.166667 )
Weighted undirected:
( 0.285714 0.32209 0.241402 0.187963 0.149146 0.116534 0.0795695 )
Weighted directed:
( 0.285714 0.155423 0.102513 0.0712963 0.0484848 0.0277778 0 )
Null graph:
( )
( )
Singleton graph:
( 0 )
( 0 )
Empty graph with two vertices:
( 0 0 )
( 0 0 )
Multiple components, unweighted:
( 0 0.1 0.1 0.1 0.3125 0.358333 0.325 0.260833 0.329167 0.368333 0.260833 0.23 0 0.315 0.315 0.315 0.315 0.05 0.05 0.220833 0.220833 )
Multiple components, constant weight vector:
( 0 0.7 0.7 0.7 2.1875 2.50833 2.275 1.82583 2.30417 2.57833 1.82583 1.61 0 2.205 2.205 2.205 2.205 0.35 0.35 1.54583 1.54583 )
+145
View File
@@ -0,0 +1,145 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_heap_t h_max;
igraph_heap_min_t h_min;
igraph_int_t i;
igraph_real_t list[] = {-2, -9.999, 0, 6, 235, -2, -1000, -1, 4, 2000, 6, 0.5, 1, -9, 10};
const igraph_int_t l_size = sizeof(list) / sizeof(list[0]);
/* max heap init & destroy*/
printf("Create empty max heap & destroy\n");
igraph_heap_init(&h_max, 0);
IGRAPH_ASSERT(igraph_heap_empty(&h_max));
igraph_heap_destroy(&h_max);
printf("Create empty max heap but allocate size for some elements\n");
igraph_heap_init(&h_max, 10);
IGRAPH_ASSERT(igraph_heap_empty(&h_max));
igraph_heap_destroy(&h_max);
/* min heap init & destroy*/
printf("Create empty min heap & destroy\n");
igraph_heap_min_init(&h_min, 0);
IGRAPH_ASSERT(igraph_heap_min_empty(&h_min));
igraph_heap_min_destroy(&h_min);
printf("Create empty min heap but allocate size for some elements\n");
igraph_heap_min_init(&h_min, 10);
IGRAPH_ASSERT(igraph_heap_min_empty(&h_min));
igraph_heap_min_destroy(&h_min);
/* max heap_reserve, heap_size and heap_empty*/
printf("Test max heap_reserve, heap_size and heap_empty\n");
igraph_heap_init(&h_max, 5);
IGRAPH_ASSERT(igraph_heap_empty(&h_max));
IGRAPH_ASSERT(igraph_heap_size(&h_max) == 0);
igraph_heap_reserve(&h_max, 10);
IGRAPH_ASSERT(igraph_heap_empty(&h_max));
IGRAPH_ASSERT(igraph_heap_size(&h_max) == 0);
for (i=0; i < 15; i++){
igraph_heap_push(&h_max,i);
}
IGRAPH_ASSERT(igraph_heap_size(&h_max) == 15);
IGRAPH_ASSERT(!igraph_heap_empty(&h_max));
igraph_heap_reserve(&h_max, 5);
IGRAPH_ASSERT(igraph_heap_size(&h_max) == 15);
IGRAPH_ASSERT(!igraph_heap_empty(&h_max));
igraph_heap_destroy(&h_max);
/* min heap reserve, heap_size and heap_empty*/
printf("Test min heap_reserve, heap_size and heap_empty\n");
igraph_heap_min_init(&h_min, 5);
IGRAPH_ASSERT(igraph_heap_min_empty(&h_min));
IGRAPH_ASSERT(igraph_heap_min_size(&h_min) == 0);
igraph_heap_min_reserve(&h_min, 10);
IGRAPH_ASSERT(igraph_heap_min_empty(&h_min));
IGRAPH_ASSERT(igraph_heap_min_size(&h_min) == 0);
for (i=0; i < 15; i++){
igraph_heap_min_push(&h_min, i);
}
IGRAPH_ASSERT(igraph_heap_min_size(&h_min) == 15);
IGRAPH_ASSERT(!igraph_heap_min_empty(&h_min));
igraph_heap_min_reserve(&h_min, 5);
IGRAPH_ASSERT(igraph_heap_min_size(&h_min) == 15);
IGRAPH_ASSERT(!igraph_heap_min_empty(&h_min));
igraph_heap_min_destroy(&h_min);
/* max heap init_array and delete_top */
printf("Test max heap_init array and delete_top\n");
igraph_heap_init_array(&h_max,list,l_size);
while (igraph_heap_size(&h_max) > 0){
printf("%g ", igraph_heap_delete_top(&h_max));
}
printf("\n");
igraph_heap_destroy(&h_max);
/* min heap init_array and delete_top */
printf("Test min heap init_array and delete_top\n");
igraph_heap_min_init_array(&h_min, list, l_size);
while (igraph_heap_min_size(&h_min) > 0) {
printf("%g ", igraph_heap_min_delete_top(&h_min));
}
printf("\n");
igraph_heap_min_destroy(&h_min);
/* max heap top and push */
printf("Test max heap top and push\n");
igraph_heap_init(&h_max, 0);
for (i=0; i < l_size; i++){
igraph_heap_push(&h_max, list[i]);
printf("%g ", igraph_heap_top(&h_max));
}
printf("\n");
while (igraph_heap_size(&h_max)>0){
printf("%g ", igraph_heap_delete_top(&h_max));
}
printf("\n");
/* min heap top and push */
printf("Test min heap top and push\n");
igraph_heap_min_init(&h_min, 0);
for (i=0; i < l_size; i++){
igraph_heap_min_push(&h_min, list[i]);
printf("%g ", igraph_heap_min_top(&h_min));
}
printf("\n");
while (igraph_heap_min_size(&h_min) > 0){
printf("%g ", igraph_heap_min_delete_top(&h_min));
}
printf("\n");
igraph_heap_destroy(&h_max);
igraph_heap_min_destroy(&h_min);
/* Test initializing empty heap from array. */
igraph_heap_init_array(&h_max, list, 0);
IGRAPH_ASSERT(igraph_heap_empty(&h_max));
igraph_heap_push(&h_max, 3.0);
IGRAPH_ASSERT(! igraph_heap_empty(&h_max));
IGRAPH_ASSERT(igraph_heap_top(&h_max) == 3.0);
igraph_heap_destroy(&h_max);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,16 @@
Create empty max heap & destroy
Create empty max heap but allocate size for some elements
Create empty min heap & destroy
Create empty min heap but allocate size for some elements
Test max heap_reserve, heap_size and heap_empty
Test min heap_reserve, heap_size and heap_empty
Test max heap_init array and delete_top
2000 235 10 6 6 4 1 0.5 0 -1 -2 -2 -9 -9.999 -1000
Test min heap init_array and delete_top
-1000 -9.999 -9 -2 -2 -1 0 0.5 1 4 6 6 10 235 2000
Test max heap top and push
-2 -2 0 6 235 235 235 235 235 2000 2000 2000 2000 2000 2000
2000 235 10 6 6 4 1 0.5 0 -1 -2 -2 -9 -9.999 -1000
Test min heap top and push
-2 -9.999 -9.999 -9.999 -9.999 -9.999 -1000 -1000 -1000 -1000 -1000 -1000 -1000 -1000 -1000
-1000 -9.999 -9 -2 -2 -1 0 0.5 1 4 6 6 10 235 2000
@@ -0,0 +1,148 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void print_hub_and_authority(igraph_t *g, igraph_vector_t *weights, igraph_bool_t use_options) {
igraph_arpack_options_t options;
igraph_vector_t hub_vector, authority_vector;
igraph_real_t value;
igraph_arpack_options_init(&options);
igraph_vector_init(&hub_vector, 0);
igraph_vector_init(&authority_vector, 0);
printf("--------------------------------------------------\n");
igraph_hub_and_authority_scores(g, &hub_vector, &authority_vector, &value,
weights, use_options ? &options : NULL);
vector_chop(&hub_vector, 10e-10);
vector_chop(&authority_vector, 10e-10);
printf("hub:\n");
print_vector(&hub_vector);
printf("authority:\n");
print_vector(&authority_vector);
printf("value:\n");
print_real(stdout, value, "%g");
printf("\n");
printf("--------------------------------------------------\n\n\n");
igraph_vector_destroy(&hub_vector);
igraph_vector_destroy(&authority_vector);
}
int main(void) {
igraph_t g;
igraph_vector_t weights;
igraph_arpack_options_t options;
igraph_real_t value;
igraph_arpack_options_init(&options);
printf("Null graph:\n");
igraph_small(&g, 0, IGRAPH_DIRECTED, -1);
print_hub_and_authority(&g, NULL, true);
igraph_destroy(&g);
printf("Singleton graph with loop:\n");
igraph_small(&g, 1, IGRAPH_DIRECTED, 0,0, -1);
print_hub_and_authority(&g, NULL, true);
igraph_destroy(&g);
printf("Singleton graph with three loops:\n");
igraph_small(&g, 1, IGRAPH_DIRECTED, 0,0, 0,0, 0,0, -1);
print_hub_and_authority(&g, NULL, true);
igraph_destroy(&g);
printf("Three vertices, no links:\n");
igraph_small(&g, 3, IGRAPH_DIRECTED, -1);
print_hub_and_authority(&g, NULL, true);
igraph_destroy(&g);
printf("Two hubs and one authority:\n");
igraph_small(&g, 3, IGRAPH_DIRECTED,
0,2, 1,2, -1);
igraph_vector_init_int(&weights, 2,
1, 1);
print_hub_and_authority(&g, &weights, true);
igraph_destroy(&g);
igraph_vector_destroy(&weights);
/* https://nlp.stanford.edu/IR-book/html/htmledition/hubs-and-authorities-1.html */
/* with different normalization */
printf("Stanford example:\n");
igraph_small(&g, 7, IGRAPH_DIRECTED,
0,2, 1,1, 1,2, 2,0, 2,2, 2,3, 3,3, 3,4, 4,6, 5,5,
5,6, 6,3, 6,4, 6,6, -1);
igraph_vector_init_int(&weights, 14,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
1, 2, 1, 1);
print_hub_and_authority(&g, &weights, false);
igraph_destroy(&g);
igraph_vector_destroy(&weights);
printf("Same example with scaling:\n");
igraph_small(&g, 7, IGRAPH_DIRECTED,
0,2, 1,1, 1,2, 2,0, 2,2, 2,3, 3,3, 3,4, 4,6, 5,5,
5,6, 6,3, 6,4, 6,6, -1);
igraph_vector_init_int(&weights, 14,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
1, 2, 1, 1);
print_hub_and_authority(&g, &weights, false);
igraph_destroy(&g);
igraph_vector_destroy(&weights);
/* Verify that self-loops are counted twice in undirected graphs. */
printf("Undirected graph with self-loops and multi-edges:\n");
igraph_small(&g, 0, IGRAPH_UNDIRECTED,
0, 1, 1, 2, 2, 2, 2, 3, 2, 3,
-1);
print_hub_and_authority(&g, NULL, false);
igraph_destroy(&g);
printf("Degenerate example:\n");
igraph_small(&g, 4, IGRAPH_DIRECTED,
0,1, 1,0, 1,2, 2,1, 2,3, 3,0, -1);
igraph_hub_and_authority_scores(&g, NULL, NULL, &value,
NULL, &options);
printf("--------------------------------------------------\n");
printf("value:\n");
print_real(stdout, value, "%g");
printf("\n");
printf("--------------------------------------------------\n\n\n");
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
igraph_set_error_handler(igraph_error_handler_ignore);
printf("Checking invalid weight vector.\n");
igraph_small(&g, 3, IGRAPH_DIRECTED,
0,2, 1,2, -1);
igraph_vector_init_int(&weights, 3,
1, 1, 1);
IGRAPH_ASSERT(igraph_hub_and_authority_scores(&g, NULL, NULL, NULL,
&weights, &options) == IGRAPH_EINVAL);
igraph_destroy(&g);
igraph_vector_destroy(&weights);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,96 @@
Null graph:
--------------------------------------------------
hub:
( )
authority:
( )
value:
0
--------------------------------------------------
Singleton graph with loop:
--------------------------------------------------
hub:
( 1 )
authority:
( 1 )
value:
1
--------------------------------------------------
Singleton graph with three loops:
--------------------------------------------------
hub:
( 1 )
authority:
( 1 )
value:
9
--------------------------------------------------
Three vertices, no links:
--------------------------------------------------
hub:
( 1 1 1 )
authority:
( 1 1 1 )
value:
0
--------------------------------------------------
Two hubs and one authority:
--------------------------------------------------
hub:
( 1 1 0 )
authority:
( 0 0 1 )
value:
2
--------------------------------------------------
Stanford example:
--------------------------------------------------
hub:
( 0.100055 0.109548 0.944987 0.5126 0.10588 0.115926 1 )
authority:
( 0.214644 0.0248828 0.262253 1 0.343572 0.0263314 0.277521 )
value:
11.5396
--------------------------------------------------
Same example with scaling:
--------------------------------------------------
hub:
( 0.100055 0.109548 0.944987 0.5126 0.10588 0.115926 1 )
authority:
( 0.214644 0.0248828 0.262253 1 0.343572 0.0263314 0.277521 )
value:
11.5396
--------------------------------------------------
Undirected graph with self-loops and multi-edges:
--------------------------------------------------
hub:
( 0.0906902 0.314507 1 0.576713 )
authority:
( 0.0906902 0.314507 1 0.576713 )
value:
12.0266
--------------------------------------------------
Degenerate example:
--------------------------------------------------
value:
2.61803
--------------------------------------------------
Checking invalid weight vector.
@@ -0,0 +1,73 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_vector_int_t v;
/* Create graph */
igraph_small(&g, 0, IGRAPH_DIRECTED,
0, 1, 1, 2, 2, 3, 2, 2,
-1);
/* Add edges */
igraph_vector_int_init_int(&v, 4, 2, 1, 3, 3);
igraph_add_edges(&g, &v, 0);
/* Check result */
igraph_get_edgelist(&g, &v, 0);
print_vector_int(&v);
/* Error, vector length */
igraph_vector_int_resize(&v, 3);
VECTOR(v)[0] = 0;
VECTOR(v)[1] = 1;
VECTOR(v)[2] = 2;
CHECK_ERROR(igraph_add_edges(&g, &v, 0), IGRAPH_EINVAL);
/* Check result */
igraph_get_edgelist(&g, &v, 0);
print_vector_int(&v);
/* Error, vector IDs */
igraph_vector_int_resize(&v, 4);
VECTOR(v)[0] = 0;
VECTOR(v)[1] = 1;
VECTOR(v)[2] = 2;
VECTOR(v)[3] = 4;
CHECK_ERROR(igraph_add_edges(&g, &v, 0), IGRAPH_EINVVID);
/* Check result */
igraph_get_edgelist(&g, &v, 0);
print_vector_int(&v);
igraph_vector_int_destroy(&v);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,3 @@
( 0 1 1 2 2 3 2 2 2 1 3 3 )
( 0 1 1 2 2 3 2 2 2 1 3 3 )
( 0 1 1 2 2 3 2 2 2 1 3 3 )
@@ -0,0 +1,60 @@
/*
igraph library.
Copyright (C) 2006-2012 Gabor Csardi <csardi.gabor@gmail.com>
334 Harvard street, Cambridge, MA 02139 USA
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g1;
igraph_vector_int_t v1;
/* Create a graph */
igraph_vector_int_init(&v1, 8);
VECTOR(v1)[0] = 0;
VECTOR(v1)[1] = 1;
VECTOR(v1)[2] = 1;
VECTOR(v1)[3] = 2;
VECTOR(v1)[4] = 2;
VECTOR(v1)[5] = 3;
VECTOR(v1)[6] = 2;
VECTOR(v1)[7] = 2;
igraph_create(&g1, &v1, 0, 0);
igraph_vector_int_destroy(&v1);
/* Add more vertices */
igraph_add_vertices(&g1, 10, 0);
IGRAPH_ASSERT(igraph_vcount(&g1) == 14);
/* Add more vertices */
igraph_add_vertices(&g1, 0, 0);
IGRAPH_ASSERT(igraph_vcount(&g1) == 14);
/* Error */
CHECK_ERROR(igraph_add_vertices(&g1, -1, 0), IGRAPH_EINVAL);
igraph_destroy(&g1);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,49 @@
/*
igraph library.
Copyright (C) 2021 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
int main(void) {
igraph_t g;
igraph_int_t value;
igraph_bool_t checks = 1;
igraph_small(&g, 7, IGRAPH_DIRECTED,
0, 1, 0, 2, 1, 2, 1, 3, 2, 4, 3, 4, 3, 5, 4, 5, 1, 6, 6, 3, -1);
igraph_adhesion(&g, &value, checks);
IGRAPH_ASSERT(value == 0);
igraph_destroy(&g);
igraph_small(&g, 7, IGRAPH_UNDIRECTED,
0, 1, 0, 2, 1, 2, 1, 3, 2, 4, 3, 4, 3, 5, 4, 5, 1, 6, 6, 3, -1);
igraph_adhesion(&g, &value, checks);
IGRAPH_ASSERT(value == 2);
igraph_destroy(&g);
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,257 @@
/*
igraph library.
Copyright (C) 2022 The igraph development team <igraph@igraph.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <igraph.h>
#include "test_utilities.h"
void print_destroy(igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, igraph_loops_t loops) {
igraph_t g;
igraph_t g_sparse;
igraph_sparsemat_t sparse_adjmatrix, sparse_adjmatrix_comp;
igraph_bool_t same;
igraph_adjacency(&g, adjmatrix, mode, loops);
igraph_matrix_as_sparsemat(&sparse_adjmatrix, adjmatrix, 0.0001);
igraph_sparsemat_compress(&sparse_adjmatrix, &sparse_adjmatrix_comp);
igraph_sparse_adjacency(&g_sparse, &sparse_adjmatrix_comp, mode, loops);
print_graph_canon(&g);
igraph_is_same_graph(&g, &g_sparse, &same);
if (!same) {
printf("Sparse graph differs from non-sparse:\n");
print_graph_canon(&g_sparse);
exit(1);
}
igraph_matrix_destroy(adjmatrix);
igraph_sparsemat_destroy(&sparse_adjmatrix);
igraph_sparsemat_destroy(&sparse_adjmatrix_comp);
igraph_destroy(&g);
igraph_destroy(&g_sparse);
}
void check_error(igraph_matrix_t *adjmatrix, igraph_adjacency_t mode, igraph_loops_t loops, igraph_error_t error) {
igraph_t g;
igraph_sparsemat_t sparse_adjmatrix, sparse_adjmatrix_comp;
igraph_matrix_as_sparsemat(&sparse_adjmatrix, adjmatrix, 0.0001);
igraph_sparsemat_compress(&sparse_adjmatrix, &sparse_adjmatrix_comp);
CHECK_ERROR(igraph_adjacency(&g, adjmatrix, mode, loops), error);
CHECK_ERROR(igraph_sparse_adjacency(&g, &sparse_adjmatrix_comp, mode, loops), error);
igraph_sparsemat_destroy(&sparse_adjmatrix);
igraph_sparsemat_destroy(&sparse_adjmatrix_comp);
}
int main(void) {
igraph_matrix_t adjmatrix;
printf("\n0x0 matrix:\n");
matrix_init_int_row_major(&adjmatrix, 0, 0, NULL);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_LOOPS_ONCE);
printf("\n1x1 matrix, no loops:\n");
{
int e[] = {1};
matrix_init_int_row_major(&adjmatrix, 1, 1, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_NO_LOOPS);
}
printf("\n1x1 matrix, loops once:\n");
{
int e[] = {1};
matrix_init_int_row_major(&adjmatrix, 1, 1, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_LOOPS_ONCE);
}
printf("\n1x1 matrix, loops twice (treated as loops once):\n");
{
int e[] = {1};
matrix_init_int_row_major(&adjmatrix, 1, 1, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_DIRECTED, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_DIRECTED, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_DIRECTED, loops twice (treated as loops once):\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UNDIRECTED, no loops:\n");
{
int e[] = {4, 2, 0, 2, 0, 4, 0, 4, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UNDIRECTED, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UNDIRECTED, loops once:\n");
{
int e[] = {4, 2, 0, 2, 0, 4, 0, 4, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UNDIRECTED, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UNDIRECTED, loops twice:\n");
{
int e[] = {4, 2, 0, 2, 0, 4, 0, 4, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UNDIRECTED, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MAX, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MAX, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MAX, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MAX, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MAX, loops twice:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MAX, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MIN, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 5, 0, 4, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MIN, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MIN, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MIN, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_MIN, loops twice:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_MIN, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_PLUS, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_PLUS, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_PLUS, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_PLUS, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_PLUS, loops twice:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_PLUS, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UPPER, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UPPER, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UPPER, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UPPER, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_UPPER, loops twice (treated as loops once):\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_UPPER, IGRAPH_LOOPS_TWICE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_LOWER, no loops:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_LOWER, IGRAPH_NO_LOOPS);
}
printf("\n3x3 matrix, IGRAPH_ADJ_LOWER, loops once:\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_LOWER, IGRAPH_LOOPS_ONCE);
}
printf("\n3x3 matrix, IGRAPH_ADJ_LOWER, loops twice (treated as loops once):\n");
{
int e[] = {4, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
print_destroy(&adjmatrix, IGRAPH_ADJ_LOWER, IGRAPH_LOOPS_TWICE);
}
VERIFY_FINALLY_STACK();
printf("\nCheck handling of non-square matrix error.\n");
{
int e[] = {1, 2, 0};
matrix_init_int_row_major(&adjmatrix, 3, 1, e);
check_error(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_NO_LOOPS, IGRAPH_EINVAL);
igraph_matrix_destroy(&adjmatrix);
}
printf("\nCheck handling of negative number of edges error.\n");
{
int e[] = {1, 2, 0, -3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
check_error(&adjmatrix, IGRAPH_ADJ_DIRECTED, IGRAPH_NO_LOOPS, IGRAPH_EINVAL);
igraph_matrix_destroy(&adjmatrix);
}
printf("\nCheck handling of odd number in diagonal.\n");
{
int e[] = {1, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
check_error(&adjmatrix, IGRAPH_ADJ_UNDIRECTED, IGRAPH_LOOPS_TWICE, IGRAPH_EINVAL);
igraph_matrix_destroy(&adjmatrix);
}
printf("\nCheck handling of invalid adjacency mode.\n");
{
int e[] = {0, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
check_error(&adjmatrix, (igraph_adjacency_t) 42, IGRAPH_LOOPS_TWICE, IGRAPH_EINVAL);
igraph_matrix_destroy(&adjmatrix);
}
printf("\nCheck handling of non-symmetric matrix for IGRAPH_ADJ_UNDIRECTED.\n");
{
int e[] = {0, 2, 0, 3, 0, 4, 0, 5, 6};
matrix_init_int_row_major(&adjmatrix, 3, 3, e);
check_error(&adjmatrix, IGRAPH_ADJ_UNDIRECTED, IGRAPH_LOOPS_ONCE, IGRAPH_EINVAL);
igraph_matrix_destroy(&adjmatrix);
}
VERIFY_FINALLY_STACK();
return 0;
}
@@ -0,0 +1,468 @@
0x0 matrix:
directed: true
vcount: 0
edges: {
}
1x1 matrix, no loops:
directed: true
vcount: 1
edges: {
}
1x1 matrix, loops once:
directed: true
vcount: 1
edges: {
0 0
}
1x1 matrix, loops twice (treated as loops once):
directed: true
vcount: 1
edges: {
0 0
}
3x3 matrix, IGRAPH_ADJ_DIRECTED, no loops:
directed: true
vcount: 3
edges: {
0 1
0 1
1 0
1 0
1 0
1 2
1 2
1 2
1 2
2 1
2 1
2 1
2 1
2 1
}
3x3 matrix, IGRAPH_ADJ_DIRECTED, loops once:
directed: true
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 0
1 0
1 0
1 2
1 2
1 2
1 2
2 1
2 1
2 1
2 1
2 1
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_DIRECTED, loops twice (treated as loops once):
directed: true
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 0
1 0
1 0
1 2
1 2
1 2
1 2
2 1
2 1
2 1
2 1
2 1
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_UNDIRECTED, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_UNDIRECTED, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_UNDIRECTED, loops twice:
directed: false
vcount: 3
edges: {
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_MAX, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_MAX, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_MAX, loops twice:
directed: false
vcount: 3
edges: {
0 0
0 0
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_MIN, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_MIN, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_MIN, loops twice:
directed: false
vcount: 3
edges: {
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_PLUS, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_PLUS, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_PLUS, loops twice:
directed: false
vcount: 3
edges: {
0 0
0 0
0 1
0 1
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_UPPER, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_UPPER, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_UPPER, loops twice (treated as loops once):
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_LOWER, no loops:
directed: false
vcount: 3
edges: {
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
}
3x3 matrix, IGRAPH_ADJ_LOWER, loops once:
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
3x3 matrix, IGRAPH_ADJ_LOWER, loops twice (treated as loops once):
directed: false
vcount: 3
edges: {
0 0
0 0
0 0
0 0
0 1
0 1
0 1
1 2
1 2
1 2
1 2
1 2
2 2
2 2
2 2
2 2
2 2
2 2
}
Check handling of non-square matrix error.
Check handling of negative number of edges error.
Check handling of odd number in diagonal.
Check handling of invalid adjacency mode.
Check handling of non-symmetric matrix for IGRAPH_ADJ_UNDIRECTED.

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