Orbiter 2022
Combinatorial Objects
boolean_function_domain.cpp
Go to the documentation of this file.
1/*
2 * boolean_function_domain.cpp
3 *
4 * Created on: Nov 7, 2020
5 * Author: betten
6 */
7
8
9
10#include "foundations.h"
11
12using namespace std;
13
14
15namespace orbiter {
16namespace layer1_foundations {
17namespace combinatorics {
18
19
21{
22 n = n2 = Q = bent = near_bent = 0;
23 NN = NULL;
24 N = 0;
25 Fq = NULL;
26 //FQ = NULL;
27 Poly = NULL;
28 A_poly = NULL;
29 B_poly = NULL;
30 Kernel = NULL;
31 dim_kernel = 0;
32 affine_points = NULL;
33 v = v1 = w = f = f2 = F = T = W = f_proj = f_proj2 = NULL;
34}
35
37{
38 int degree;
39
40 if (NN) {
42 }
43 if (Fq) {
45 }
46#if 0
47 if (FQ) {
48 FREE_OBJECT(FQ);
49 }
50#endif
51 if (Poly) {
53 }
54 if (A_poly) {
55 for (degree = 1; degree <= n; degree++) {
56 FREE_int(A_poly[degree]);
57 FREE_int(B_poly[degree]);
58 }
61 }
62 if (Kernel) {
64 }
65 if (affine_points) {
67 }
68 if (v) {
69 FREE_int(v);
70 }
71 if (v1) {
72 FREE_int(v1);
73 }
74 if (w) {
75 FREE_int(w);
76 }
77 if (f) {
78 FREE_int(f);
79 }
80 if (f2) {
81 FREE_int(f2);
82 }
83 if (F) {
84 FREE_int(F);
85 }
86 if (T) {
87 FREE_int(T);
88 }
89 if (W) {
90 FREE_int(W);
91 }
92 if (f_proj) {
94 }
95 if (f_proj2) {
97 }
98}
99
100void boolean_function_domain::init(int n, int verbose_level)
101{
102 int f_v = (verbose_level >= 1);
106
107 if (f_v) {
108 cout << "boolean_function_domain::init" << endl;
109 }
110
111 if (f_v) {
112 cout << "do_it n=" << n << endl;
113 }
114#if 0
115 if (ODD(n)) {
116 cout << "n must be even" << endl;
117 exit(1);
118 }
119#endif
121 n2 = n >> 1;
122 Q = 1 << n;
123 bent = 1 << (n2);
124 near_bent = 1 << ((n + 1) >> 1);
125 //NN = 1 << Q;
127 NN->create(2, __FILE__, __LINE__);
128 D.power_int(*NN, Q - 1);
129 N = Gg.nb_PG_elements(n, 2);
130 if (f_v) {
131 cout << "boolean_function_domain::init n=" << n << endl;
132 cout << "boolean_function_domain::init n2=" << n2 << endl;
133 cout << "boolean_function_domain::init Q=" << Q << endl;
134 cout << "boolean_function_domain::init bent=" << bent << endl;
135 cout << "boolean_function_domain::init near_bent=" << near_bent << endl;
136 cout << "boolean_function_domain::init NN=" << *NN << endl;
137 cout << "boolean_function_domain::init N=" << N << endl;
138 }
139
141 Fq->finite_field_init(2, FALSE /* f_without_tables */, 0);
142
143 //FQ = NEW_OBJECT(finite_field);
144 //FQ->finite_field_init(Q, 0);
145
147
148 v = NEW_int(n);
149 v1 = NEW_int(n);
150 w = NEW_int(n);
151 f = NEW_int(Q);
152 f2 = NEW_int(Q);
153 F = NEW_int(Q);
154 T = NEW_int(Q);
155 //W = NEW_int(Q * Q);
156 f_proj = NEW_int(N);
157 f_proj2 = NEW_int(N);
158
159 int i;
160 long int a;
161
162 for (i = 0; i < Q; i++) {
163 Gg.AG_element_unrank(2, v1, 1, n, i);
164 v1[n] = 1;
166 affine_points[i] = a;
167 }
168 if (FALSE) {
169 cout << "affine_points" << endl;
170 for (i = 0; i < Q; i++) {
171 Gg.AG_element_unrank(2, v1, 1, n, i);
172 cout << i << " : " << affine_points[i] << " : ";
173 Int_vec_print(cout, v1, n);
174 cout << endl;
175 }
176 }
177
178 // setup the Walsh matrix:
179
180 if (f_v) {
181 cout << "boolean_function_domain::init before Gg.Walsh_matrix" << endl;
182 }
183 if (n <= 10) {
184 Algebra.Walsh_matrix(Fq, n, W, verbose_level);
185 }
186 else {
187 cout << "Walsh matrix is too big" << endl;
188 }
189 if (f_v) {
190 cout << "boolean_function_domain::init after Gg.Walsh_matrix" << endl;
191 }
192
193
194 if (f_v) {
195 cout << "boolean_function_domain::init before setup_polynomial_rings" << endl;
196 }
197 setup_polynomial_rings(verbose_level);
198 if (f_v) {
199 cout << "boolean_function_domain::init after setup_polynomial_rings" << endl;
200 }
201
202
203
204 if (f_v) {
205 cout << "boolean_function_domain::init done" << endl;
206 }
207}
208
210{
211 int f_v = (verbose_level >= 1);
212 int nb_vars;
213 int degree;
214
215 if (f_v) {
216 cout << "boolean_function_domain::setup_polynomial_rings" << endl;
217 }
218 nb_vars = n + 1;
219 // We need one more variable to capture the constants
220 // So, we are really making homogeneous polynomials
221 // for projective space PG(n,2) with n+1 variables.
222
224
225 A_poly = NEW_pint(n + 1);
226 B_poly = NEW_pint(n + 1);
227 for (degree = 1; degree <= n; degree++) {
228 if (f_v) {
229 cout << "boolean_function_domain::setup_polynomial_rings "
230 "setting up polynomial ring of degree " << degree << endl;
231 }
232 Poly[degree].init(Fq, nb_vars, degree,
233 FALSE /* f_init_incidence_structure */,
234 t_PART,
235 0 /* verbose_level */);
236 A_poly[degree] = NEW_int(Poly[degree].get_nb_monomials());
237 B_poly[degree] = NEW_int(Poly[degree].get_nb_monomials());
238 }
239
240 if (f_v) {
241 cout << "boolean_function_domain::setup_polynomial_rings "
242 "before Poly[n].affine_evaluation_kernel" << endl;
243 }
245 Kernel, dim_kernel, verbose_level);
246 if (f_v) {
247 cout << "boolean_function_domain::setup_polynomial_rings "
248 "after Poly[n].affine_evaluation_kernel" << endl;
249 }
250
251 if (FALSE) {
252 cout << "Kernel of evaluation map:" << endl;
254 }
255
256 if (f_v) {
257 cout << "boolean_function_domain::setup_polynomial_rings done" << endl;
258 }
259}
260
262 int *func, int *coeff, int verbose_level)
263{
264 int f_v = (verbose_level >= 1);
265 int f_vv = (verbose_level >= 2);
267 int s, i, u, v, a, b, c, h, idx;
268 int N;
269 int degree = n + 1;
270 int *vec;
271 int *mon;
272
273 if (f_v) {
274 cout << "boolean_function_domain::compute_polynomial_representation" << endl;
275 }
276 N = 1 << n;
277 if (f_v) {
278 cout << "func=" << endl;
279 for (s = 0; s < N; s++) {
280 cout << s << " : " << func[s] << endl;
281 }
282 cout << "Poly[n].nb_monomials=" << Poly[n].get_nb_monomials() << endl;
283 }
284 vec = NEW_int(n);
285 mon = NEW_int(degree);
286 Int_vec_zero(coeff, Poly[n].get_nb_monomials());
287 if (f_v) {
288 cout << "boolean_function_domain::compute_polynomial_representation "
289 "looping over all values, N=" << N << endl;
290 }
291 for (s = 0; s < N; s++) {
292
293 // we are making the complement of the function,
294 // so we are skipping all entries which are zero!
295
296 if (f_v) {
297 cout << "boolean_function_domain::compute_polynomial_representation "
298 "s=" << s << " / " << N << endl;
299 }
300
301 if (func[s]) {
302 continue;
303 }
304
305 if (f_vv) {
306 cout << "the function value at s=" << s << " is " << func[s] << endl;
307 cout << "func=" << endl;
308 for (h = 0; h < N; h++) {
309 cout << h << " : " << func[h] << endl;
310 }
311 }
312 Gg.AG_element_unrank(2, vec, 1, n, s);
313
314
315 // create the polynomial
316 // \prod_{i=0}^{n-1} (x_i+(vec[i]+1)*x_n)
317 // which is one exactly if x_i = vec[i] for i=0..n-1 and x_n = 1.
318 // and zero otherwise.
319 // So this polynomial agrees with the boolean function
320 // on the affine space x_n = 1.
321
322 for (i = 0; i < n; i++) {
323
324
325 if (f_vv) {
326 cout << "s=" << s << " i=" << i << endl;
327 }
328
329 // create the polynomial (x_i+(vec[i]+1)*x_n)
330 // note that x_n stands for the constants
331 // because we are in affine space
332 Int_vec_zero(A_poly[1], Poly[1].get_nb_monomials());
333 A_poly[1][n] = Fq->add(1, vec[i]);
334 A_poly[1][i] = 1;
335
336 if (f_v) {
337 cout << "created the polynomial ";
338 Poly[1].print_equation(cout, A_poly[1]);
339 cout << endl;
340 }
341
342
343 if (i == 0) {
344 Int_vec_copy(A_poly[1], B_poly[1], Poly[1].get_nb_monomials());
345 }
346 else {
347 // B_poly[i + 1] = A_poly[1] * B_poly[i]
348 Int_vec_zero(B_poly[i + 1], Poly[i + 1].get_nb_monomials());
349 for (u = 0; u < Poly[1].get_nb_monomials(); u++) {
350 a = A_poly[1][u];
351 if (a == 0) {
352 continue;
353 }
354 for (v = 0; v < Poly[i].get_nb_monomials(); v++) {
355 b = B_poly[i][v];
356 if (b == 0) {
357 continue;
358 }
359 c = Fq->mult(a, b);
360 Int_vec_zero(mon, n + 1);
361 for (h = 0; h <= n + 1; h++) {
362 mon[h] = Poly[1].get_monomial(u, h) +
363 Poly[i].get_monomial(v, h);
364 }
365 idx = Poly[i + 1].index_of_monomial(mon);
366 B_poly[i + 1][idx] = Fq->add(B_poly[i + 1][idx], c);
367 } // next v
368 } // next u
369 } // else
370 } // next i
371 if (f_v) {
372 cout << "s=" << s << " / " << N << " : ";
373 Poly[n].print_equation(cout, B_poly[n]);
374 cout << endl;
375 }
376 for (h = 0; h < Poly[n].get_nb_monomials(); h++) {
377 coeff[h] = Fq->add(coeff[h], B_poly[n][h]);
378 }
379 } // next s
380 if (f_v) {
381 cout << "boolean_function_domain::compute_polynomial_representation "
382 "looping over all values done" << endl;
383 }
384
385 if (f_v) {
386 cout << "preliminary result : ";
387 Poly[n].print_equation(cout, coeff);
388 cout << endl;
389
390 int *f;
391 int f_error = FALSE;
392
393 f = NEW_int(Q);
394 evaluate(coeff, f);
395
396 for (h = 0; h < Q; h++) {
397 cout << h << " : " << func[h] << " : " << f[h];
398#if 0
399 if (func[h] == f[h]) {
400 cout << "error";
401 f_error = TRUE;
402 }
403#endif
404 cout << endl;
405 }
406 if (f_error) {
407 cout << "an error has occurred" << endl;
408 exit(1);
409 }
410 FREE_int(f);
411 }
412
413 Int_vec_zero(mon, n + 1);
414 mon[n] = n;
415 idx = Poly[n].index_of_monomial(mon);
416 coeff[idx] = Fq->add(coeff[idx], 1);
417
418 if (f_v) {
419 cout << "result : ";
420 Poly[n].print_equation(cout, coeff);
421 cout << endl;
422
423
424 int *f;
425 int f_error = FALSE;
426
427 f = NEW_int(Q);
428 evaluate(coeff, f);
429
430 for (h = 0; h < Q; h++) {
431 cout << h << " : " << func[h] << " : " << f[h];
432 if (func[h] != f[h]) {
433 cout << "error";
434 f_error = TRUE;
435 }
436 cout << endl;
437 }
438 if (f_error) {
439 cout << "an error has occurred" << endl;
440 exit(1);
441 }
442 FREE_int(f);
443
444
445 }
446
447 FREE_int(vec);
448 FREE_int(mon);
449
450 if (f_v) {
451 cout << "boolean_function_domain::compute_polynomial_representation done" << endl;
452 }
453}
454
456{
457 int i;
458
459 for (i = 0; i < N; i++) {
460 f[i] = Poly[n].evaluate_at_a_point_by_rank(coeff, i);
461 }
462
463}
464
465void boolean_function_domain::evaluate(int *coeff, int *f)
466{
467 int i;
469
470 for (i = 0; i < Q; i++) {
471 Gg.AG_element_unrank(2, v1, 1, n, i);
472 v1[n] = 1;
473 f[i] = Poly[n].evaluate_at_a_point(coeff, v1);
474 }
475
476}
477
478void boolean_function_domain::raise(int *in, int *out)
479{
480 int i;
481
482 for (i = 0; i < Q; i++) {
483 if (in[i]) {
484 out[i] = -1;
485 }
486 else {
487 out[i] = 1;
488 }
489 }
490}
491
493{
494 int i, j;
495
496 Int_vec_zero(out, Q);
497 for (i = 0; i < Q; i++) {
498 for (j = 0; j < Q; j++) {
499 out[i] += W[i * Q + j] * in[j];
500 }
501 }
502}
503
505{
506 int i;
507
508 for (i = 0; i < Q; i++) {
509 if (ABS(T[i]) != bent) {
510 //cout << "ABS(T[i]) != bent, T[i] = " << T[i] << " bent=" << bent << endl;
511 break;
512 }
513 }
514 if (i == Q) {
515 return TRUE;
516 }
517 else {
518 return FALSE;
519 }
520}
521
523{
524 int i;
525
526 for (i = 0; i < Q; i++) {
527 if (T[i] == 0) {
528 continue;
529 }
530 if (ABS(T[i]) != near_bent) {
531 //cout << "ABS(T[i]) != near_bent, T[i] = " << T[i] << " near_bent=" << near_bent << endl;
532 break;
533 }
534 }
535 if (i == Q) {
536 return TRUE;
537 }
538 else {
539 return FALSE;
540 }
541}
542
543
544
545}}}
546
547
548
global functions related to finite fields, irreducible polynomials and such
Definition: algebra.h:130
void Walsh_matrix(field_theory::finite_field *F, int n, int *&W, int verbose_level)
ring_theory::homogeneous_polynomial_domain * Poly
Definition: combinatorics.h:43
void compute_polynomial_representation(int *func, int *coeff, int verbose_level)
void finite_field_init(int q, int f_without_tables, int verbose_level)
void PG_element_rank_modified_lint(int *v, int stride, int len, long int &a)
various functions related to geometries
Definition: geometry.h:721
void AG_element_unrank(int q, int *v, int stride, int len, long int a)
homogeneous polynomials of a given degree in a given number of variables over a finite field GF(q)
Definition: ring_theory.h:88
void init(field_theory::finite_field *F, int nb_vars, int degree, int f_init_incidence_structure, monomial_ordering_type Monomial_ordering_type, int verbose_level)
void affine_evaluation_kernel(int *&Kernel, int &dim_kernel, int verbose_level)
domain to compute with objects of type longinteger
Definition: ring_theory.h:240
a class to represent arbitrary precision integers
Definition: ring_theory.h:366
void create(long int i, const char *file, int line)
#define FREE_OBJECTS(p)
Definition: foundations.h:652
#define FREE_int(p)
Definition: foundations.h:640
#define Int_vec_zero(A, B)
Definition: foundations.h:713
#define NEW_pint(n)
Definition: foundations.h:627
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define NEW_int(n)
Definition: foundations.h:625
#define ABS(x)
Definition: foundations.h:220
#define Int_matrix_print(A, B, C)
Definition: foundations.h:707
#define NEW_OBJECTS(type, n)
Definition: foundations.h:639
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define ODD(x)
Definition: foundations.h:222
#define Int_vec_copy(A, B, C)
Definition: foundations.h:693
#define FREE_lint(p)
Definition: foundations.h:642
#define NEW_lint(n)
Definition: foundations.h:628
#define FREE_pint(p)
Definition: foundations.h:641
#define Int_vec_print(A, B, C)
Definition: foundations.h:685
the orbiter library for the classification of combinatorial objects