Files
Abdelrahman Said a11edf0c53 Add graph references
2026-06-28 13:49:01 +01:00

306 lines
11 KiB
C

/*
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;
}