Orbiter 2022
Combinatorial Objects
hadamard_classify.cpp
Go to the documentation of this file.
1/*
2 * hadamard_classify.cpp
3 *
4 * Created on: Oct 28, 2019
5 * Author: betten
6 */
7
8
9#include "orbiter.h"
10
11using namespace std;
12
13namespace orbiter {
14namespace layer5_applications {
15namespace apps_combinatorics {
16
17
18
19static void hadamard_classify_early_test_function(long int *S, int len,
20 long int *candidates, int nb_candidates,
21 long int *good_candidates, int &nb_good_candidates,
22 void *data, int verbose_level);
23
24
25
26void hadamard_classify::init(int n, int f_draw,
27 int verbose_level, int verbose_level_clique)
28{
29 int f_v = (verbose_level = 1);
30 int i, j, k, d, cnt, cnt1;
32
33
34 if (n > (int)sizeof(int) * 8) {
35 cout << "n > sizeof(uint) * 8" << endl;
36 exit(1);
37 }
38
40
41 v = NEW_int(n);
42
43 N = (1 << n);
44
45 if (f_v) {
46 cout << "n =" << n << endl;
47 cout << "N =" << N << endl;
48 }
49
50 N2 = (N * (N - 1)) >> 1;
51
52 if (f_v) {
53 cout << "N2 = (N * (N - 1)) >> 1 =" << N2 << endl;
54 cout << "list of points:" << endl;
55 for (i = 0; i < N; i++) {
56 Gg.AG_element_unrank(2, v, 1, n, i);
57 cout << i << " : ";
58 for (j = 0; j < n; j++) {
59 if (v[j]) {
60 cout << "+";
61 }
62 else {
63 cout << "-";
64 }
65 }
66 //int_vec_print(cout, v, n);
67 cout << endl;
68 }
69 }
70
73 //bitvector_length = (N2 + 7) >> 3;
74
75 //bitvector_adjacency = NEW_uchar(bitvector_length);
76
77 if (f_v) {
78 cout << "after allocating adjacency bitvector" << endl;
79 cout << "computing adjacency matrix:" << endl;
80 }
81 k = 0;
82 cnt = 0;
83 for (i = 0; i < N; i++) {
84 for (j = i + 1; j < N; j++) {
85
86 d = dot_product(i, j, n);
87
88 if (FALSE) {
89 cout << "dotproduct i=" << i << " j=" << j << " is " << d << endl;
90 }
91
92 if (d == 0) {
93 Bitvec->m_i(k, 1);
94 cnt++;
95 }
96 else {
97 Bitvec->m_i(k, 0);
98 }
99 k++;
100 if ((k & ((1 << 13) - 1)) == 0) {
101 cout << "i=" << i << " j=" << j << " k=" << k << " / " << N2 << endl;
102 }
103 }
104 }
105 cout << "We have " << cnt << " edges in the graph" << endl;
106
107
108#if 0
109 // test the graph:
110
111 k = 0;
112 cnt1 = 0;
113 for (i = 0; i < N; i++) {
114 for (j = i + 1; j < N; j++) {
115
116 d = dot_product(i, j, n);
117 if (bitvector_s_i(bitvector_adjacency, k)) {
118 cnt1++;
119 }
120 if (bitvector_s_i(bitvector_adjacency, k) && d) {
121 cout << "something is wrong in entry i=" << i << " j=" << j << endl;
122 cout << "dotproduct i=" << i << " j=" << j << " is " << d << endl;
123 cout << "bitvector_s_i(bitvector_adjacency, k)="
124 << bitvector_s_i(bitvector_adjacency, k) << endl;
125 exit(1);
126 }
127 k++;
128 }
129 }
130 cout << "We found " << cnt1 << " edges in the graph" << endl;
131
132 if (cnt1 != cnt) {
133 cout << "cnt1 != cnt, something is wrong" << endl;
134 cout << "cnt=" << cnt << endl;
135 cout << "cnt1=" << cnt1 << endl;
136 exit(1);
137 }
138#endif
139
140 char str[1000];
141
142 string label, label_tex;
143
144 sprintf(str, "Hadamard_graph_%d", n);
145 label.assign(str);;
146 sprintf(str, "Hadamard\\_graph\\_%d", n);
147 label_tex.assign(str);
148
149
150 {
152 string fname;
153
155 int *color;
156
157 color = NEW_int(N);
158 Int_vec_zero(color, N);
159
160
161 CG->init(N, 1, 1, color, Bitvec, FALSE, label, label_tex, verbose_level);
162
163 fname.assign(label);
164 fname.append(".colored_graph");
165
166 CG->save(fname, verbose_level);
167
168
169 FREE_int(color);
171 }
172
173
174
175
177
178 if (f_v) {
179 cout << "initializing colored graph" << endl;
180 }
181
182 int *color;
183
184 color = NEW_int(N);
185 Int_vec_zero(color, N);
186
187 CG->init(N, 1, 1, color, Bitvec, FALSE, label, label_tex, verbose_level);
188
189 if (f_v) {
190 cout << "initializing colored graph done" << endl;
191 }
192
193 string fname_graph;
194
195 sprintf(str, "Hadamard_graph_%d.magma", n);
196 fname_graph.assign(label);
197 fname_graph.append(".magma");
198
199 CG->export_to_magma(fname_graph, 1);
200
201 {
202 int *color_graph;
203
204 color_graph = NEW_int(N * N);
205 Int_vec_zero(color_graph, N * N);
206 k = 0;
207 cnt1 = 0;
208 for (i = 0; i < N; i++) {
209 for (j = i + 1; j < N; j++) {
210 if (Bitvec->s_i(k)) {
211 cnt1++;
212 color_graph[i * N + j] = 2;
213 color_graph[j * N + i] = 2;
214 }
215 else {
216 color_graph[i * N + j] = 1;
217 color_graph[j * N + i] = 1;
218 }
219 k++;
220 }
221 }
222 cout << "We found " << cnt1 << " edges in the graph" << endl;
223
224 if (cnt1 != cnt) {
225 cout << "cnt1 != cnt, something is wrong" << endl;
226 cout << "cnt=" << cnt << endl;
227 cout << "cnt1=" << cnt1 << endl;
228 exit(1);
229 }
230
231 cout << "color graph:" << endl;
232 if (N < 30) {
233 Int_matrix_print(color_graph, N, N);
234 }
235 else {
236 cout << "Too big to print" << endl;
237 }
238
239#if 0
240 int *Pijk;
241 int *colors;
242 int nb_colors;
243
244 is_association_scheme(color_graph, N, Pijk,
245 colors, nb_colors, verbose_level);
246
247 cout << "number of colors = " << nb_colors << endl;
248 cout << "colors: ";
249 int_vec_print(cout, colors, nb_colors);
250 cout << endl;
251 cout << "Pijk:" << endl;
252 for (i = 0; i < nb_colors; i++) {
253 cout << "i=" << i << ":" << endl;
254 int_matrix_print(Pijk + i * nb_colors * nb_colors, nb_colors, nb_colors);
255 }
256 FREE_int(Pijk);
257 FREE_int(colors);
258#endif
259
260 FREE_int(color_graph);
261 }
262
263 if (f_draw) {
264 if (f_v) {
265 cout << "drawing adjacency matrix" << endl;
266 }
267
268 char str[1000];
269 string fname_base;
270
271 sprintf(str, "Hadamard_graph_%d", n);
272 fname_base.assign(str);
273
274
275 CG->draw(fname_base,
276 orbiter_kernel_system::Orbiter->draw_options,
277 verbose_level);
278
279 if (f_v) {
280 cout << "drawing adjacency matrix done" << endl;
281 }
282 }
283
284
285 if (f_v) {
286 cout << "computing automorphism group of "
287 "uncolored graph:" << endl;
288 }
289
291
292
295 verbose_level);
296
298 A->group_order(go);
299 if (f_v) {
300 cout << "computing automorphism group of "
301 "uncolored graph done, group order = " << go << endl;
302 }
303
304 string fname_group;
305
306
307 fname_group.assign("Hadamard_group_");
308 sprintf(str, "%d", n);
309 fname_group.append(str);
310 fname_group.append(".magma");
311
313 fname_group, A, 1 /* verbose_level */);
314
315 char prefix[1000];
316 sprintf(prefix, "./had_%d", n);
317
318 if (f_v) {
319 cout << "Starting the clique finder, "
320 "target_depth = " << n << " prefix=" << prefix << endl;
321 }
322
325
327 Poset->init_subset_lattice(A, A,
328 A->Strong_gens,
329 verbose_level);
331 hadamard_classify_early_test_function,
332 this /* void *data */,
333 verbose_level);
334
337 Control->f_W = TRUE;
338 Control->problem_label = prefix;
339 Control->f_problem_label = TRUE;
340
341
343 n /* target_depth */,
344 //prefix,
345 //TRUE /* f_W */, FALSE /* f_w */,
346 Control,
347 Poset,
348 verbose_level_clique);
349
351
352 int h, a, c;
353 long int *set;
354 int *H;
355 int *Ht;
356 int *M;
357
358 set = NEW_lint(n);
359 H = NEW_int(n * n);
360 Ht = NEW_int(n * n);
361 M = NEW_int(n * n);
362 for (h = 0; h < nb_orbits; h++) {
363 gen->get_set_by_level(n, h, set);
364 cout << "Orbit " << h << " is the set ";
365 Lint_vec_print(cout, set, n);
366 cout << endl;
367
368
369 if (clique_test(set, n)) {
370 cout << "is a clique" << endl;
371 }
372 else {
373 cout << "is not a clique, this should not happen" << endl;
374 exit(1);
375 }
376
377 for (j = 0; j < n; j++) {
378 a = set[j];
379 for (i = 0; i < n; i++) {
380 if (a % 2) {
381 H[i * n + j] = 1;
382 }
383 else {
384 H[i * n + j] = -1;
385 }
386 a >>= 1;
387 }
388 }
389 cout << "The Hadamard matrix " << h << " is:" << endl;
390 Int_matrix_print(H, n, n);
391 for (i = 0; i < n; i++) {
392 for (j = 0; j < n; j++) {
393 a = H[i * n + j];
394 Ht[j * n + i] = a;
395 }
396 }
397
398 for (i = 0; i < n; i++) {
399 for (j = 0; j < n; j++) {
400 c = 0;
401 for (k = 0; k < n; k++) {
402 c += H[i * n + k] * Ht[k * n + j];
403 }
404 M[i * n + j] = c;
405 }
406 }
407 cout << "The matrix H * H^t is:" << endl;
408 Int_matrix_print(M, n, n);
409 }
410}
411
412int hadamard_classify::clique_test(long int *set, int sz)
413{
414 long int i, j, a, b, idx;
416
417 for (i = 0; i < n; i++) {
418 a = set[i];
419 for (j = i + 1; j < n; j++) {
420 b = set[j];
421 idx = Combi.ij2k_lint(a, b, N);
422 if (Bitvec->s_i(idx)) {
423 //cout << "pair (" << i << "," << j << ") vertices " << a << " and " << b << " are adjacent" << endl;
424 }
425 else {
426 //cout << "pair (" << i << "," << j << ") vertices " << a << " and " << b << " are NOT adjacent" << endl;
427 return FALSE;
428 }
429 }
430 }
431 return TRUE;
432}
433
434void hadamard_classify::early_test_func(long int *S, int len,
435 long int *candidates, int nb_candidates,
436 long int *good_candidates, int &nb_good_candidates,
437 int verbose_level)
438{
439 int f_v = (verbose_level >= 1);
440 //int f_vv = (verbose_level >= 2);
441 long int j, a, pt;
442
443 if (f_v) {
444 cout << "hadamard_classify::early_test_func checking set ";
445 Lint_vec_print(cout, S, len);
446 cout << endl;
447 cout << "candidate set of size " << nb_candidates << ":" << endl;
448 Lint_vec_print(cout, candidates, nb_candidates);
449 cout << endl;
450 }
451 if (len == 0) {
452 nb_good_candidates = nb_candidates;
453 Lint_vec_copy(candidates, good_candidates, nb_candidates);
454 return;
455 }
456
457 pt = S[len - 1];
458
459 nb_good_candidates = 0;
460 for (j = 0; j < nb_candidates; j++) {
461 a = candidates[j];
462
463 if (CG->is_adjacent(pt, a)) {
464 good_candidates[nb_good_candidates++] = a;
465 }
466 } // next j
467
468}
469
470
471int hadamard_classify::dot_product(int a, int b, int n)
472{
473 int i, c, aa, bb;
474
475 c = 0;
476 for (i = 0; i < n; i++) {
477 aa = a % 2;
478 bb = b % 2;
479 if (aa == bb) {
480 c++;
481 }
482 else {
483 c--;
484 }
485 a >>= 1;
486 b >>= 1;
487 }
488 return c;
489}
490
491void hadamard_classify_early_test_function(long int *S, int len,
492 long int *candidates, int nb_candidates,
493 long int *good_candidates, int &nb_good_candidates,
494 void *data, int verbose_level)
495{
497 int f_v = (verbose_level >= 1);
498
499 if (f_v) {
500 cout << "early_test_function for set ";
501 Lint_vec_print(cout, S, len);
502 cout << endl;
503 }
504 H->early_test_func(S, len,
505 candidates, nb_candidates,
506 good_candidates, nb_good_candidates,
507 verbose_level - 2);
508 if (f_v) {
509 cout << "early_test_function done" << endl;
510 }
511}
512
513
514
515}}}
516
517
518
compact storage of 0/1-data as bitvectors
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
void draw(std::string &fname, graphics::layered_graph_draw_options *Draw_options, int verbose_level)
void save(std::string &fname, int verbose_level)
void export_to_magma(std::string &fname, int verbose_level)
void init(int nb_points, int nb_colors, int nb_colors_per_vertex, int *colors, data_structures::bitvector *Bitvec, int f_ownership_of_bitvec, std::string &label, std::string &label_tex, int verbose_level)
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
groups::strong_generators * Strong_gens
Definition: actions.h:130
void group_order(ring_theory::longinteger_object &go)
Definition: action.cpp:2223
Interface to the graph canonization software Nauty.
Definition: actions.h:1154
action * create_automorphism_group_of_graph_bitvec(int n, data_structures::bitvector *Bitvec, int verbose_level)
void export_permutation_group_to_magma(std::string &fname, actions::action *A2, int verbose_level)
to control the behavior of the poset classification algorithm
void compute_orbits_on_subsets(int target_depth, poset_classification_control *PC_control, poset_with_group_action *Poset, int verbose_level)
void init_subset_lattice(actions::action *A, actions::action *A2, groups::strong_generators *Strong_gens, int verbose_level)
void add_testing_without_group(void(*func)(long int *S, int len, long int *candidates, int nb_candidates, long int *good_candidates, int &nb_good_candidates, void *data, int verbose_level), void *data, int verbose_level)
void init(int n, int f_draw, int verbose_level, int verbose_level_clique)
void early_test_func(long int *S, int len, long int *candidates, int nb_candidates, long int *good_candidates, int &nb_good_candidates, int verbose_level)
#define Lint_vec_copy(A, B, C)
Definition: foundations.h:694
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define Lint_vec_print(A, B, C)
Definition: foundations.h:686
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define Int_matrix_print(A, B, C)
Definition: foundations.h:707
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define NEW_lint(n)
Definition: foundations.h:628
orbiter_kernel_system::orbiter_session * Orbiter
global Orbiter session
the orbiter library for the classification of combinatorial objects