Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 19204
1
r"""
2
Classification of bent functions by their Cayley graphs
3
=======================================================
4
5
The ``bent_function_cayley_graph_classification`` module defines:
6
7
* the ``BentFunctionCayleyGraphClassification`` class;
8
which represents the classification of the Cayley graphs
9
within the extended translation class of a bent function; and
10
* the ``BentFunctionCayleyGraphClassPart`` class,
11
which represents part of a Cayley graph classification.
12
13
AUTHORS:
14
15
- Paul Leopardi (2016-08-02): initial version
16
17
EXAMPLES:
18
19
::
20
21
The classification of the bent function defined by the polynomial x2 + x1*x2.
22
23
sage: from boolean_cayley_graphs.bent_function import BentFunction
24
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
25
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
26
sage: p = x2+x1*x2
27
sage: f = BentFunction(p)
28
sage: c = BentFunctionCGC.from_function(f)
29
sage: dict(sorted(c.__dict__.items()))
30
{'algebraic_normal_form': x0*x1 + x1,
31
'bent_cayley_graph_index_matrix': [0 0 1 0]
32
[1 0 0 0]
33
[0 0 0 1]
34
[0 1 0 0],
35
'cayley_graph_class_list': ['CK', 'C~'],
36
'dual_cayley_graph_index_matrix': [0 0 1 0]
37
[1 0 0 0]
38
[0 0 0 1]
39
[0 1 0 0],
40
'weight_class_matrix': [0 0 1 0]
41
[1 0 0 0]
42
[0 0 0 1]
43
[0 1 0 0]}
44
45
REFERENCES:
46
47
The extended translation equivalence class and the extended Cayley equivalence class
48
of a bent function are defined by Leopardi [Leo2017]_.
49
"""
50
#*****************************************************************************
51
# Copyright (C) 2016-2017 Paul Leopardi [email protected]
52
#
53
# Distributed under the terms of the GNU General Public License (GPL)
54
# as published by the Free Software Foundation; either version 2 of
55
# the License, or (at your option) any later version.
56
# http://www.gnu.org/licenses/
57
#*****************************************************************************
58
59
60
from datetime import datetime
61
from numpy import array, argwhere
62
from sage.coding.linear_code import LinearCode
63
from sage.combinat.designs.incidence_structures import IncidenceStructure
64
from sage.functions.log import log
65
from sage.graphs.graph import Graph
66
from sage.graphs.strongly_regular_db import strongly_regular_from_two_weight_code
67
from sage.matrix.constructor import matrix
68
from sage.misc.latex import latex
69
from sage.misc.persist import load
70
from sage.plot.matrix_plot import matrix_plot
71
from sage.rings.integer import Integer
72
from sage.structure.sage_object import SageObject
73
from sys import stdout
74
75
import glob
76
import numpy as np
77
78
from boolean_cayley_graphs.bent_function import BentFunction
79
from boolean_cayley_graphs.binary_projective_two_weight_codes import binary_projective_two_weight_27_6_12
80
from boolean_cayley_graphs.binary_projective_two_weight_codes import binary_projective_two_weight_35_6_16
81
from boolean_cayley_graphs.boolean_cayley_graph import boolean_cayley_graph
82
from boolean_cayley_graphs.boolean_linear_code import linear_code_from_code_gens
83
from boolean_cayley_graphs.boolean_linear_code import print_latex_code_parameters
84
from boolean_cayley_graphs.boolean_linear_code_graph import boolean_linear_code_graph
85
from boolean_cayley_graphs.containers import BijectiveList
86
from boolean_cayley_graphs.containers import ShelveBijectiveList
87
from boolean_cayley_graphs.saveable import Saveable
88
from boolean_cayley_graphs.strongly_regular_graph import StronglyRegularGraph
89
from boolean_cayley_graphs.weight_class import weight_class
90
91
import boolean_cayley_graphs.cayley_graph_controls as controls
92
import csv
93
import os.path
94
95
default_algorithm = "sage"
96
97
98
class BentFunctionCayleyGraphClassPart(SageObject, Saveable):
99
r"""
100
Partial classification of the Cayley graphs within the
101
extended translation equivalence class of a bent function.
102
103
EXAMPLES:
104
105
::
106
107
sage: from boolean_cayley_graphs.bent_function import BentFunction
108
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
109
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
110
sage: p = x1+x2+x1*x2
111
sage: f = BentFunction(p)
112
sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
113
sage: print(c1)
114
BentFunctionCayleyGraphClassPart.from_function(BentFunction(x0*x1 + x0 + x1, c_start=0, c_stop=1))
115
sage: latex(c1)
116
\text{\texttt{BentFunctionCayleyGraphClassPart.from{\char`\_}function(BentFunction(x0*x1{ }+{ }x0{ }+{ }x1,{ }c{\char`\_}start=0,{ }c{\char`\_}stop=1))}}
117
118
"""
119
120
def __init__(self, *args, **kwargs):
121
r"""
122
Constructor from an object or from class attributes.
123
124
INPUT:
125
126
- ``algebraic_normal_form`` -- a polynomial of the type
127
returned by ``BooleanFunction.algebraic_normal_form()``,
128
representing the ``BentFunction`` whose classification this is.
129
- ``cayley_graph_class_list`` -- a list of ``graph6_string`` strings
130
corresponding to the complete set of non-isomorphic Cayley graphs of
131
the bent functions within the extended translation equivalence class
132
of the ``BentFunction`` represented by ``algebraic_normal_form``,
133
and their duals, if ``dual_cayley_graph_index_matrix`` is not ``None``,
134
- ``bent_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
135
which are indices into ``cayley_graph_class_list`` representing the
136
correspondence between bent functions and their Cayley graphs.
137
- ``dual_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
138
which are indices into ``cayley_graph_class_list`` representing the
139
correspondence between dual bent functions and their Cayley graphs.
140
- ``weight_class_matrix`` -- a ``Matrix` of integers with value 0 or 1
141
corresponding to the weight class of each bent function.
142
- ``c_start`` -- an integer representing the Boolean vector
143
corresponding to the first row of each matrix.
144
145
OUTPUT:
146
147
None.
148
149
EFFECT:
150
151
The current object ``self`` is initialized as follows.
152
153
Each of
154
- ``algebraic_normal_form``
155
- ``cayley_graph_class_list``
156
- ``bent_cayley_graph_index_matrix``
157
- ``dual_cayley_graph_index_matrix``
158
- ``weight_class_matrix``
159
- ``c_start``
160
is set to the corresponding input parameter.
161
162
EXAMPLES:
163
164
The partial classification of the bent function defined by the polynomial
165
:math:`x_1 + x_2 + x_1 x_2` is copied from `c1` to `c2`.
166
167
::
168
169
sage: from boolean_cayley_graphs.bent_function import BentFunction
170
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
171
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
172
sage: p = x1+x2+x1*x2
173
sage: f = BentFunction(p)
174
sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
175
sage: c2 = BentFunctionCGCP(c1)
176
sage: print(c1 == c2)
177
True
178
"""
179
try:
180
sobj = args[0]
181
self.algebraic_normal_form=sobj.algebraic_normal_form
182
self.cayley_graph_class_list=sobj.cayley_graph_class_list
183
self.bent_cayley_graph_index_matrix=sobj.bent_cayley_graph_index_matrix
184
self.dual_cayley_graph_index_matrix=sobj.dual_cayley_graph_index_matrix
185
self.weight_class_matrix=sobj.weight_class_matrix
186
self.c_start=sobj.c_start
187
except:
188
self.algebraic_normal_form = kwargs.pop(
189
'algebraic_normal_form')
190
self.cayley_graph_class_list = kwargs.pop(
191
'cayley_graph_class_list')
192
self.bent_cayley_graph_index_matrix = kwargs.pop(
193
'bent_cayley_graph_index_matrix')
194
self.dual_cayley_graph_index_matrix = kwargs.pop(
195
'dual_cayley_graph_index_matrix', None)
196
self.weight_class_matrix = kwargs.pop(
197
'weight_class_matrix')
198
self.c_start = kwargs.pop(
199
'c_start')
200
201
202
def _repr_(self):
203
r"""
204
Sage string representation.
205
206
INPUT:
207
208
- ``self`` -- the current object.
209
210
EXAMPLES:
211
212
::
213
214
sage: from boolean_cayley_graphs.bent_function import BentFunction
215
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
216
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
217
sage: p = x1+x2+x1*x2
218
sage: f = BentFunction(p)
219
sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
220
sage: print(c1)
221
BentFunctionCayleyGraphClassPart.from_function(BentFunction(x0*x1 + x0 + x1, c_start=0, c_stop=1))
222
"""
223
c_stop = self.c_start + self.weight_class_matrix.nrows()
224
return (
225
type(self).__name__ +
226
".from_function(BentFunction(" +
227
repr(self.algebraic_normal_form) +
228
", c_start=" +
229
repr(self.c_start) +
230
", c_stop=" +
231
repr(c_stop) +
232
"))")
233
234
235
@classmethod
236
def from_function(
237
cls,
238
bentf,
239
list_dual_graphs=True,
240
c_start=0,
241
c_stop=None,
242
limited_memory=False,
243
algorithm=default_algorithm):
244
r"""
245
Constructor from the ``BentFunction`` ``bentf``.
246
247
INPUT:
248
249
- ``bentf`` -- an object of class ``BentFunction``.
250
- ``list_dual_graphs`` -- boolean (default: ``True``).
251
A flag indicating whether to list dual graphs.
252
- ``c_start`` -- integer (default: 0).
253
The smallest value of `c` to use for extended translates.
254
- ``c_stop`` -- integer (default: ``None``).
255
One more than largest value of `c` to use for extended
256
translates. ``None`` means use all remaining values.
257
- ``limited_memory`` -- boolean (default: ``False``).
258
A flag indicating whether the classification might be
259
too large to fit into memory.
260
- ``algorithm`` -- string (default: ``default_algorithm``).
261
The algorithm used for canonical labelling.
262
263
OUTPUT:
264
265
An object of class BentFunctionCayleyGraphClassPart,
266
initialized as follows.
267
268
- ``algebraic_normal_form`` is set to ``bentf.algebraic_normal_form()``,
269
- ``cayley_graph_class_list`` is set to a list of ``graph6_string`` stings
270
corresponding to the complete set of non-isomorphic Cayley graphs
271
of the bent functions within the extended translation equivalence
272
class of ``bentf`` (and their duals, if ``list_dual_graphs`` is ``True``),
273
- ``bent_cayley_graph_index_matrix`` is set to a matrix of indices
274
into ``cayley_graph_class_list`` corresponding to these bent functions,
275
- ``dual_cayley_graph_index_matrix`` is set to ``None``
276
if ``list_dual_graphs`` is ``False``, otherwise it is set to
277
a matrix of indices into ``cayley_graph_class_list`` corresponding
278
to the duals of these bent functions, and
279
- ``weight_class_matrix`` is set to the 0-1 matrix of weight classes
280
corresponding to ``bent_cayley_graph_index_matrix``,
281
- ``c_start`` is set to smallest value of `c` used for extended translates.
282
283
Each entry ``bent_cayley_graph_index_matrix[c-c_start,b]`` corresponds to
284
the Cayley graph of the bent function
285
:math:`x \mapsto \mathtt{bentf}(x+b) + \langle c, x \rangle + \mathtt{bentf}(b)`.
286
This enumerates all of the extended translates of ``bentf`` having ``c``
287
from ``c_start`` to but not including ``c_stop``.
288
289
EXAMPLES:
290
291
A partial classification of the bent function defined by the polynomial
292
:math:`x_1 + x_2 + x_1 x_2`.
293
294
::
295
296
sage: from boolean_cayley_graphs.bent_function import BentFunction
297
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCPart
298
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
299
sage: p = x1+x2+x1*x2
300
sage: f = BentFunction(p)
301
sage: c1 = BentFunctionCGCPart.from_function(f,c_start=2,c_stop=4)
302
sage: dict(sorted(c1.__dict__.items()))
303
{'algebraic_normal_form': x0*x1 + x0 + x1,
304
'bent_cayley_graph_index_matrix': [0 1 0 0]
305
[0 0 0 1],
306
'c_start': 2,
307
'cayley_graph_class_list': ['CK', 'C~'],
308
'dual_cayley_graph_index_matrix': [0 1 0 0]
309
[0 0 0 1],
310
'weight_class_matrix': [0 1 0 0]
311
[0 0 0 1]}
312
313
A partial classification of the bent function defined by the polynomial
314
:math:`x_1 + x_2 + x_1 x_2`, but with list_dual_graphs=False.
315
316
::
317
318
sage: from boolean_cayley_graphs.bent_function import BentFunction
319
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
320
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
321
sage: p = x1+x2+x1*x2
322
sage: f = BentFunction(p)
323
sage: c2 = BentFunctionCGCPart.from_function(f,list_dual_graphs=False,c_start=0,c_stop=2)
324
sage: dict(sorted(c2.__dict__.items()))
325
{'algebraic_normal_form': x0*x1 + x0 + x1,
326
'bent_cayley_graph_index_matrix': [0 1 1 1]
327
[1 1 0 1],
328
'c_start': 0,
329
'cayley_graph_class_list': ['C~', 'CK'],
330
'dual_cayley_graph_index_matrix': None,
331
'weight_class_matrix': [1 0 0 0]
332
[0 0 1 0]}
333
"""
334
checking = controls.checking
335
timing = controls.timing
336
337
dim = bentf.nvariables()
338
v = 2 ** dim
339
c_start
340
if c_stop == None:
341
c_stop = v
342
else:
343
c_stop = min(c_stop, v)
344
algebraic_normal_form = bentf.algebraic_normal_form()
345
346
cayley_graph_class_bijection = (
347
ShelveBijectiveList()
348
if dim > 8 or (dim == 8 and limited_memory) else
349
BijectiveList())
350
351
c_len = c_stop - c_start
352
bent_cayley_graph_index_matrix = matrix(c_len, v)
353
if list_dual_graphs:
354
dual_cayley_graph_index_matrix = matrix(c_len, v)
355
else:
356
dual_cayley_graph_index_matrix = None
357
weight_class_matrix = matrix(c_len, v)
358
359
f = bentf.extended_translate()
360
dual_bentf = bentf.walsh_hadamard_dual()
361
dual_f = dual_bentf.extended_translate()
362
363
for b in range(v):
364
if timing:
365
print(datetime.now(), b, end=' ')
366
print(len(cayley_graph_class_bijection))
367
stdout.flush()
368
369
fb = f(b)
370
for c in range(c_start, c_stop):
371
fbc = bentf.extended_translate(b, c, fb)
372
cg = boolean_cayley_graph(dim, fbc).canonical_label(algorithm=algorithm)
373
cg_index = cayley_graph_class_bijection.index_append(cg.graph6_string())
374
bent_cayley_graph_index_matrix[c - c_start, b] = cg_index
375
376
weight = sum(fbc(x) for x in range(v))
377
wc = weight_class(v, weight)
378
weight_class_matrix[c - c_start, b] = wc
379
380
if checking:
381
if wc != 0 and wc != 1:
382
raise ValueError(
383
"Weight class is "
384
+ str(wc))
385
if list_dual_graphs:
386
bentfbc = BentFunction([fbc(x) for x in range(v)])
387
388
dual_fbc = bentfbc.walsh_hadamard_dual().extended_translate(d=wc)
389
dg = boolean_cayley_graph(dim, dual_fbc).canonical_label(algorithm=algorithm)
390
dg_index = cayley_graph_class_bijection.index_append(dg.graph6_string())
391
dual_cayley_graph_index_matrix[c - c_start, b] = dg_index
392
393
if checking and dim > 2:
394
blcg = boolean_linear_code_graph(dim, fbc)
395
lg = (
396
blcg.canonical_label(algorithm=algorithm)
397
if wc == 0 else
398
blcg.complement().canonical_label(algorithm=algorithm))
399
if lg != dg:
400
raise ValueError(
401
"Cayley graph of dual does not match"
402
+ "graph from linear code at "
403
+ str(b) + ","
404
+ str(c))
405
cayley_graph_class_bijection.sync()
406
407
# Retain the list part of cayley_graph_class_bijection, and
408
# close and remove the dict part.
409
cayley_graph_class_list = cayley_graph_class_bijection.get_list()
410
cayley_graph_class_bijection.close_dict()
411
cayley_graph_class_bijection.remove_dict()
412
413
if checking:
414
sdp_design_matrix = bentf.sdp_design_matrix()
415
if weight_class_matrix != sdp_design_matrix:
416
raise ValueError(
417
"weight_class_matrix != sdp_design_matrix"
418
+ "\n"
419
+ str(weight_class_matrix)
420
+ "\n"
421
+ str(sdp_design_matrix))
422
423
if timing:
424
print(datetime.now())
425
stdout.flush()
426
427
return cls(
428
algebraic_normal_form=algebraic_normal_form,
429
cayley_graph_class_list=cayley_graph_class_list,
430
bent_cayley_graph_index_matrix=bent_cayley_graph_index_matrix,
431
dual_cayley_graph_index_matrix=dual_cayley_graph_index_matrix,
432
weight_class_matrix=weight_class_matrix,
433
c_start=c_start)
434
435
436
def __eq__(self, other):
437
"""
438
Test for equality between partial classifications.
439
440
WARNING:
441
442
This test is for strict equality rather than mathematical equivalence.
443
444
INPUT:
445
446
- ``other`` - BentFunctionCayleyGraphClassPart: another partial classification.
447
448
OUTPUT:
449
450
A Boolean value indicating whether ``self`` strictly equals ``other``.
451
452
EXAMPLES:
453
454
::
455
456
sage: from boolean_cayley_graphs.bent_function import BentFunction
457
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
458
sage: R2.<x0,x1> = BooleanPolynomialRing(2)
459
sage: p = x0*x1
460
sage: f1 = BentFunction(p)
461
sage: c1 = BentFunctionCGCP.from_function(f1, c_stop=1)
462
sage: f2 = BentFunction([0,0,0,1])
463
sage: c2 = BentFunctionCGCP.from_function(f2, c_stop=1)
464
sage: print(c2.algebraic_normal_form)
465
x0*x1
466
sage: print(c1 == c2)
467
True
468
"""
469
if other is None:
470
return False
471
return (
472
self.algebraic_normal_form == other.algebraic_normal_form and
473
self.cayley_graph_class_list == other.cayley_graph_class_list and
474
self.bent_cayley_graph_index_matrix == other.bent_cayley_graph_index_matrix and
475
self.dual_cayley_graph_index_matrix == other.dual_cayley_graph_index_matrix and
476
self.weight_class_matrix == other.weight_class_matrix and
477
self.c_start == other.c_start)
478
479
480
class BentFunctionCayleyGraphClassification(BentFunctionCayleyGraphClassPart):
481
r"""
482
Classification of the Cayley graphs within the
483
extended translation equivalence class of a bent function.
484
485
EXAMPLES:
486
487
::
488
489
sage: from boolean_cayley_graphs.bent_function import BentFunction
490
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
491
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
492
sage: p = x1+x2+x1*x2
493
sage: f = BentFunction(p)
494
sage: c1 = BentFunctionCGC.from_function(f)
495
sage: print(c1)
496
BentFunctionCayleyGraphClassification.from_function(BentFunction(x0*x1 + x0 + x1))
497
sage: latex(c1)
498
\text{\texttt{BentFunctionCayleyGraphClassification.from{\char`\_}function(BentFunction(x0*x1{ }+{ }x0{ }+{ }x1))}}
499
"""
500
501
# Suffixes used by from_csv() and save_as_csv().
502
bent_function_csv_suffix = "_bent_function.csv"
503
cg_class_list_csv_suffix = "_cg_class_list.csv"
504
matrices_csv_suffix = "_matrices.csv"
505
506
507
def __init__(self, *args, **kwargs):
508
r"""
509
Constructor from an object or from class attributes.
510
511
INPUT:
512
513
- ``sobj`` -- BentFunctionCayleyGraphClassification: object to copy.
514
515
- ``algebraic_normal_form`` -- a polynomial of the type
516
returned by ``BooleanFunction.algebraic_normal_form()``,
517
representing the ``BentFunction`` whose classification this is.
518
- ``cayley_graph_class_list`` -- a list of ``graph6_string`` strings
519
corresponding to the complete set of non-isomorphic Cayley graphs of
520
the bent functions within the extended translation equivalence class
521
of the ``BentFunction`` represented by ``algebraic_normal_form``,
522
and their duals, if ``dual_cayley_graph_index_matrix`` is not ``None``,
523
- ``bent_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
524
which are indices into ``cayley_graph_class_list`` representing the
525
correspondence between bent functions and their Cayley graphs.
526
- ``dual_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
527
which are indices into ``cayley_graph_class_list`` representing the
528
correspondence between dual bent functions and their Cayley graphs.
529
- ``weight_class_matrix`` -- a ``Matrix` of integers with value 0 or 1
530
corresponding to the weight class of each bent function.
531
532
OUTPUT:
533
534
None.
535
536
EFFECT:
537
538
The current object ``self`` is initialized as follows.
539
540
Each of
541
- ``algebraic_normal_form``
542
- ``cayley_graph_class_list``
543
- ``bent_cayley_graph_index_matrix``
544
- ``dual_cayley_graph_index_matrix``
545
- ``weight_class_matrix``
546
is set to the corresponding input parameter.
547
548
EXAMPLES:
549
550
The classification of the bent function defined by the polynomial
551
:math:`x_1 + x_2 + x_1 x_2` is copied from `c1` to `c2`.
552
553
::
554
555
sage: from boolean_cayley_graphs.bent_function import BentFunction
556
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
557
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
558
sage: p = x1+x2+x1*x2
559
sage: f = BentFunction(p)
560
sage: c1 = BentFunctionCGC.from_function(f)
561
sage: c2 = BentFunctionCGC(c1)
562
sage: print(c1 == c2)
563
True
564
"""
565
try:
566
sobj = args[0]
567
self.algebraic_normal_form=sobj.algebraic_normal_form
568
self.cayley_graph_class_list=sobj.cayley_graph_class_list
569
self.bent_cayley_graph_index_matrix=sobj.bent_cayley_graph_index_matrix
570
self.dual_cayley_graph_index_matrix=sobj.dual_cayley_graph_index_matrix
571
self.weight_class_matrix=sobj.weight_class_matrix
572
except:
573
self.algebraic_normal_form = kwargs.pop(
574
'algebraic_normal_form')
575
self.cayley_graph_class_list = kwargs.pop(
576
'cayley_graph_class_list')
577
self.bent_cayley_graph_index_matrix = kwargs.pop(
578
'bent_cayley_graph_index_matrix')
579
self.dual_cayley_graph_index_matrix = kwargs.pop(
580
'dual_cayley_graph_index_matrix', None)
581
self.weight_class_matrix = kwargs.pop(
582
'weight_class_matrix')
583
584
585
def _repr_(self):
586
r"""
587
Sage string representation.
588
589
INPUT:
590
591
- ``self`` -- the current object.
592
593
EXAMPLES:
594
595
::
596
597
sage: from boolean_cayley_graphs.bent_function import BentFunction
598
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
599
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
600
sage: p = x1+x2+x1*x2
601
sage: f = BentFunction(p)
602
sage: c1 = BentFunctionCGC.from_function(f)
603
sage: print(c1)
604
BentFunctionCayleyGraphClassification.from_function(BentFunction(x0*x1 + x0 + x1))
605
"""
606
return (
607
type(self).__name__ +
608
".from_function(BentFunction(" +
609
repr(self.algebraic_normal_form) +
610
"))")
611
612
613
@classmethod
614
def cg_class_list_from_csv(
615
cls,
616
file_name):
617
"""
618
Read a Cayley graph class list from a csv file.
619
620
The csv file is assumed to be created by the method
621
save_cg_class_list_as_csv().
622
623
INPUT:
624
625
- ``file_name`` -- the name of the csv file.
626
627
OUTPUT:
628
629
A list of Cayley graphs in graph6_string format.
630
631
EXAMPLES:
632
633
::
634
635
sage: from boolean_cayley_graphs.bent_function import BentFunction
636
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
637
sage: import os
638
sage: bf2 = BentFunction([1,0,1,1])
639
sage: c2 = BentFunctionCGC.from_function(bf2)
640
sage: csv_name = tmp_filename(ext=".csv")
641
sage: c2.save_cg_class_list_as_csv(csv_name)
642
sage: cgcl_saved = BentFunctionCGC.cg_class_list_from_csv(csv_name)
643
sage: print(cgcl_saved == c2.cayley_graph_class_list)
644
True
645
sage: os.remove(csv_name)
646
647
"""
648
cg_list = []
649
with open(file_name) as csv_file:
650
reader = csv.DictReader(csv_file)
651
for row in reader:
652
cg_list.append(row["canonical_label"])
653
return cg_list
654
655
656
@classmethod
657
def matrices_from_csv(
658
cls,
659
dim,
660
file_name):
661
r"""
662
Read three matrices from a csv file.
663
664
The csv file is assumed to be created by the method
665
save_matrices_as_csv().
666
667
INPUT:
668
669
- ``dim`` -- integer: the dimension of the bent function.
670
- ``file_name`` -- the name of the csv file.
671
672
OUTPUT:
673
674
A tuple of matrices,
675
676
EXAMPLES:
677
678
::
679
680
sage: from boolean_cayley_graphs.bent_function import BentFunction
681
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
682
sage: import os
683
sage: bf2 = BentFunction([1,1,0,1])
684
sage: dim = bf2.nvariables()
685
sage: c2 = BentFunctionCGC.from_function(bf2)
686
sage: csv_name = tmp_filename(ext=".csv")
687
sage: c2.save_matrices_as_csv(csv_name)
688
sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
689
sage: print(c2.bent_cayley_graph_index_matrix == ci_matrix)
690
True
691
sage: print(c2.dual_cayley_graph_index_matrix == di_matrix)
692
True
693
sage: print(c2.weight_class_matrix == wc_matrix)
694
True
695
sage: os.remove(csv_name)
696
697
TESTS:
698
699
Test the case where list_dual_graphs==False and dual_cayley_graph_index_matrix is None.
700
701
::
702
703
sage: from boolean_cayley_graphs.bent_function import BentFunction
704
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
705
sage: import os
706
sage: bf = BentFunction([1,1,0,1])
707
sage: dim = bf.nvariables()
708
sage: c = BentFunctionCGC.from_function(bf, list_dual_graphs=False)
709
sage: csv_name = tmp_filename(ext=".csv")
710
sage: c.save_matrices_as_csv(csv_name)
711
sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
712
sage: print(c.bent_cayley_graph_index_matrix == ci_matrix)
713
True
714
sage: print(c.dual_cayley_graph_index_matrix == di_matrix)
715
True
716
sage: print(c.weight_class_matrix == wc_matrix)
717
True
718
sage: os.remove(csv_name)
719
"""
720
v = 2 ** dim
721
with open(file_name) as csv_file:
722
reader = csv.DictReader(csv_file)
723
fieldnames = reader.fieldnames
724
ci_matrix = matrix(v, v)
725
wc_matrix = matrix(v, v)
726
di_matrix = (
727
matrix(v, v)
728
if "dual_cayley_graph_index" in fieldnames
729
else
730
None)
731
for row in reader:
732
c = int(row["c"])
733
b = int(row["b"])
734
ci_matrix[c, b] = row["bent_cayley_graph_index"]
735
wc_matrix[c, b] = row["weight_class"]
736
if "dual_cayley_graph_index" in fieldnames:
737
di_matrix[c, b] = row["dual_cayley_graph_index"]
738
739
return (ci_matrix, di_matrix, wc_matrix)
740
741
742
@classmethod
743
def from_csv(
744
cls,
745
file_name_prefix):
746
r"""
747
Constructor from three csv files.
748
749
INPUT:
750
751
- ``file_name_prefix`` -- string: the common prefix to use for file names.
752
753
OUTPUT:
754
755
None.
756
757
EXAMPLES:
758
759
::
760
761
sage: from boolean_cayley_graphs.bent_function import BentFunction
762
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
763
sage: import os
764
sage: bf2 = BentFunction([1,1,0,1])
765
sage: c2 = BentFunctionCGC.from_function(bf2)
766
sage: prefix = tmp_filename()
767
sage: c2.save_as_csv(prefix)
768
sage: c2_saved = BentFunctionCGC.from_csv(prefix)
769
sage: print(c2 == c2_saved)
770
True
771
sage: bent_function_csv_name = prefix + BentFunctionCGC.bent_function_csv_suffix
772
sage: os.remove(bent_function_csv_name)
773
sage: cg_class_list_csv_name = prefix + BentFunctionCGC.cg_class_list_csv_suffix
774
sage: os.remove(cg_class_list_csv_name)
775
sage: matrices_csv_name = prefix + BentFunctionCGC.matrices_csv_suffix
776
sage: os.remove(matrices_csv_name)
777
778
"""
779
bentf = BentFunction.from_csv(
780
file_name_prefix + cls.bent_function_csv_suffix)
781
algebraic_normal_form = bentf.algebraic_normal_form()
782
cayley_graph_class_list = cls.cg_class_list_from_csv(
783
file_name_prefix + cls.cg_class_list_csv_suffix)
784
dim = bentf.nvariables()
785
(
786
bent_cayley_graph_index_matrix,
787
dual_cayley_graph_index_matrix,
788
weight_class_matrix) = cls.matrices_from_csv(
789
dim,
790
file_name_prefix + cls.matrices_csv_suffix)
791
792
return cls(
793
algebraic_normal_form=algebraic_normal_form,
794
cayley_graph_class_list=cayley_graph_class_list,
795
bent_cayley_graph_index_matrix=bent_cayley_graph_index_matrix,
796
dual_cayley_graph_index_matrix=dual_cayley_graph_index_matrix,
797
weight_class_matrix=weight_class_matrix)
798
799
800
@classmethod
801
def from_function(
802
cls,
803
bentf,
804
list_dual_graphs=True,
805
limited_memory=False):
806
r"""
807
Constructor from the ``BentFunction`` ``bentf``.
808
809
INPUT:
810
811
- ``bentf`` -- an object of class ``BentFunction``.
812
- ``list_dual_graphs`` -- boolean. a flag indicating
813
whether to list dual graphs.
814
- ``limited_memory`` -- boolean. A flag indicating
815
whether the classification might be too large
816
to fit into memory. Default is False.
817
818
OUTPUT:
819
820
An object of class BentFunctionCayleyGraphClassification,
821
initialized as follows.
822
823
- ``algebraic_normal_form`` is set to ``bentf.algebraic_normal_form()``,
824
- ``cayley_graph_class_list`` is set to a list of ``graph6_string``
825
strings corresponding to the complete set of non-isomorphic Cayley graphs
826
of the bent functions within the extended translation equivalence
827
class of ``bentf`` (and their duals, if ``list_dual_graphs`` is ``True``),
828
- ``bent_cayley_graph_index_matrix`` is set to a matrix of indices
829
into ``cayley_graph_class_list`` corresponding to these bent functions,
830
- ``dual_cayley_graph_index_matrix`` is set to ``None``
831
if ``list_dual_graphs`` is ``False``, otherwise it is set to
832
a matrix of indices into ``cayley_graph_class_list`` corresponding
833
to the duals of these bent functions, and
834
- ``weight_class_matrix`` is set to the 0-1 matrix of weight classes
835
corresponding to ``bent_cayley_graph_index_matrix``.
836
837
Each entry ``bent_cayley_graph_index_matrix[c,b]`` corresponds to
838
the Cayley graph of the bent function
839
:math:`x \mapsto \mathtt{bentf}(x+b) + \langle c, x \rangle + \mathtt{bentf}(b)`.
840
This enumerates all of the extended translates of ``bentf``.
841
842
EXAMPLES:
843
844
The classification of the bent function defined by the polynomial
845
:math:`x_1 + x_2 + x_1 x_2`.
846
847
::
848
849
sage: from boolean_cayley_graphs.bent_function import BentFunction
850
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
851
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
852
sage: p = x1+x2+x1*x2
853
sage: f = BentFunction(p)
854
sage: c3 = BentFunctionCGC.from_function(f)
855
sage: dict(sorted(c3.__dict__.items()))
856
{'algebraic_normal_form': x0*x1 + x0 + x1,
857
'bent_cayley_graph_index_matrix': [0 1 1 1]
858
[1 1 0 1]
859
[1 0 1 1]
860
[1 1 1 0],
861
'cayley_graph_class_list': ['C~', 'CK'],
862
'dual_cayley_graph_index_matrix': [0 1 1 1]
863
[1 1 0 1]
864
[1 0 1 1]
865
[1 1 1 0],
866
'weight_class_matrix': [1 0 0 0]
867
[0 0 1 0]
868
[0 1 0 0]
869
[0 0 0 1]}
870
871
TESTS:
872
873
The classification of the bent function defined by the polynomial
874
:math:`x_1 + x_2 + x_1 x_2`, but with list_dual_graphs=False.
875
876
::
877
878
sage: from boolean_cayley_graphs.bent_function import BentFunction
879
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
880
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
881
sage: p = x1+x2+x1*x2
882
sage: f = BentFunction(p)
883
sage: c4 = BentFunctionCGC.from_function(f,list_dual_graphs=False)
884
sage: dict(sorted(c4.__dict__.items()))
885
{'algebraic_normal_form': x0*x1 + x0 + x1,
886
'bent_cayley_graph_index_matrix': [0 1 1 1]
887
[1 1 0 1]
888
[1 0 1 1]
889
[1 1 1 0],
890
'cayley_graph_class_list': ['C~', 'CK'],
891
'dual_cayley_graph_index_matrix': None,
892
'weight_class_matrix': [1 0 0 0]
893
[0 0 1 0]
894
[0 1 0 0]
895
[0 0 0 1]}
896
"""
897
cp = BentFunctionCayleyGraphClassPart.from_function(
898
bentf,
899
list_dual_graphs=list_dual_graphs,
900
limited_memory=limited_memory)
901
return cls(cp)
902
903
904
@classmethod
905
def from_parts(
906
cls,
907
prefix_basename,
908
dir=None,
909
limited_memory=False):
910
"""
911
Constructor from saved class parts.
912
913
INPUTS:
914
915
- ``prefix_basename`` -- string. The prefix to use with mangled_name()
916
to obtain the file names of the saved class parts.
917
- ``dir`` -- string, optional. The directory where the parts
918
are located. Default is None, meaning the current directory.
919
- ``limited_memory`` -- boolean, default is False.
920
A flag indicating whether the classification might be too large to
921
fit into memory.
922
923
OUTPUT:
924
925
An object of class BentFunctionCayleyGraphClassification,
926
constructed from the saved class parts.
927
928
EXAMPLES:
929
930
A classification of the bent function defined by the polynomial
931
:math:`x_1 + x_2 + x_1 x_2`.
932
933
::
934
935
sage: from boolean_cayley_graphs.bent_function import BentFunction
936
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
937
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCPart
938
sage: import os.path
939
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
940
sage: p = x1+x2+x1*x2
941
sage: f = BentFunction(p)
942
sage: prefix = tmp_filename()
943
sage: prefix_dirname = os.path.dirname(prefix)
944
sage: prefix_basename = os.path.basename(prefix)
945
sage: for row in range(4):
946
....: c = BentFunctionCGCPart.from_function(f, c_start=row,c_stop=row+1)
947
....: part_prefix = prefix_basename + "_" + str(row)
948
....: c.save_mangled(
949
....: part_prefix,
950
....: dir=prefix_dirname)
951
sage: cl1 = BentFunctionCGC.from_parts(
952
....: prefix_basename,
953
....: dir=prefix_dirname)
954
sage: cl1.report(report_on_matrix_details=True)
955
Algebraic normal form of Boolean function: x0*x1 + x0 + x1
956
Function is bent.
957
<BLANKLINE>
958
Weight class matrix:
959
[1 0 0 0]
960
[0 0 1 0]
961
[0 1 0 0]
962
[0 0 0 1]
963
<BLANKLINE>
964
SDP design incidence structure t-design parameters: (True, (1, 4, 1, 1))
965
<BLANKLINE>
966
Classification of Cayley graphs and classification of Cayley graphs of duals are the same:
967
<BLANKLINE>
968
There are 2 extended Cayley classes in the extended translation class.
969
<BLANKLINE>
970
Matrix of indices of Cayley graphs:
971
[0 1 1 1]
972
[1 1 0 1]
973
[1 0 1 1]
974
[1 1 1 0]
975
sage: for row in range(4):
976
....: part_prefix = prefix_basename + "_" + str(row)
977
....: BentFunctionCGCPart.remove_mangled(
978
....: part_prefix,
979
....: dir=prefix_dirname)
980
"""
981
mangled_part_prefix = BentFunctionCayleyGraphClassPart.mangled_name(
982
prefix_basename,
983
dir=dir)
984
file_name_list = glob.glob(mangled_part_prefix + "_[0-9]*.sobj")
985
file_name_list.sort()
986
987
# Load the first part to see how large the matrices need to be.
988
part_nbr = 0
989
part = load(file_name_list[part_nbr])
990
algebraic_normal_form = part.algebraic_normal_form
991
bentf = BentFunction(algebraic_normal_form)
992
dim = bentf.nvariables()
993
v = 2 ** dim
994
995
# If the number of columns in the part must match
996
# (be 2 to the power of) the number of variables of the bent function.
997
if part.bent_cayley_graph_index_matrix.ncols() != v:
998
raise ValueError
999
1000
# Initialize the graph class bijection to be empty.
1001
cayley_graph_class_bijection = (
1002
ShelveBijectiveList()
1003
if dim > 8 or (dim == 8 and limited_memory) else
1004
BijectiveList())
1005
1006
# Initialize the matrix attributes to be empty and of the right size.
1007
bent_cayley_graph_index_matrix = matrix(v, v)
1008
list_dual_graphs = part.dual_cayley_graph_index_matrix != None
1009
if list_dual_graphs:
1010
dual_cayley_graph_index_matrix = matrix(v, v)
1011
else:
1012
dual_cayley_graph_index_matrix = None
1013
weight_class_matrix = matrix(v,v)
1014
1015
for part_nbr in range(len(file_name_list)):
1016
# In the main loop, map each part classification into
1017
# the whole classification.
1018
if part_nbr > 0:
1019
part = load(file_name_list[part_nbr])
1020
whole_cg_index = dict()
1021
for part_cg_index in range(len(part.cayley_graph_class_list)):
1022
cg_index = cayley_graph_class_bijection.index_append(
1023
part.cayley_graph_class_list[part_cg_index])
1024
whole_cg_index[part_cg_index] = cg_index
1025
c_len = part.bent_cayley_graph_index_matrix.nrows()
1026
for part_c in range(c_len):
1027
c = part.c_start + part_c
1028
for b in range(v):
1029
bent_cayley_graph_index_matrix[c, b] = (
1030
whole_cg_index[
1031
part.bent_cayley_graph_index_matrix[part_c, b]])
1032
dual_cayley_graph_index_matrix[c, b] = (
1033
whole_cg_index[
1034
part.dual_cayley_graph_index_matrix[part_c, b]])
1035
weight_class_matrix[c, b] = (
1036
part.weight_class_matrix[part_c, b])
1037
1038
# Retain the list part of cayley_graph_class_bijection, and
1039
# close and remove the dict part.
1040
cayley_graph_class_list = cayley_graph_class_bijection.get_list()
1041
cayley_graph_class_bijection.close_dict()
1042
cayley_graph_class_bijection.remove_dict()
1043
1044
return cls(
1045
algebraic_normal_form=algebraic_normal_form,
1046
cayley_graph_class_list=cayley_graph_class_list,
1047
bent_cayley_graph_index_matrix=bent_cayley_graph_index_matrix,
1048
dual_cayley_graph_index_matrix=dual_cayley_graph_index_matrix,
1049
weight_class_matrix=weight_class_matrix)
1050
1051
1052
def __eq__(self, other):
1053
"""
1054
Test for equality between classifications.
1055
1056
WARNING:
1057
1058
This test is for strict equality rather than mathematical equivalence.
1059
1060
INPUT:
1061
1062
- ``other`` - BentFunctionCayleyGraphClassification: another classification.
1063
1064
OUTPUT:
1065
1066
A Boolean value indicating whether ``self`` strictly equals ``other``.
1067
1068
EXAMPLES:
1069
1070
::
1071
1072
sage: from boolean_cayley_graphs.bent_function import BentFunction
1073
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1074
sage: R2.<x0,x1> = BooleanPolynomialRing(2)
1075
sage: p = x0*x1
1076
sage: f1 = BentFunction(p)
1077
sage: c1 = BentFunctionCGC.from_function(f1)
1078
sage: f2 = BentFunction([0,0,0,1])
1079
sage: c2 = BentFunctionCGC.from_function(f2)
1080
sage: print(c2.algebraic_normal_form)
1081
x0*x1
1082
sage: print(c1 == c2)
1083
True
1084
"""
1085
if other is None:
1086
return False
1087
return (
1088
self.algebraic_normal_form == other.algebraic_normal_form and
1089
self.cayley_graph_class_list == other.cayley_graph_class_list and
1090
self.bent_cayley_graph_index_matrix == other.bent_cayley_graph_index_matrix and
1091
self.dual_cayley_graph_index_matrix == other.dual_cayley_graph_index_matrix and
1092
self.weight_class_matrix == other.weight_class_matrix)
1093
1094
1095
def first_matrix_index_list(self):
1096
r"""
1097
Obtain a representative bent function corresponding to each extended Cayley class.
1098
1099
INPUT:
1100
1101
- ``self`` -- the current object.
1102
1103
OUTPUT:
1104
1105
A list of tuples `(i_n,j_n)`, each of which is the first index into
1106
the matrix `self.bent_cayley_graph_index_matrix` that contains the entry `n`.
1107
The first index is determined by ``argwhere``.
1108
1109
EXAMPLES:
1110
1111
The result for the bent function defined by the polynomial :math:`x_1 + x_2 + x_1 x_2`.
1112
1113
::
1114
1115
sage: from boolean_cayley_graphs.bent_function import BentFunction
1116
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1117
sage: R2.<x1,x2> = BooleanPolynomialRing(2)
1118
sage: p = x1+x2+x1*x2
1119
sage: f = BentFunction(p)
1120
sage: c = BentFunctionCGC.from_function(f)
1121
sage: c.first_matrix_index_list()
1122
[(0, 0), (0, 1)]
1123
"""
1124
tot_cayley_graph_classes = len(self.cayley_graph_class_list)
1125
ci_matrix = self.bent_cayley_graph_index_matrix
1126
1127
ci_array = array(ci_matrix)
1128
ci_where = [
1129
argwhere(ci_array == index)
1130
for index in range(tot_cayley_graph_classes)]
1131
cb_list = [
1132
(None
1133
if ci_where[index].shape[0] == 0
1134
else tuple(ci_where[index][0,:]))
1135
for index in range(tot_cayley_graph_classes)]
1136
return cb_list
1137
1138
1139
def report(
1140
self,
1141
report_on_matrix_details=False,
1142
report_on_graph_details=False):
1143
r"""
1144
Print a report on the classification.
1145
1146
The report includes attributes and various computed quantities.
1147
1148
INPUT:
1149
1150
- ``self`` -- the current object.
1151
- ``report_on_matrix_details`` -- Boolean (default: False).
1152
If True, print each matrix.
1153
- ``report_on_graph_details`` -- Boolean (default: False).
1154
If True, produce a detailed report for each Cayley graph.
1155
1156
OUTPUT:
1157
1158
(To standard output)
1159
A report on the following attributes of ``self``:
1160
1161
- ``algebraic_normal_form``
1162
- ``cayley_graph_class_list``
1163
- If report_on_matrix_details is ``True``:
1164
- ``bent_cayley_graph_index_matrix``
1165
- ``dual_cayley_graph_index_matrix``
1166
(only if this is not ``None`` and is different from ``bent_cayley_graph_index_matrix``)
1167
- ``weight_class_matrix``
1168
- If report_on_graph_details is ``True``:
1169
details of each graph in ``cayley_graph_class_list``.
1170
1171
EXAMPLES:
1172
1173
Report on the classification of the bent function defined by
1174
the polynomial :math:`x_0 + x_0 x_1 + x_2 x_3`.
1175
1176
::
1177
1178
sage: from boolean_cayley_graphs.bent_function import BentFunction
1179
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1180
sage: R4.<x0,x1,x2,x3> = BooleanPolynomialRing(4)
1181
sage: p = x0+x0*x1+x2*x3
1182
sage: f = BentFunction(p)
1183
sage: c = BentFunctionCGC.from_function(f)
1184
sage: c.report(report_on_matrix_details=True, report_on_graph_details=True)
1185
Algebraic normal form of Boolean function: x0*x1 + x0 + x2*x3
1186
Function is bent.
1187
<BLANKLINE>
1188
Weight class matrix:
1189
[0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 1]
1190
[0 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0]
1191
[1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1]
1192
[0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1]
1193
[0 1 0 0 1 0 1 1 0 1 0 0 0 1 0 0]
1194
[0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1]
1195
[1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0]
1196
[0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0]
1197
[0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0]
1198
[0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1]
1199
[1 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0]
1200
[0 0 1 0 0 0 1 0 1 1 0 1 0 0 1 0]
1201
[1 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0]
1202
[1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1]
1203
[0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0]
1204
[1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0]
1205
<BLANKLINE>
1206
SDP design incidence structure t-design parameters: (True, (2, 16, 6, 2))
1207
<BLANKLINE>
1208
Classification of Cayley graphs and classification of Cayley graphs of duals are the same:
1209
<BLANKLINE>
1210
There are 2 extended Cayley classes in the extended translation class.
1211
<BLANKLINE>
1212
Matrix of indices of Cayley graphs:
1213
[0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 1]
1214
[0 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0]
1215
[1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1]
1216
[0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1]
1217
[0 1 0 0 1 0 1 1 0 1 0 0 0 1 0 0]
1218
[0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1]
1219
[1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0]
1220
[0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0]
1221
[0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0]
1222
[0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1]
1223
[1 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0]
1224
[0 0 1 0 0 0 1 0 1 1 0 1 0 0 1 0]
1225
[1 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0]
1226
[1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1]
1227
[0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0]
1228
[1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0]
1229
<BLANKLINE>
1230
For each extended Cayley class in the extended translation class:
1231
Clique polynomial, strongly regular parameters, rank, and order of a representative graph; and
1232
linear code and generator matrix for a representative bent function:
1233
<BLANKLINE>
1234
EC class 0 :
1235
Algebraic normal form of representative: x0*x1 + x0 + x2*x3
1236
Clique polynomial: 8*t^4 + 32*t^3 + 48*t^2 + 16*t + 1
1237
Strongly regular parameters: (16, 6, 2, 2)
1238
Rank: 6 Order: 1152
1239
<BLANKLINE>
1240
Linear code from representative:
1241
[6, 4] linear code over GF(2)
1242
Generator matrix:
1243
[1 0 0 0 0 1]
1244
[0 1 0 1 0 0]
1245
[0 0 1 1 0 0]
1246
[0 0 0 0 1 1]
1247
Linear code is projective.
1248
Weight distribution: {0: 1, 2: 6, 4: 9}
1249
<BLANKLINE>
1250
EC class 1 :
1251
Algebraic normal form of representative: x0*x1 + x0 + x1 + x2*x3
1252
Clique polynomial: 16*t^5 + 120*t^4 + 160*t^3 + 80*t^2 + 16*t + 1
1253
Strongly regular parameters: (16, 10, 6, 6)
1254
Rank: 6 Order: 1920
1255
<BLANKLINE>
1256
Linear code from representative:
1257
[10, 4] linear code over GF(2)
1258
Generator matrix:
1259
[1 0 1 0 1 0 0 1 0 0]
1260
[0 1 1 0 1 1 0 1 1 0]
1261
[0 0 0 1 1 1 0 0 0 1]
1262
[0 0 0 0 0 0 1 1 1 1]
1263
Linear code is projective.
1264
Weight distribution: {0: 1, 4: 5, 6: 10}
1265
1266
REFERENCES:
1267
1268
- [Leo2017]_.
1269
"""
1270
def graph_and_linear_code_report(
1271
bentf,
1272
report_on_matrix_details,
1273
report_on_graph_details,
1274
cayley_graph_class_list,
1275
pair_c_b_list,
1276
bent_cayley_graph_index_matrix,
1277
dual_cayley_graph_index_matrix=None):
1278
r"""
1279
Report on the Cayley graphs and linear codes given by the
1280
representative bent functions in the extended translation class.
1281
"""
1282
def print_compare(verb, a, b):
1283
1284
print((
1285
verb + " the same."
1286
if a == b
1287
else a), end=' ')
1288
1289
1290
verbose = controls.verbose
1291
1292
nbr_bent_cayley_graph_classes = len(
1293
np.unique(bent_cayley_graph_index_matrix))
1294
print("")
1295
print("There are", nbr_bent_cayley_graph_classes, end=' ')
1296
print("extended Cayley classes in the extended translation class.")
1297
1298
tot_cayley_graph_classes = len(cayley_graph_class_list)
1299
1300
if dual_cayley_graph_index_matrix != None:
1301
nbr_dual_cayley_graph_classes = len(
1302
np.unique(dual_cayley_graph_index_matrix))
1303
print("There are", nbr_dual_cayley_graph_classes, end=' ')
1304
print("extended Cayley classes of dual bent functions", end=' ')
1305
print("in the extended translation class,")
1306
print("and", tot_cayley_graph_classes, end=' ')
1307
print("extended Cayley classes in the union of the two.")
1308
1309
if report_on_matrix_details:
1310
print("")
1311
print("Matrix of indices of Cayley graphs:")
1312
print(bent_cayley_graph_index_matrix)
1313
1314
if dual_cayley_graph_index_matrix != None:
1315
print("Matrix of indices of Cayley graphs", end=' ')
1316
print("of dual bent functions:")
1317
print(dual_cayley_graph_index_matrix)
1318
1319
if not report_on_graph_details:
1320
return
1321
1322
print("")
1323
print("For each extended Cayley class in the extended translation class:")
1324
print("Clique polynomial, strongly regular parameters,", end=' ')
1325
print("rank, and order of a representative graph; and")
1326
print("linear code and generator matrix for a representative bent function:")
1327
1328
for index in range(tot_cayley_graph_classes):
1329
print("")
1330
print("EC class", index, ":")
1331
c_b = pair_c_b_list[index]
1332
if c_b == None:
1333
print("No such representative graph.")
1334
else:
1335
c = Integer(c_b[0])
1336
b = Integer(c_b[1])
1337
fb = f(b)
1338
fbc = bentf.extended_translate(b, c, fb)
1339
bent_fbc = BentFunction([fbc(x) for x in range(v)])
1340
p = bent_fbc.algebraic_normal_form()
1341
print("Algebraic normal form of representative:", p)
1342
g = Graph(cayley_graph_class_list[index])
1343
s = StronglyRegularGraph(g)
1344
print("Clique polynomial:", end=' ')
1345
print(s.stored_clique_polynomial)
1346
print("Strongly regular parameters:", end=' ')
1347
print(s.strongly_regular_parameters)
1348
print("Rank:", s.rank, end=' ')
1349
print("Order:", s.group_order)
1350
1351
if dual_cayley_graph_index_matrix != None:
1352
dual_index = dual_cayley_graph_index_matrix[c, b]
1353
if dual_index != index:
1354
print("Cayley graph of dual of representative differs:")
1355
print("Index is", dual_index)
1356
dual_g = Graph(cayley_graph_class_list[dual_index])
1357
dual_s = StronglyRegularGraph(dual_g)
1358
print("Clique polynomial", end=' ')
1359
print_compare(
1360
"is",
1361
dual_s.stored_clique_polynomial,
1362
s.stored_clique_polynomial)
1363
print("")
1364
print("Strongly regular parameters", end=' ')
1365
print_compare (
1366
"are",
1367
dual_s.strongly_regular_parameters,
1368
s.strongly_regular_parameters)
1369
print("")
1370
print("Rank", end=' ')
1371
print_compare ("is", dual_s.rank, s.rank)
1372
print("Order", end=' ')
1373
print_compare (
1374
"is", dual_s.group_order, s.group_order)
1375
print("")
1376
if verbose:
1377
if log(s.group_order, Integer(2)).is_integer():
1378
print("Order is a power of 2.")
1379
else:
1380
print("")
1381
print("Automorphism group", end=' ')
1382
dual_a = dual_s.automorphism_group
1383
print((
1384
"is"
1385
if dual_a.is_isomorphic(s.automorphism_group)
1386
else "is not"), end=' ')
1387
print("isomorphic.")
1388
1389
print("")
1390
print("Linear code from representative:")
1391
lc = bent_fbc.linear_code()
1392
print(lc)
1393
print("Generator matrix:")
1394
print(lc.generator_matrix().echelon_form())
1395
print("Linear code", end=' ')
1396
print("is" if lc.is_projective() else "is not", end=' ')
1397
print("projective.")
1398
print("Weight distribution:", end=' ')
1399
wd = lc.weight_distribution()
1400
print(dict([
1401
(w,wd[w]) for w in range(len(wd)) if wd[w] > 0]))
1402
1403
1404
p = self.algebraic_normal_form
1405
print("Algebraic normal form of Boolean function:", p)
1406
bentf = BentFunction(p)
1407
f = bentf.extended_translate()
1408
1409
dim = bentf.nvariables()
1410
v = 2 ** dim
1411
1412
print("Function", ("is" if bentf.is_bent() else "is not"), "bent.")
1413
print("")
1414
D = self.weight_class_matrix
1415
if report_on_matrix_details:
1416
print("Weight class matrix:")
1417
print(D)
1418
1419
print("")
1420
print("SDP design incidence structure t-design parameters:", end=' ')
1421
I = IncidenceStructure(D)
1422
print(I.is_t_design(return_parameters=True))
1423
1424
cg_list = self.cayley_graph_class_list
1425
ci_matrix = self.bent_cayley_graph_index_matrix
1426
di_matrix = self.dual_cayley_graph_index_matrix
1427
cb_list = self.first_matrix_index_list()
1428
1429
print("")
1430
if di_matrix == None:
1431
print("Classification of Cayley graphs:")
1432
1433
graph_and_linear_code_report(
1434
bentf,
1435
report_on_matrix_details,
1436
report_on_graph_details,
1437
cg_list,
1438
cb_list,
1439
ci_matrix)
1440
else:
1441
print("Classification of Cayley graphs and", end=' ')
1442
print("classification of Cayley graphs of duals", end=' ')
1443
if ci_matrix == di_matrix:
1444
print("are the same:")
1445
1446
graph_and_linear_code_report(
1447
bentf,
1448
report_on_matrix_details,
1449
report_on_graph_details,
1450
cg_list,
1451
cb_list,
1452
ci_matrix)
1453
else:
1454
print("differ in matrices of indexes:")
1455
1456
graph_and_linear_code_report(
1457
bentf,
1458
report_on_matrix_details,
1459
report_on_graph_details,
1460
cg_list,
1461
cb_list,
1462
ci_matrix,
1463
di_matrix)
1464
1465
1466
def print_latex_table_of_cayley_classes(self, width=40, rows_per_table=6):
1467
r"""
1468
Print a table of Cayley classes in LaTeX format.
1469
1470
For a given classification, print, in LaTeX format, the table
1471
of selected properties of the Cayley classes of that classification.
1472
1473
INPUT:
1474
1475
- ``self`` -- the current object.
1476
- ``width`` -- integer (default: 40): the table width.
1477
- ``rows_per_table`` -- integer (default: 6).
1478
The number of rows to include before starting a new table.
1479
1480
OUTPUT:
1481
1482
(To standard output.) A table in LaTeX format.
1483
1484
EXAMPLES:
1485
1486
Print the table of Cayley classes for the classification of the bent
1487
function defined by the polynomial :math:`x_0 + x_0 x_1 + x_2 x_3`.
1488
1489
::
1490
1491
sage: from boolean_cayley_graphs.bent_function import BentFunction
1492
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1493
sage: R4.<x0,x1,x2,x3> = BooleanPolynomialRing(4)
1494
sage: p = x0+x0*x1+x2*x3
1495
sage: f = BentFunction(p)
1496
sage: c = BentFunctionCGC.from_function(f)
1497
sage: c.print_latex_table_of_cayley_classes()
1498
\small{}
1499
\begin{align*}
1500
\def\arraystretch{1.2}
1501
\begin{array}{|cccl|}
1502
\hline
1503
\text{Class} &
1504
\text{Parameters} &
1505
\text{2-rank} &
1506
\text{Clique polynomial}
1507
\\
1508
\hline
1509
0 &
1510
(16, 6, 2, 2) &
1511
6 &
1512
\begin{array}{l}
1513
8t^{4} + 32t^{3} + 48t^{2} + 16t + 1
1514
\end{array}
1515
\\
1516
1 &
1517
(16, 10, 6, 6) &
1518
6 &
1519
\begin{array}{l}
1520
16t^{5} + 120t^{4} + 160t^{3}
1521
\,+
1522
\\
1523
80t^{2} + 16t + 1
1524
\end{array}
1525
\\
1526
\hline
1527
\end{array}
1528
\end{align*}
1529
"""
1530
def print_latex_header():
1531
print("\\small{}")
1532
print("\\begin{align*}")
1533
print("\\def\\arraystretch{1.2}")
1534
print("\\begin{array}{|cccl|}")
1535
print("\\hline")
1536
print("\\text{Class} &")
1537
print("\\text{Parameters} &")
1538
print("\\text{2-rank} &")
1539
print("\\text{Clique polynomial}")
1540
print("\\\\")
1541
print("\\hline")
1542
1543
1544
def print_latex_footer():
1545
print("\\hline")
1546
print("\\end{array}")
1547
print("\\end{align*}")
1548
1549
print_latex_header()
1550
cg_list = self.cayley_graph_class_list
1551
for n in range(len(cg_list)):
1552
if n > 0 and n % rows_per_table == 0:
1553
print_latex_footer()
1554
print("\\newpage")
1555
print_latex_header()
1556
1557
print(n, "&")
1558
g = Graph(cg_list[n])
1559
srg = StronglyRegularGraph(g)
1560
print(srg.strongly_regular_parameters, "&")
1561
print(srg.rank, "&")
1562
cp = srg.stored_clique_polynomial
1563
print("\\begin{array}{l}")
1564
lf = latex(cp)
1565
cut = 0
1566
while cut >= 0 and len(lf) > width:
1567
cut = lf.rfind('+', 0, width)
1568
if cut > 0:
1569
print(lf[:cut])
1570
if cut >= 0 and cut < len(lf):
1571
print("\\,+")
1572
print("\\\\")
1573
lf = lf[cut + 1:]
1574
print(lf)
1575
print("\\end{array}")
1576
print("\\\\")
1577
1578
print_latex_footer()
1579
1580
1581
def print_latex_table_of_tonchev_graphs(self, width=40):
1582
r"""
1583
Print a table comparing Cayley graphs with graphs from Tonchev's codes.
1584
1585
Tonchev's codes are binary projective two-weight codes
1586
as published by Tonchev [Ton1996]_, [Ton2007]_.
1587
1588
INPUT:
1589
1590
- ``self`` -- the current object.
1591
- ``width`` -- integer (default: 40): the table width.
1592
- ``algorithm`` -- string (default: ``default_algorithm``).
1593
Algorithm used for canonical labelling.
1594
1595
OUTPUT:
1596
1597
(To standard output.) A table in LaTeX format.
1598
1599
.. NOTE::
1600
1601
The comparison displayed in this table really only makes sense for
1602
bent functions in 6 dimensions.
1603
1604
EXAMPLES:
1605
1606
The classification for the bent function defined by the polynomial
1607
:math:`x_0 x_1 + x_2 x_3 + x_4 x_5`.
1608
1609
::
1610
1611
sage: from boolean_cayley_graphs.bent_function import BentFunction
1612
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1613
sage: R6.<x0,x1,x2,x3,x4,x5> = BooleanPolynomialRing(6)
1614
sage: p = x0*x1 + x2*x3 + x4*x5
1615
sage: f = BentFunction(p)
1616
sage: c = BentFunctionCGC.from_function(f) # long time (60 seconds)
1617
sage: c.print_latex_table_of_tonchev_graphs() # long time (depends on line above)
1618
\begin{align*}
1619
\def\arraystretch{1.2}
1620
\begin{array}{|ccl|}
1621
\hline
1622
\text{Class} &
1623
\text{Parameters} &
1624
\text{Reference}
1625
\\
1626
\hline
1627
0 & [35,6,16] & \text{Table 1.156 1 (complement)}
1628
\\
1629
0 & [35,6,16] & \text{Table 1.156 2 (complement)}
1630
\\
1631
1 & [27,6,12] & \text{Table 1.155 1 }
1632
\\
1633
\hline
1634
\end{array}
1635
\end{align*}
1636
1637
REFERENCES:
1638
1639
- [Ton1996]_.
1640
1641
- [Ton2007]_.
1642
"""
1643
print("\\begin{align*}")
1644
print("\\def\\arraystretch{1.2}")
1645
print("\\begin{array}{|ccl|}")
1646
print("\\hline")
1647
print("\\text{Class} &")
1648
print("\\text{Parameters} &")
1649
print("\\text{Reference}")
1650
print("\\\\")
1651
print("\\hline")
1652
1653
tw_155 = binary_projective_two_weight_27_6_12()
1654
lc_155 = [
1655
linear_code_from_code_gens(tw)
1656
for tw in tw_155]
1657
sr_155 = [
1658
strongly_regular_from_two_weight_code(lc).canonical_label(algorithm=algorithm).graph6_string()
1659
for lc in lc_155]
1660
1661
tw_156 = binary_projective_two_weight_35_6_16()
1662
lc_156 = [
1663
linear_code_from_code_gens(tw)
1664
for tw in tw_156]
1665
sr_156 = [
1666
strongly_regular_from_two_weight_code(lc).complement().canonical_label(algorithm=algorithm).graph6_string()
1667
for lc in lc_156]
1668
1669
cg_list = self.cayley_graph_class_list
1670
for n in range(len(cg_list)):
1671
cg = cg_list[n]
1672
for k in range(len(sr_155)):
1673
if cg == sr_155[k]:
1674
print(n, "&", end=' ')
1675
print_latex_code_parameters(lc_155[k])
1676
print("& \\text{Table 1.155", end=' ')
1677
print(k + 1, end=' ')
1678
print("}")
1679
print("\\\\")
1680
for k in range(len(sr_156)):
1681
if cg == sr_156[k]:
1682
print(n, "&", end=' ')
1683
print_latex_code_parameters(lc_156[k])
1684
print("& \\text{Table 1.156", end=' ')
1685
print(k + 1, end=' ')
1686
print("(complement)}")
1687
print("\\\\")
1688
1689
print("\\hline")
1690
print("\\end{array}")
1691
print("\\end{align*}")
1692
1693
1694
def save_matrix_plots(
1695
self,
1696
figure_name,
1697
cmap='gist_stern'):
1698
r"""
1699
Plot the matrix attributes to figure files.
1700
1701
Use ``matrix_plot`` to plot the matrix attributes
1702
``bent_cayley_graph_index_matrix``, ``dual_cayley_graph_index_matrix``,
1703
and ``weight_class_matrix`` to corresponding figure files.
1704
1705
INPUT:
1706
1707
- ``self`` -- the current object.
1708
- ``figure_name`` -- string.
1709
The prefix to use in the file names for the figures.
1710
- ``cmap`` -- string (default: ``'gist_stern'``).
1711
The colormap to use with ``matrixplot``.
1712
1713
OUTPUT:
1714
1715
(To figure files:
1716
``figure_name`` + ``"_bent_cayley_graph_index_matrix.png"``,
1717
``figure_name`` + ``"_dual_cayley_graph_index_matrix.png"``,
1718
``figure_name`` + ``"_weight_class_matrix.png"``) Plots of the corresponding
1719
matrix attributes.
1720
1721
EXAMPLES:
1722
1723
::
1724
1725
sage: from boolean_cayley_graphs.bent_function import BentFunction
1726
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1727
sage: import glob
1728
sage: import os
1729
sage: bf = BentFunction([1,1,0,1])
1730
sage: dim = bf.nvariables()
1731
sage: c = BentFunctionCGC.from_function(bf)
1732
sage: figure_name = tmp_filename()
1733
sage: c.save_matrix_plots(figure_name)
1734
sage: figure_list = glob.glob(figure_name+"*.png")
1735
sage: for figure in figure_list:
1736
....: print(
1737
....: "_bent_cayley_graph_index_matrix.png" in figure or
1738
....: "_dual_cayley_graph_index_matrix.png" in figure or
1739
....: "_weight_class_matrix.png" in figure)
1740
....: print(os.path.isfile(figure))
1741
....: os.remove(figure)
1742
True
1743
True
1744
True
1745
True
1746
True
1747
True
1748
"""
1749
matrix_names = (
1750
"bent_cayley_graph_index_matrix",
1751
"dual_cayley_graph_index_matrix",
1752
"weight_class_matrix")
1753
1754
attributes = self.__dict__
1755
for name in matrix_names:
1756
graphic = matrix_plot(matrix(attributes[name]),cmap=cmap)
1757
graphic.save(figure_name + "_" + name + ".png")
1758
1759
1760
def save_cg_class_list_as_csv(
1761
self,
1762
file_name):
1763
"""
1764
Save the Cayley graph class list to a csv file.
1765
1766
INPUT:
1767
1768
- ``file_name`` -- the name of the csv file.
1769
1770
OUTPUT:
1771
1772
None.
1773
1774
EXAMPLES:
1775
1776
::
1777
1778
sage: from boolean_cayley_graphs.bent_function import BentFunction
1779
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1780
sage: import os
1781
sage: bf2 = BentFunction([1,0,1,1])
1782
sage: c2 = BentFunctionCGC.from_function(bf2)
1783
sage: csv_name = tmp_filename(ext=".csv")
1784
sage: c2.save_cg_class_list_as_csv(csv_name)
1785
sage: cgcl_saved = BentFunctionCGC.cg_class_list_from_csv(csv_name)
1786
sage: print(cgcl_saved == c2.cayley_graph_class_list)
1787
True
1788
sage: os.remove(csv_name)
1789
"""
1790
cg_list = self.cayley_graph_class_list
1791
1792
fieldnames = [
1793
"cayley_graph_index",
1794
"canonical_label"]
1795
with open(file_name, "w") as cg_class_file:
1796
writer = csv.DictWriter(
1797
cg_class_file,
1798
fieldnames=fieldnames)
1799
writer.writeheader()
1800
for n in range(len(cg_list)):
1801
writer.writerow({
1802
"cayley_graph_index":
1803
n,
1804
"canonical_label":
1805
cg_list[n]})
1806
1807
1808
def save_matrices_as_csv(
1809
self,
1810
file_name):
1811
"""
1812
Save the matrices bent_cayley_graph_index_matrix,
1813
dual_cayley_graph_index_matrix and weight_class_matrix to a csv file.
1814
1815
INPUT:
1816
1817
- ``file_name`` -- the name of the csv file.
1818
1819
OUTPUT:
1820
1821
None.
1822
1823
EXAMPLES::
1824
1825
sage: from boolean_cayley_graphs.bent_function import BentFunction
1826
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1827
sage: import os
1828
sage: bf2 = BentFunction([0,1,1,1])
1829
sage: dim = bf2.nvariables()
1830
sage: c2 = BentFunctionCGC.from_function(bf2)
1831
sage: csv_name = tmp_filename(ext=".csv")
1832
sage: c2.save_matrices_as_csv(csv_name)
1833
sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
1834
sage: print(c2.bent_cayley_graph_index_matrix == ci_matrix)
1835
True
1836
sage: print(c2.dual_cayley_graph_index_matrix == di_matrix)
1837
True
1838
sage: print(c2.weight_class_matrix == wc_matrix)
1839
True
1840
sage: os.remove(csv_name)
1841
1842
TESTS:
1843
1844
Test the case where list_dual_graphs=False and dual_cayley_graph_index_matrix is None.
1845
1846
::
1847
1848
sage: from boolean_cayley_graphs.bent_function import BentFunction
1849
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1850
sage: import os
1851
sage: bf = BentFunction([1,0,1,1])
1852
sage: dim = bf.nvariables()
1853
sage: c = BentFunctionCGC.from_function(bf, list_dual_graphs=False)
1854
sage: csv_name = tmp_filename(ext=".csv")
1855
sage: c.save_matrices_as_csv(csv_name)
1856
sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
1857
sage: print(c.bent_cayley_graph_index_matrix == ci_matrix)
1858
True
1859
sage: print(c.dual_cayley_graph_index_matrix == di_matrix)
1860
True
1861
sage: print(c.weight_class_matrix == wc_matrix)
1862
True
1863
sage: os.remove(csv_name)
1864
1865
"""
1866
bentf = BentFunction(self.algebraic_normal_form)
1867
dim = bentf.nvariables()
1868
v = 2 ** dim
1869
1870
ci_matrix = self.bent_cayley_graph_index_matrix
1871
di_matrix = self.dual_cayley_graph_index_matrix
1872
wc_matrix = self.weight_class_matrix
1873
1874
fieldnames = [
1875
"b",
1876
"c",
1877
"bent_cayley_graph_index",
1878
"weight_class"]
1879
if di_matrix is not None:
1880
fieldnames.append(
1881
"dual_cayley_graph_index")
1882
with open(file_name, "w") as matrix_file:
1883
writer = csv.DictWriter(
1884
matrix_file,
1885
fieldnames=fieldnames)
1886
writer.writeheader()
1887
1888
for c in range(v):
1889
for b in range(v):
1890
row_dict = {
1891
"b":
1892
b,
1893
"c":
1894
c,
1895
"bent_cayley_graph_index":
1896
ci_matrix[c, b],
1897
"weight_class":
1898
wc_matrix[c, b]}
1899
if di_matrix is not None:
1900
row_dict[
1901
"dual_cayley_graph_index"] = di_matrix[c, b]
1902
writer.writerow(row_dict)
1903
1904
1905
def save_as_csv(
1906
self,
1907
file_name_prefix):
1908
"""
1909
Save the classification as three csv files with a common prefix.
1910
1911
INPUT:
1912
1913
- ``self`` -- the current object.
1914
- ``file_name_prefix`` -- string: the common prefix to use for file names.
1915
1916
OUTPUT:
1917
1918
None.
1919
1920
EXAMPLES:
1921
1922
::
1923
1924
sage: from boolean_cayley_graphs.bent_function import BentFunction
1925
sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
1926
sage: import os
1927
sage: bf2 = BentFunction([0,0,0,1])
1928
sage: c2 = BentFunctionCGC.from_function(bf2)
1929
sage: prefix = tmp_filename()
1930
sage: c2.save_as_csv(prefix)
1931
sage: c2_saved = BentFunctionCGC.from_csv(prefix)
1932
sage: print(c2 == c2_saved)
1933
True
1934
sage: bent_function_csv_name = prefix + BentFunctionCGC.bent_function_csv_suffix
1935
sage: os.remove(bent_function_csv_name)
1936
sage: cg_class_list_csv_name = prefix + BentFunctionCGC.cg_class_list_csv_suffix
1937
sage: os.remove(cg_class_list_csv_name)
1938
sage: matrices_csv_name = prefix + BentFunctionCGC.matrices_csv_suffix
1939
sage: os.remove(matrices_csv_name)
1940
"""
1941
cls = type(self)
1942
bentf = BentFunction(self.algebraic_normal_form)
1943
bentf.save_as_csv(
1944
file_name_prefix + cls.bent_function_csv_suffix)
1945
1946
self.save_cg_class_list_as_csv(
1947
file_name_prefix + cls.cg_class_list_csv_suffix)
1948
1949
self.save_matrices_as_csv(
1950
file_name_prefix + cls.matrices_csv_suffix)
1951
1952