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