Coverage Report

Created: 2026-10-16 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/igraph/fuzzing/community.cpp
Line
Count
Source
1
/*
2
   igraph library.
3
   Copyright (C) 2024  The igraph development team
4
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 2 of the License, or
8
   (at your option) any later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program; if not, write to the Free Software
17
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
   02110-1301 USA
19
*/
20
21
#include <igraph.h>
22
#include <cstdlib>
23
24
// Verify that all communities are connected subgraphs
25
6.76k
void check_communities_are_connected(const igraph_t *graph, const igraph_vector_int_t *membership) {
26
6.76k
    igraph_vector_int_t memb, comp, map;
27
6.76k
    igraph_int_t vcount = igraph_vcount(graph);
28
6.76k
    igraph_int_t no;
29
30
6.76k
    igraph_vector_int_init_copy(&memb, membership);
31
6.76k
    igraph_reindex_membership(&memb, NULL, &no);
32
33
6.76k
    igraph_vector_int_init(&map, no);
34
6.76k
    igraph_vector_int_fill(&map, -1);
35
36
6.76k
    igraph_vector_int_init(&comp, 0);
37
38
6.76k
    igraph_connected_components(graph, &comp, NULL, NULL, IGRAPH_WEAK);
39
40
327k
    for (igraph_int_t v=0; v < vcount; v++) {
41
320k
        if (VECTOR(map)[ VECTOR(memb)[v] ] == -1) {
42
319k
            VECTOR(map)[ VECTOR(memb)[v] ] = VECTOR(comp)[v];
43
319k
        } else {
44
1.26k
            IGRAPH_ASSERT(VECTOR(map)[ VECTOR(memb)[v] ] == VECTOR(comp)[v]);
45
1.26k
        }
46
320k
    }
47
48
6.76k
    igraph_vector_int_destroy(&comp);
49
6.76k
    igraph_vector_int_destroy(&map);
50
6.76k
    igraph_vector_int_destroy(&memb);
51
6.76k
}
52
53
3.42k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
54
3.42k
    igraph_t graph;
55
3.42k
    igraph_vector_int_t edges;
56
57
3.42k
    igraph_set_warning_handler(igraph_warning_handler_ignore);
58
59
3.42k
    if (Size % 2 == 0 || Size > 512+1 || Size < 1) {
60
14
        return 0;
61
14
    }
62
63
3.41k
    igraph_vector_int_init(&edges, Size-1);
64
207k
    for (size_t i=0; i < Size-1; ++i) {
65
204k
        VECTOR(edges)[i] = Data[i+1];
66
204k
    }
67
68
3.41k
    igraph_rng_seed(igraph_rng_default(), 42);
