1
2 #include <igraph.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "test_utilities.inc"
7
random_permutation(igraph_vector_t * vec)8 int random_permutation(igraph_vector_t *vec) {
9 /* We just do size(vec) * 2 swaps */
10 long int one, two, tmp, i, n = igraph_vector_size(vec);
11 for (i = 0; i < 2 * n; i++) {
12 one = (double)rand() / RAND_MAX * n;
13 two = (double)rand() / RAND_MAX * n;
14 tmp = one;
15 one = two;
16 two = tmp;
17 }
18 return 0;
19 }
20
21
test3()22 void test3() {
23 int i, j;
24 igraph_vector_ptr_t graphs3;
25
26 // Verify that no two 3-vertex graphs of distinct isoclasses are considered isomorphic by Bliss or VF2.
27
28 igraph_vector_ptr_init(&graphs3, 0);
29 IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&graphs3, igraph_destroy);
30
31 for (i = 0; i < 16; i++) {
32 igraph_t *g;
33 g = (igraph_t *) malloc(sizeof(igraph_t));
34 igraph_vector_ptr_push_back(&graphs3, g);
35 igraph_isoclass_create(g, 3, i, /* directed = */ 1);
36 }
37
38 for (i = 0; i < 16; i++)
39 for (j = i + 1; j < 16; j++) {
40 igraph_bool_t iso;
41 igraph_isomorphic_bliss(
42 (igraph_t *) VECTOR(graphs3)[i], (igraph_t *) VECTOR(graphs3)[j],
43 NULL, NULL, &iso, NULL, NULL, IGRAPH_BLISS_F, NULL, NULL);
44 if (iso) {
45 printf("Bliss failure, 3 vertex directed graphs of isoclass %d and %d are not isomorphic. Bliss reports otherwise.\n", i, j);
46 }
47 }
48
49 for (i = 0; i < 16; i++)
50 for (j = i + 1; j < 16; j++) {
51 igraph_bool_t iso;
52 igraph_isomorphic_vf2(
53 (igraph_t *) VECTOR(graphs3)[i], (igraph_t *) VECTOR(graphs3)[j],
54 NULL, NULL, NULL, NULL, &iso, NULL, NULL, NULL, NULL, NULL);
55 if (iso) {
56 printf("VF2 failure, 3 vertex directed graphs of isoclass %d and %d are not isomorphic. VF2 reports otherwise.\n", i, j);
57 }
58 }
59
60 igraph_vector_ptr_destroy_all(&graphs3);
61 }
62
63
test4()64 void test4() {
65 int i, j;
66 igraph_vector_ptr_t graphs4;
67
68 // Verify that no two 4-vertex graphs of distinct isoclasses are considered isomorphic by Bliss or VF2.
69
70 igraph_vector_ptr_init(&graphs4, 0);
71 IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&graphs4, igraph_destroy);
72
73 for (i = 0; i < 218; i++) {
74 igraph_t *g;
75 g = (igraph_t *) malloc(sizeof(igraph_t));
76 igraph_vector_ptr_push_back(&graphs4, g);
77 igraph_isoclass_create(g, 4, i, /* directed = */ 1);
78 }
79
80 for (i = 0; i < 218; i++)
81 for (j = i + 1; j < 218; j++) {
82 igraph_bool_t iso;
83 igraph_isomorphic_bliss(
84 (igraph_t *) VECTOR(graphs4)[i], (igraph_t *) VECTOR(graphs4)[j],
85 NULL, NULL, &iso, NULL, NULL, IGRAPH_BLISS_F, NULL, NULL);
86 if (iso) {
87 printf("Bliss failure, 4 vertex directed graphs of isoclass %d and %d are not isomorphic. Bliss reports otherwise.\n", i, j);
88 }
89 }
90
91 for (i = 0; i < 218; i++)
92 for (j = i + 1; j < 218; j++) {
93 igraph_bool_t iso;
94 igraph_isomorphic_vf2(
95 (igraph_t *) VECTOR(graphs4)[i], (igraph_t *) VECTOR(graphs4)[j],
96 NULL, NULL, NULL, NULL, &iso, NULL, NULL, NULL, NULL, NULL);
97 if (iso) {
98 printf("VF2 failure, 4 vertex directed graphs of isoclass %d and %d are not isomorphic. VF2 reports otherwise.\n", i, j);
99 }
100 }
101
102 igraph_vector_ptr_destroy_all(&graphs4);
103 }
104
105
test_bliss()106 void test_bliss() {
107 igraph_t ring1, ring2, directed_ring;
108 igraph_vector_t perm;
109 igraph_bool_t iso;
110 igraph_bliss_info_t info;
111 igraph_vector_int_t color;
112 igraph_vector_ptr_t generators;
113
114 igraph_ring(&ring1, 100, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/1);
115 igraph_vector_init_seq(&perm, 0, igraph_vcount(&ring1) - 1);
116 random_permutation(&perm);
117 igraph_permute_vertices(&ring1, &ring2, &perm);
118
119 igraph_ring(&directed_ring, 100, /* directed= */ 1, /* mutual = */0, /* circular = */1);
120
121 igraph_vector_ptr_init(&generators, 0);
122 IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&generators, igraph_vector_destroy);
123
124 igraph_isomorphic_bliss(&ring1, &ring2, NULL, NULL, &iso, NULL, NULL, IGRAPH_BLISS_F, NULL, NULL);
125 if (! iso) {
126 printf("Bliss failed on ring isomorphism.\n");
127 }
128
129 igraph_automorphisms(&ring1, NULL, IGRAPH_BLISS_F, &info);
130 if (strcmp(info.group_size, "200") != 0) {
131 printf("Biss automorphism count failed: ring1.\n");
132 }
133 igraph_free(info.group_size);
134
135 igraph_automorphisms(&ring2, NULL, IGRAPH_BLISS_F, &info);
136 if (strcmp(info.group_size, "200") != 0) {
137 printf("Biss automorphism count failed: ring2.\n");
138 }
139 igraph_free(info.group_size);
140
141 igraph_automorphisms(&directed_ring, NULL, IGRAPH_BLISS_F, &info);
142 if (strcmp(info.group_size, "100") != 0) {
143 printf("Biss automorphism count failed: directed_ring.\n");
144 }
145 igraph_free(info.group_size);
146
147 // The follwing test is included so there is at least one call to igraph_automorphism_group
148 // in the test suite. However, the generator set returned may depend on the splitting
149 // heursitics as well as on the Bliss version. If the test fails, please verify manually
150 // that the generating set is valid. For a undirected cycle graph like ring2, there should
151 // be two generators: a cyclic permutation and a reversal of the vertex order.
152 igraph_automorphism_group(&ring2, NULL, &generators, IGRAPH_BLISS_F, NULL);
153 if (igraph_vector_ptr_size(&generators) != 2)
154 printf("Bliss automorphism generators may have failed with ring2. "
155 "Please verify the generators manually. "
156 "Note that the generator set is not guaranteed to be minimal.\n");
157 igraph_vector_ptr_free_all(&generators);
158
159 // For a directed ring, the only generator should be a cyclic permutation.
160 igraph_automorphism_group(&directed_ring, NULL, &generators, IGRAPH_BLISS_F, NULL);
161 if (igraph_vector_ptr_size(&generators) != 1)
162 printf("Bliss automorphism generators may have failed with directed_ring. "
163 "Please verify the generators manually. "
164 "Note that the generator set is not guaranteed to be minimal.\n");
165 igraph_vector_ptr_free_all(&generators);
166
167 igraph_vector_int_init_seq(&color, 0, igraph_vcount(&ring1) - 1);
168
169 igraph_automorphisms(&ring1, &color, IGRAPH_BLISS_F, &info);
170 if (strcmp(info.group_size, "1") != 0) {
171 printf("Biss automorphism count with color failed: ring1.\n");
172 }
173 igraph_free(info.group_size);
174
175 // There's only one automorphism for this coloured graph, so the generating set is empty.
176 igraph_automorphism_group(&ring1, &color, &generators, IGRAPH_BLISS_F, NULL);
177 if (igraph_vector_ptr_size(&generators) != 0) {
178 printf("Bliss automorphism generators failed with colored graph.\n");
179 }
180
181 igraph_vector_ptr_destroy_all(&generators);
182
183 igraph_vector_int_destroy(&color);
184
185 igraph_vector_destroy(&perm);
186
187 igraph_destroy(&ring1);
188 igraph_destroy(&ring2);
189 igraph_destroy(&directed_ring);
190 }
191
test_bug_995()192 void test_bug_995() {
193 igraph_t g1, g2;
194 igraph_bool_t result;
195
196 igraph_small(&g1, 3, 0, 0, 1, 1, 2, 2, 2, -1);
197 igraph_small(&g2, 3, 0, 0, 1, 1, 2, 1, 1, -1);
198
199 igraph_isomorphic(&g1, &g2, &result);
200 if (result) {
201 printf("igraph_isomorphic() failed with loop edges, see bug #995\n");
202 }
203
204 igraph_destroy(&g1);
205 igraph_destroy(&g2);
206 }
207
main()208 int main() {
209
210 srand(293847); /* rand() is used in random_permutation() */
211
212 test3();
213 test4();
214 test_bliss();
215 test_bug_995();
216
217 VERIFY_FINALLY_STACK();
218
219 return 0;
220 }
221