69
70
3.41k
    if (igraph_create(&graph, &edges, Data[0], IGRAPH_DIRECTED) == IGRAPH_SUCCESS) {
71
3.41k
        igraph_matrix_int_t merges, im;
72
3.41k
        igraph_matrix_t mat;
73
3.41k
        igraph_vector_int_t membership, membership2, iv, iv2;
74
3.41k
        igraph_vector_t mv, v;
75
3.41k
        igraph_real_t m, r;
76
3.41k
        igraph_int_t i;
77
3.41k
        igraph_bool_t b;
78
79
        /* Limit graph size for the sake of performance. */
80
3.41k
        if (igraph_vcount(&graph) <= 64) {
81
3.38k
            igraph_matrix_int_init(&merges, 0, 0);
82
3.38k
            igraph_matrix_int_init(&im, 0, 0);
83
3.38k
            igraph_matrix_init(&mat, 0, 0);
84
3.38k
            igraph_vector_int_init(&membership, 0);
85
3.38k
            igraph_vector_int_init(&membership2, 0);
86
3.38k
            igraph_vector_int_init(&iv, 0);
87
3.38k
            igraph_vector_int_init(&iv2, 0);
88
3.38k
            igraph_vector_init(&mv, 0);
89
3.38k
            igraph_vector_init(&v, 0);
90
91
            // The IGRAPH_LPA_FAST version is temporarily switched to undirected until
92
            // the reason for the bad performance / infinite loop in the directed version
93
            // is debugged. See https://github.com/igraph/igraph/issues/2608
94
3.38k
            igraph_community_label_propagation(&graph, &membership, IGRAPH_ALL, NULL, NULL, NULL, IGRAPH_LPA_FAST);
95
3.38k
            igraph_community_label_propagation(&graph, &membership, IGRAPH_OUT, NULL, NULL, NULL, IGRAPH_LPA_RETENTION);
96
3.38k
            igraph_community_label_propagation(&graph, &membership, IGRAPH_OUT, NULL, NULL, NULL, IGRAPH_LPA_DOMINANCE);
97
98
3.38k
            igraph_community_walktrap(&graph, NULL, 3, &merges, &mv, &membership);
99
3.38k
            igraph_community_edge_betweenness(&graph, &iv, &v, &merges, &iv2, &mv, &membership2, IGRAPH_DIRECTED, NULL, NULL);
100
101
3.38k
            igraph_community_leiden(&graph, NULL, NULL, NULL, 1.5, 0.01, false, 2, &membership, &i, &r);
102
3.38k
            check_communities_are_connected(&graph, &membership);
103
104
            // Take the opportunity to run functions that can use the output of community detection.
105
106
3.38k
            {
107
3.38k
                igraph_community_comparison_t method[] = {
108
3.38k
                    IGRAPH_COMMCMP_VI,
109
3.38k
                    IGRAPH_COMMCMP_NMI,
110
3.38k
                    IGRAPH_COMMCMP_SPLIT_JOIN,
111
3.38k
                    IGRAPH_COMMCMP_RAND,
112
3.38k
                    IGRAPH_COMMCMP_ADJUSTED_RAND
113
3.38k
                };
114
20.2k
                for (size_t i=0; i < sizeof(method) / sizeof(method[0]); i++) {
115
16.9k
                    if ((method[i] == IGRAPH_COMMCMP_RAND ||
116
13.5k
                         method[i] == IGRAPH_COMMCMP_ADJUSTED_RAND) &&
117
6.76k
                        igraph_vcount(&graph) < 2) {
118
26
                        continue;
119
26
                    }
120
16.8k
                    igraph_compare_communities(&membership, &membership2, &r, method[i]);
121
16.8k
                }
122
3.38k
            }
123
124
3.38k
            {
125
3.38k
                igraph_t graph2;
126
3.38k
                igraph_copy(&graph2, &graph);
127
3.38k
                igraph_contract_vertices(&graph2, &membership, NULL);
128
3.38k
                igraph_destroy(&graph2);
129
3.38k
            }
130
131
3.38k
            igraph_modularity(&graph, &membership, NULL, 1.5, IGRAPH_UNDIRECTED, &m);
132
3.38k
            igraph_modularity_matrix(&graph, NULL, 0.75, &mat, IGRAPH_DIRECTED);
133
3.38k
            igraph_assortativity_nominal(&graph, NULL, &membership, &r, IGRAPH_DIRECTED, true);
134
135
3.38k
            igraph_simplify(&graph, true, true, NULL);
136
3.38k
            igraph_community_voronoi(&graph, &membership, &iv, &m, NULL, NULL, IGRAPH_OUT, 1.0);
137
138
3.38k
            igraph_to_undirected(&graph, IGRAPH_TO_UNDIRECTED_COLLAPSE, NULL);
139
3.38k
            igraph_community_fastgreedy(&graph, NULL, &merges, &mv, &membership);
140
141
3.38k
            igraph_community_leiden(&graph, NULL, NULL, NULL, 1.5, 0.01, false, 2, &membership, &i, &r);
142
3.38k
            check_communities_are_connected(&graph, &membership);
143
144
3.38k
            igraph_community_multilevel(&graph, NULL, 0.8, &membership, &im, &mv);
145
146
3.38k
            igraph_is_connected(&graph, &b, IGRAPH_WEAK);
147
3.38k
            if (b) {
148
230
                igraph_int_t no_comm = 4;
149
230
                if (no_comm > igraph_vcount(&graph)) {
150
59
                    no_comm = igraph_vcount(&graph);
151
59
                }
152
230
                igraph_community_fluid_communities(&graph, no_comm, &membership);
153
230
            }
154
155
3.38k
            igraph_vector_destroy(&v);
156
3.38k
            igraph_vector_destroy(&mv);
157
3.38k
            igraph_vector_int_destroy(&iv2);
158
3.38k
            igraph_vector_int_destroy(&iv);
159
3.38k
            igraph_vector_int_destroy(&membership2);
160
3.38k
            igraph_vector_int_destroy(&membership);
161
3.38k
            igraph_matrix_destroy(&mat);
162
3.38k
            igraph_matrix_int_destroy(&im);
163
3.38k
            igraph_matrix_int_destroy(&merges);
164
3.38k
        }
165
166
3.41k
        igraph_destroy(&graph);
167
3.41k
    }
168
169
3.41k
    igraph_vector_int_destroy(&edges);
170
171
3.41k
    IGRAPH_ASSERT(IGRAPH_FINALLY_STACK_EMPTY);
172
173
3.41k
    return 0;  // Non-zero return values are reserved for future use.
174
3.41k
}