Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
22144 views
o

�Ul_T)�@s�dZddlmZddlmZmZddlmZddlmZddl	m
Z
ddlmZddl
mZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlmZddlZddlZddlm Z ddl!m"Z"ddl!m#Z#ddl$m%Z%ddl&m'Z'ddl&m(Z(ddl)m*Z*ddl+m,Z,ddl+m-Z-ddl.m/Z/ddl0m1Z1ddl2m3Z3ddl4m5Z6ddl7Z7ddl8Z9dZ:Gdd�dee/�Z;Gd d!�d!e;�Z<dS)"a

Classification of bent functions by their Cayley graphs
=======================================================

The ``bent_function_cayley_graph_classification`` module defines:

 * the ``BentFunctionCayleyGraphClassification`` class;
   which represents the classification of the Cayley graphs
   within the extended translation class of a bent function; and
 * the ``BentFunctionCayleyGraphClassPart`` class,
   which represents part of a Cayley graph classification.

AUTHORS:

- Paul Leopardi (2016-08-02): initial version

EXAMPLES:

::

    The classification of the bent function defined by the polynomial x2 + x1*x2.

    sage: from boolean_cayley_graphs.bent_function import BentFunction
    sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
    sage: R2.<x1,x2> = BooleanPolynomialRing(2)
    sage: p = x2+x1*x2
    sage: f = BentFunction(p)
    sage: c = BentFunctionCGC.from_function(f)
    sage: dict(sorted(c.__dict__.items()))
    {'algebraic_normal_form': x0*x1 + x1,
     'bent_cayley_graph_index_matrix': [0 0 1 0]
     [1 0 0 0]
     [0 0 0 1]
     [0 1 0 0],
     'cayley_graph_class_list': ['CK', 'C~'],
     'dual_cayley_graph_index_matrix': [0 0 1 0]
     [1 0 0 0]
     [0 0 0 1]
     [0 1 0 0],
     'weight_class_matrix': [0 0 1 0]
     [1 0 0 0]
     [0 0 0 1]
     [0 1 0 0]}

REFERENCES:

The extended translation equivalence class and the extended Cayley equivalence class
of a bent function are defined by Leopardi [Leo2017]_.
�)�datetime)�array�argwhere)�
LinearCode)�IncidenceStructure)�log)�Graph)�%strongly_regular_from_two_weight_code)�matrix)�latex)�load)�matrix_plot)�Integer)�
SageObject)�stdoutN)�BentFunction)�$binary_projective_two_weight_27_6_12)�$binary_projective_two_weight_35_6_16)�boolean_cayley_graph��linear_code_from_code_gens)�print_latex_code_parameters)�boolean_linear_code_graph)�
BijectiveList)�ShelveBijectiveList)�Saveable)�StronglyRegularGraph)�weight_class�sagec@s@eZdZdZdd�Zdd�Zedddd	efd
d��Zdd
�Z	dS)� BentFunctionCayleyGraphClassPartab
    Partial classification of the Cayley graphs within the
    extended translation equivalence class of a bent function.

    EXAMPLES:

    ::

        sage: from boolean_cayley_graphs.bent_function import BentFunction
        sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
        sage: R2.<x1,x2> = BooleanPolynomialRing(2)
        sage: p = x1+x2+x1*x2
        sage: f = BentFunction(p)
        sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
        sage: print(c1)
        BentFunctionCayleyGraphClassPart.from_function(BentFunction(x0*x1 + x0 + x1, c_start=0, c_stop=1))
        sage: latex(c1)
        \text{\texttt{BentFunctionCayleyGraphClassPart.from{\char`\_}function(BentFunction(x0*x1{ }+{ }x0{ }+{ }x1,{ }c{\char`\_}start=0,{ }c{\char`\_}stop=1))}}

    cOs�z|d}|j|_|j|_|j|_|j|_|j|_|j|_WdS|�d�|_|�d�|_|�d�|_|�dd�|_|�d�|_|�d�|_YdS)	a�	
        Constructor from an object or from class attributes.

        INPUT:

        - ``algebraic_normal_form`` -- a polynomial of the type
          returned by ``BooleanFunction.algebraic_normal_form()``,
          representing the ``BentFunction`` whose classification this is.
        - ``cayley_graph_class_list`` -- a list of ``graph6_string`` strings
          corresponding to the complete set of non-isomorphic Cayley graphs of
          the bent functions within the extended translation equivalence class
          of the ``BentFunction`` represented by ``algebraic_normal_form``,
          and their duals, if ``dual_cayley_graph_index_matrix`` is not ``None``,
        - ``bent_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
          which are indices into ``cayley_graph_class_list`` representing the
          correspondence between bent functions and their Cayley graphs.
        - ``dual_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
          which are indices into ``cayley_graph_class_list`` representing the
          correspondence between dual bent functions and their Cayley graphs.
        - ``weight_class_matrix`` -- a ``Matrix` of integers with value 0 or 1
          corresponding to the weight class of each bent function.
        - ``c_start`` -- an integer representing the Boolean vector
          corresponding to the first row of each matrix.

        OUTPUT:

        None.

        EFFECT:

        The current object ``self`` is initialized as follows.

        Each of
        - ``algebraic_normal_form``
        - ``cayley_graph_class_list``
        - ``bent_cayley_graph_index_matrix``
        - ``dual_cayley_graph_index_matrix``
        - ``weight_class_matrix``
        - ``c_start``
        is set to the corresponding input parameter.

        EXAMPLES:

        The partial classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2` is copied from `c1` to `c2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
            sage: c2 = BentFunctionCGCP(c1)
            sage: print(c1 == c2)
            True
        r�algebraic_normal_form�cayley_graph_class_list�bent_cayley_graph_index_matrix�dual_cayley_graph_index_matrixN�weight_class_matrix�c_start)r r!r"r#r$r%�pop��self�args�kwargs�sobj�r,�c/home/user/Boolean-Cayley-graphs/boolean_cayley_graphs/bent_function_cayley_graph_classification.py�__init__xs6;������z)BentFunctionCayleyGraphClassPart.__init__cCsF|j|j��}t|�jdt|j�dt|j�dt|�dS)a�
        Sage string representation.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c1 = BentFunctionCGCP.from_function(f, c_stop=1)
            sage: print(c1)
            BentFunctionCayleyGraphClassPart.from_function(BentFunction(x0*x1 + x0 + x1, c_start=0, c_stop=1))
        �.from_function(BentFunction(z
, c_start=z	, c_stop=�)))r%r$�nrows�type�__name__�reprr )r(�c_stopr,r,r-�_repr_�s"��������z'BentFunctionCayleyGraphClassPart._repr_TrNFc#s�tj}tj}|��}	d|	}
||dkr|
}nt||
�}|��}|	dks*|	dkr-|r-t�nt�}||}
t|
|
�}|rAt|
|
�}nd}t|
|
�}|�	�}|�
�}|�	�}t|
�D]�}|rott
��|dd�tt|��t��||�}t||�D]�}|�	|||��t|	��j|d�}|�|���}|||||f<t�fdd�t|
�D��}t|
|�}|||||f<|r�|d	kr�|d
kr�tdt|���|�r(t�fdd
�t|
�D��}|�
�j	|d�}t|	|�j|d�}|�|���}|||||f<|�r(|	dk�r(t|	��}|d	k�r
|j|d�n|��j|d�} | |k�r(tdt|�dt|���qx|��qX|��}!|��|� �|�rT|�!�}"||"k�rTtdt|�dt|"���|�ratt
���t��|||!||||d�S)a
        Constructor from the ``BentFunction`` ``bentf``.

        INPUT:

        - ``bentf`` -- an object of class ``BentFunction``.
        - ``list_dual_graphs`` -- boolean (default: ``True``). 
          A flag indicating whether to list dual graphs.
        - ``c_start`` -- integer (default: 0).
          The smallest value of `c` to use for extended translates.
        - ``c_stop`` -- integer (default: ``None``).
          One more than largest value of `c` to use for extended
          translates. ``None`` means use all remaining values.
        - ``limited_memory`` -- boolean (default: ``False``).
          A flag indicating whether the classification might be
          too large to fit into memory.
        - ``algorithm`` -- string (default: ``default_algorithm``). 
          The algorithm used for canonical labelling.

        OUTPUT:

        An object of class BentFunctionCayleyGraphClassPart,
        initialized as follows.

        - ``algebraic_normal_form`` is set to ``bentf.algebraic_normal_form()``,
        - ``cayley_graph_class_list`` is set to a list of ``graph6_string`` stings
          corresponding to the complete set of non-isomorphic Cayley graphs
          of the bent functions within the extended translation equivalence
          class of ``bentf`` (and their duals, if ``list_dual_graphs`` is ``True``),
        - ``bent_cayley_graph_index_matrix`` is set to a matrix of indices
          into ``cayley_graph_class_list`` corresponding to these bent functions,
        - ``dual_cayley_graph_index_matrix`` is set to ``None``
          if ``list_dual_graphs`` is ``False``, otherwise it is set to
          a matrix of indices into ``cayley_graph_class_list`` corresponding
          to the duals of these bent functions, and
        - ``weight_class_matrix`` is set to the 0-1 matrix of weight classes
          corresponding to ``bent_cayley_graph_index_matrix``,
        - ``c_start`` is set to smallest value of `c` used for extended translates.

        Each entry ``bent_cayley_graph_index_matrix[c-c_start,b]`` corresponds to
        the Cayley graph of the bent function
        :math:`x \mapsto \mathtt{bentf}(x+b) + \langle c, x \rangle + \mathtt{bentf}(b)`.
        This enumerates all of the extended translates of ``bentf`` having ``c``
        from ``c_start`` to but not including ``c_stop``.

        EXAMPLES:

        A partial classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCPart
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c1 = BentFunctionCGCPart.from_function(f,c_start=2,c_stop=4)
            sage: dict(sorted(c1.__dict__.items()))
            {'algebraic_normal_form': x0*x1 + x0 + x1,
            'bent_cayley_graph_index_matrix': [0 1 0 0]
            [0 0 0 1],
            'c_start': 2,
            'cayley_graph_class_list': ['CK', 'C~'],
            'dual_cayley_graph_index_matrix': [0 1 0 0]
            [0 0 0 1],
            'weight_class_matrix': [0 1 0 0]
            [0 0 0 1]}

        A partial classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2`, but with list_dual_graphs=False.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c2 = BentFunctionCGCPart.from_function(f,list_dual_graphs=False,c_start=0,c_stop=2)
            sage: dict(sorted(c2.__dict__.items()))
            {'algebraic_normal_form': x0*x1 + x0 + x1,
            'bent_cayley_graph_index_matrix': [0 1 1 1]
            [1 1 0 1],
            'c_start': 0,
            'cayley_graph_class_list': ['C~', 'CK'],
            'dual_cayley_graph_index_matrix': None,
            'weight_class_matrix': [1 0 0 0]
            [0 0 1 0]}
        �N�� ��end��	algorithmc3s�|]}�|�VqdS�Nr,��.0�x��fbcr,r-�	<genexpr>xs�zABentFunctionCayleyGraphClassPart.from_function.<locals>.<genexpr>r�zWeight class is c�g|]}�|��qSr,r,r?rBr,r-�
<listcomp>��zBBentFunctionCayleyGraphClassPart.from_function.<locals>.<listcomp>)�dz=Cayley graph of dual does not matchgraph from linear code at �,z)weight_class_matrix != sdp_design_matrix
�
�r r!r"r#r$r%)"�controls�checking�timing�
nvariables�minr rrr
�extended_translate�walsh_hadamard_dual�range�printr�now�lenr�flushr�canonical_label�index_append�
graph6_string�sumr�
ValueError�strrr�
complement�sync�get_list�
close_dict�remove_dict�sdp_design_matrix)#�cls�bentf�list_dual_graphsr%r5�limited_memoryr=rNrO�dim�vr �cayley_graph_class_bijection�c_lenr"r#r$�fZ
dual_bentf�dual_f�b�fb�c�cg�cg_index�weight�wcZbentfbcZdual_fbc�dgZdg_indexZblcgZlgr!rdr,rBr-�
from_function�s�c
����


��
��
�����

�����z.BentFunctionCayleyGraphClassPart.from_functioncCsT|durdS|j|jko)|j|jko)|j|jko)|j|jko)|j|jko)|j|jkS)a
        Test for equality between partial classifications.

        WARNING:

        This test is for strict equality rather than mathematical equivalence.

        INPUT:

        - ``other`` - BentFunctionCayleyGraphClassPart: another partial classification.

        OUTPUT:

        A Boolean value indicating whether ``self`` strictly equals ``other``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCP
            sage: R2.<x0,x1> = BooleanPolynomialRing(2)
            sage: p = x0*x1
            sage: f1 = BentFunction(p)
            sage: c1 = BentFunctionCGCP.from_function(f1, c_stop=1)
            sage: f2 = BentFunction([0,0,0,1])
            sage: c2 = BentFunctionCGCP.from_function(f2, c_stop=1)
            sage: print(c2.algebraic_normal_form)
            x0*x1
            sage: print(c1 == c2)
            True
        NFrL�r(�otherr,r,r-�__eq__�s!
�
�
�
�
�z'BentFunctionCayleyGraphClassPart.__eq__)
r3�
__module__�__qualname__�__doc__r.r6�classmethod�default_algorithmrwrzr,r,r,r-rbsR!�Irc@s�eZdZdZdZdZdZdd�Zdd�Ze	d	d
��Z
e	dd��Ze	d
d��Ze			d+dd��Z
e			d,dd��Zdd�Zdd�Z		d-dd�Zd.dd�Zd/d d!�Z	"d0d#d$�Zd%d&�Zd'd(�Zd)d*�ZdS)1�%BentFunctionCayleyGraphClassificationa
    Classification of the Cayley graphs within the
    extended translation equivalence class of a bent function.

    EXAMPLES:

    ::

        sage: from boolean_cayley_graphs.bent_function import BentFunction
        sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
        sage: R2.<x1,x2> = BooleanPolynomialRing(2)
        sage: p = x1+x2+x1*x2
        sage: f = BentFunction(p)
        sage: c1 = BentFunctionCGC.from_function(f)
        sage: print(c1)
        BentFunctionCayleyGraphClassification.from_function(BentFunction(x0*x1 + x0 + x1))
        sage: latex(c1)
        \text{\texttt{BentFunctionCayleyGraphClassification.from{\char`\_}function(BentFunction(x0*x1{ }+{ }x0{ }+{ }x1))}}
    z_bent_function.csvz_cg_class_list.csvz
_matrices.csvcOs�z|d}|j|_|j|_|j|_|j|_|j|_WdS|�d�|_|�d�|_|�d�|_|�dd�|_|�d�|_YdS)aw	
        Constructor from an object or from class attributes.

        INPUT:

        - ``sobj`` -- BentFunctionCayleyGraphClassification: object to copy.

        - ``algebraic_normal_form`` -- a polynomial of the type
          returned by ``BooleanFunction.algebraic_normal_form()``,
          representing the ``BentFunction`` whose classification this is.
        - ``cayley_graph_class_list`` -- a list of ``graph6_string`` strings
          corresponding to the complete set of non-isomorphic Cayley graphs of
          the bent functions within the extended translation equivalence class
          of the ``BentFunction`` represented by ``algebraic_normal_form``,
          and their duals, if ``dual_cayley_graph_index_matrix`` is not ``None``,
        - ``bent_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
          which are indices into ``cayley_graph_class_list`` representing the
          correspondence between bent functions and their Cayley graphs.
        - ``dual_cayley_graph_index_matrix`` -- a ``Matrix` of integers,
          which are indices into ``cayley_graph_class_list`` representing the
          correspondence between dual bent functions and their Cayley graphs.
        - ``weight_class_matrix`` -- a ``Matrix` of integers with value 0 or 1
          corresponding to the weight class of each bent function.

        OUTPUT:

        None.

        EFFECT:

        The current object ``self`` is initialized as follows.

        Each of
        - ``algebraic_normal_form``
        - ``cayley_graph_class_list``
        - ``bent_cayley_graph_index_matrix``
        - ``dual_cayley_graph_index_matrix``
        - ``weight_class_matrix``
        is set to the corresponding input parameter.

        EXAMPLES:

        The classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2` is copied from `c1` to `c2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c1 = BentFunctionCGC.from_function(f)
            sage: c2 = BentFunctionCGC(c1)
            sage: print(c1 == c2)
            True
        rr r!r"r#Nr$)r r!r"r#r$r&r'r,r,r-r.�s.:�����z.BentFunctionCayleyGraphClassification.__init__cCst|�jdt|j�dS)a�
        Sage string representation.

        INPUT:

        - ``self`` -- the current object.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c1 = BentFunctionCGC.from_function(f)
            sage: print(c1)
            BentFunctionCayleyGraphClassification.from_function(BentFunction(x0*x1 + x0 + x1))
        r/r0)r2r3r4r )r(r,r,r-r6Is����z,BentFunctionCayleyGraphClassification._repr_cCsTg}t|��}t�|�}|D]	}|�|d�qWd�|S1s#wY|S)a�
        Read a Cayley graph class list from a csv file.

        The csv file is assumed to be created by the method
        save_cg_class_list_as_csv().

        INPUT:

        - ``file_name`` -- the name of the csv file.

        OUTPUT:

        A list of Cayley graphs in graph6_string format.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([1,0,1,1])
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c2.save_cg_class_list_as_csv(csv_name)
            sage: cgcl_saved = BentFunctionCGC.cg_class_list_from_csv(csv_name)
            sage: print(cgcl_saved == c2.cayley_graph_class_list)
            True
            sage: os.remove(csv_name)

        rYN)�open�csv�
DictReader�append)re�	file_name�cg_list�csv_file�reader�rowr,r,r-�cg_class_list_from_csves#

�
��z<BentFunctionCayleyGraphClassification.cg_class_list_from_csvc
Cs�d|}t|��R}t�|�}|j}t||�}t||�}d|vr$t||�nd}	|D]*}
t|
d�}t|
d�}|
d|||f<|
d|||f<d|vrR|
d|	||f<q(Wd�n1s]wY||	|fS)a	
        Read three matrices from a csv file.

        The csv file is assumed to be created by the method
        save_matrices_as_csv().

        INPUT:

        - ``dim`` -- integer: the dimension of the bent function.
        - ``file_name`` -- the name of the csv file.

        OUTPUT:

        A tuple of matrices,

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([1,1,0,1])
            sage: dim = bf2.nvariables()
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c2.save_matrices_as_csv(csv_name)
            sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
            sage: print(c2.bent_cayley_graph_index_matrix == ci_matrix)
            True
            sage: print(c2.dual_cayley_graph_index_matrix == di_matrix)
            True
            sage: print(c2.weight_class_matrix == wc_matrix)
            True
            sage: os.remove(csv_name)

        TESTS:

            Test the case where list_dual_graphs==False and dual_cayley_graph_index_matrix is None.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf = BentFunction([1,1,0,1])
            sage: dim = bf.nvariables()
            sage: c = BentFunctionCGC.from_function(bf, list_dual_graphs=False)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c.save_matrices_as_csv(csv_name)
            sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
            sage: print(c.bent_cayley_graph_index_matrix == ci_matrix)
            True
            sage: print(c.dual_cayley_graph_index_matrix == di_matrix)
            True
            sage: print(c.weight_class_matrix == wc_matrix)
            True
            sage: os.remove(csv_name)
        r7�dual_cayley_graph_indexNrqro�bent_cayley_graph_indexr)r�r�r��
fieldnamesr
�int)
rerir�rjr�r�r��	ci_matrix�	wc_matrix�	di_matrixr�rqror,r,r-�matrices_from_csv�s*@



�����
z7BentFunctionCayleyGraphClassification.matrices_from_csvc	CsZt�||j�}|��}|�||j�}|��}|�|||j�\}}}||||||d�S)a�
        Constructor from three csv files.

        INPUT:

        - ``file_name_prefix`` -- string: the common prefix to use for file names.

        OUTPUT:

        None.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([1,1,0,1])
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: prefix = tmp_filename()
            sage: c2.save_as_csv(prefix)
            sage: c2_saved = BentFunctionCGC.from_csv(prefix)
            sage: print(c2 == c2_saved)
            True
            sage: bent_function_csv_name = prefix + BentFunctionCGC.bent_function_csv_suffix
            sage: os.remove(bent_function_csv_name)
            sage: cg_class_list_csv_name = prefix + BentFunctionCGC.cg_class_list_csv_suffix
            sage: os.remove(cg_class_list_csv_name)
            sage: matrices_csv_name = prefix + BentFunctionCGC.matrices_csv_suffix
            sage: os.remove(matrices_csv_name)

        �r r!r"r#r$)	r�from_csv�bent_function_csv_suffixr r��cg_class_list_csv_suffixrPr��matrices_csv_suffix)	re�file_name_prefixrfr r!rir"r#r$r,r,r-r��s.%�����z.BentFunctionCayleyGraphClassification.from_csvTFcCstj|||d�}||�S)a<
        Constructor from the ``BentFunction`` ``bentf``.

        INPUT:

        - ``bentf`` -- an object of class ``BentFunction``.
        - ``list_dual_graphs`` -- boolean. a flag indicating
          whether to list dual graphs.
        - ``limited_memory`` -- boolean. A flag indicating
          whether the classification might be too large
          to fit into memory. Default is False.

        OUTPUT:

        An object of class BentFunctionCayleyGraphClassification,
        initialized as follows.

        - ``algebraic_normal_form`` is set to ``bentf.algebraic_normal_form()``,
        - ``cayley_graph_class_list`` is set to a list of ``graph6_string``
          strings corresponding to the complete set of non-isomorphic Cayley graphs
          of the bent functions within the extended translation equivalence
          class of ``bentf`` (and their duals, if ``list_dual_graphs`` is ``True``),
        - ``bent_cayley_graph_index_matrix`` is set to a matrix of indices
          into ``cayley_graph_class_list`` corresponding to these bent functions,
        - ``dual_cayley_graph_index_matrix`` is set to ``None``
          if ``list_dual_graphs`` is ``False``, otherwise it is set to
          a matrix of indices into ``cayley_graph_class_list`` corresponding
          to the duals of these bent functions, and
        - ``weight_class_matrix`` is set to the 0-1 matrix of weight classes
          corresponding to ``bent_cayley_graph_index_matrix``.

        Each entry ``bent_cayley_graph_index_matrix[c,b]`` corresponds to
        the Cayley graph of the bent function
        :math:`x \mapsto \mathtt{bentf}(x+b) + \langle c, x \rangle + \mathtt{bentf}(b)`.
        This enumerates all of the extended translates of ``bentf``.

        EXAMPLES:

        The classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c3 = BentFunctionCGC.from_function(f)
            sage: dict(sorted(c3.__dict__.items()))
            {'algebraic_normal_form': x0*x1 + x0 + x1,
            'bent_cayley_graph_index_matrix': [0 1 1 1]
            [1 1 0 1]
            [1 0 1 1]
            [1 1 1 0],
            'cayley_graph_class_list': ['C~', 'CK'],
            'dual_cayley_graph_index_matrix': [0 1 1 1]
            [1 1 0 1]
            [1 0 1 1]
            [1 1 1 0],
            'weight_class_matrix': [1 0 0 0]
            [0 0 1 0]
            [0 1 0 0]
            [0 0 0 1]}

        TESTS:

        The classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2`, but with list_dual_graphs=False.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c4 = BentFunctionCGC.from_function(f,list_dual_graphs=False)
            sage: dict(sorted(c4.__dict__.items()))
            {'algebraic_normal_form': x0*x1 + x0 + x1,
            'bent_cayley_graph_index_matrix': [0 1 1 1]
            [1 1 0 1]
            [1 0 1 1]
            [1 1 1 0],
            'cayley_graph_class_list': ['C~', 'CK'],
            'dual_cayley_graph_index_matrix': None,
            'weight_class_matrix': [1 0 0 0]
            [0 0 1 0]
            [0 1 0 0]
            [0 0 0 1]}
        )rgrh)rrw)rerfrgrh�cpr,r,r-rw sa�z3BentFunctionCayleyGraphClassification.from_functionNcCs�tj||d�}t�|d�}|��d}t||�}|j}t|�}	|	��}
d|
}|j�	�|kr2t
�|
dks<|
dkr?|r?t�nt�}t
||�}
|jdk}|rTt
||�}nd}t
||�}tt|��D]b}|dkrmt||�}t�}tt|j��D]}|�|j|�}|||<qw|j��}t|�D]3}|j|}t|�D]'}||j||f|
||f<||j||f|||f<|j||f|||f<q�q�qa|��}|��|��||||
||d�S)a�
        Constructor from saved class parts.

        INPUTS:

        - ``prefix_basename`` -- string. The prefix to use with mangled_name()
          to obtain the file names of the saved class parts.
        - ``dir`` -- string, optional. The directory where the parts
          are located. Default is None, meaning the current directory.
        - ``limited_memory`` -- boolean, default is False.
          A flag indicating whether the classification might be too large to
          fit into memory.

        OUTPUT:

        An object of class BentFunctionCayleyGraphClassification,
        constructed from the saved class parts.

        EXAMPLES:

        A classification of the bent function defined by the polynomial
        :math:`x_1 + x_2 + x_1 x_2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassPart as BentFunctionCGCPart
            sage: import os.path
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: prefix = tmp_filename()
            sage: prefix_dirname = os.path.dirname(prefix)
            sage: prefix_basename = os.path.basename(prefix)
            sage: for row in range(4):
            ....:     c = BentFunctionCGCPart.from_function(f, c_start=row,c_stop=row+1)
            ....:     part_prefix = prefix_basename + "_" + str(row)
            ....:     c.save_mangled(
            ....:         part_prefix,
            ....:         dir=prefix_dirname)
            sage: cl1 = BentFunctionCGC.from_parts(
            ....:    prefix_basename,
            ....:    dir=prefix_dirname)
            sage: cl1.report(report_on_matrix_details=True)
            Algebraic normal form of Boolean function: x0*x1 + x0 + x1
            Function is bent.
            <BLANKLINE>
            Weight class matrix:
            [1 0 0 0]
            [0 0 1 0]
            [0 1 0 0]
            [0 0 0 1]
            <BLANKLINE>
            SDP design incidence structure t-design parameters: (True, (1, 4, 1, 1))
            <BLANKLINE>
            Classification of Cayley graphs and classification of Cayley graphs of duals are the same:
            <BLANKLINE>
            There are 2 extended Cayley classes in the extended translation class.
            <BLANKLINE>
            Matrix of indices of Cayley graphs:
            [0 1 1 1]
            [1 1 0 1]
            [1 0 1 1]
            [1 1 1 0]
            sage: for row in range(4):
            ....:     part_prefix = prefix_basename + "_" + str(row)
            ....:     BentFunctionCGCPart.remove_mangled(
            ....:         part_prefix,
            ....:         dir=prefix_dirname)
        )�dirz_[0-9]*.sobjrr7r8Nr�)r�mangled_name�glob�sortrr rrPr"�ncolsr]rrr
r#rTrW�dictr!rZr1r%r$rarbrc)reZprefix_basenamer�rhZmangled_part_prefixZfile_name_listZpart_nbr�partr rfrirjrkr"rgr#r$Zwhole_cg_indexZ
part_cg_indexrsrlZpart_crqror!r,r,r-�
from_parts�s~M�����


�


�
��
�����z0BentFunctionCayleyGraphClassification.from_partscCsH|durdS|j|jko#|j|jko#|j|jko#|j|jko#|j|jkS)a�
        Test for equality between classifications.

        WARNING:

        This test is for strict equality rather than mathematical equivalence.

        INPUT:

        - ``other`` - BentFunctionCayleyGraphClassification: another classification.

        OUTPUT:

        A Boolean value indicating whether ``self`` strictly equals ``other``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x0,x1> = BooleanPolynomialRing(2)
            sage: p = x0*x1
            sage: f1 = BentFunction(p)
            sage: c1 = BentFunctionCGC.from_function(f1)
            sage: f2 = BentFunction([0,0,0,1])
            sage: c2 = BentFunctionCGC.from_function(f2)
            sage: print(c2.algebraic_normal_form)
            x0*x1
            sage: print(c1 == c2)
            True
        NFr�rxr,r,r-rzs!
�
�
�
�z,BentFunctionCayleyGraphClassification.__eq__csHt|j�}|j}t|���fdd�t|�D���fdd�t|�D�}|S)a�
        Obtain a representative bent function corresponding to each extended Cayley class.

        INPUT:

        - ``self`` -- the current object.

        OUTPUT:

        A list of tuples `(i_n,j_n)`, each of which is the first index into
        the matrix `self.bent_cayley_graph_index_matrix` that contains the entry `n`.
        The first index is determined by ``argwhere``.

        EXAMPLES:

        The result for the bent function defined by the polynomial :math:`x_1 + x_2 + x_1 x_2`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R2.<x1,x2> = BooleanPolynomialRing(2)
            sage: p = x1+x2+x1*x2
            sage: f = BentFunction(p)
            sage: c = BentFunctionCGC.from_function(f)
            sage: c.first_matrix_index_list()
            [(0, 0), (0, 1)]
        csg|]}t�|k��qSr,)r�r@�index)�ci_arrayr,r-rGhs
��zQBentFunctionCayleyGraphClassification.first_matrix_index_list.<locals>.<listcomp>cs:g|]}�|jddkrdnt�|ddd�f��qS)rN)�shape�tupler�)�ci_wherer,r-rGks���)rWr!r"rrT)r(�tot_cayley_graph_classesr��cb_listr,)r�r�r-�first_matrix_index_listGs

�
�z=BentFunctionCayleyGraphClassification.first_matrix_index_listc
sN	d��fdd�	}|j}td|�t|�}|���|��}d|�td|��r)dndd	�td
�|j}|r>td�t|�td
�tdd
d�t|�}t|jdd��|j	}	|j
}
|j}|��}td
�|dkrxtd�|||||	||
�dStdd
d�tdd
d�|
|kr�td�|||||	||
�dStd�|||||	||
|�dS)a�
        Print a report on the classification.

        The report includes attributes and various computed quantities.

        INPUT:

        - ``self`` -- the current object.
        - ``report_on_matrix_details`` -- Boolean (default: False).
           If True, print each matrix.
        - ``report_on_graph_details`` -- Boolean (default: False).
           If True, produce a detailed report for each Cayley graph.

        OUTPUT:

        (To standard output)
        A report on the following attributes of ``self``:

        - ``algebraic_normal_form``
        - ``cayley_graph_class_list``
        - If report_on_matrix_details is ``True``:
           - ``bent_cayley_graph_index_matrix``
           - ``dual_cayley_graph_index_matrix``
             (only if this is not ``None`` and is different from ``bent_cayley_graph_index_matrix``)
           - ``weight_class_matrix``
        - If report_on_graph_details is ``True``:
          details of each graph in ``cayley_graph_class_list``.

        EXAMPLES:

        Report on the classification of the bent function defined by
        the polynomial :math:`x_0 + x_0 x_1 + x_2 x_3`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R4.<x0,x1,x2,x3> = BooleanPolynomialRing(4)
            sage: p = x0+x0*x1+x2*x3
            sage: f = BentFunction(p)
            sage: c = BentFunctionCGC.from_function(f)
            sage: c.report(report_on_matrix_details=True, report_on_graph_details=True)
            Algebraic normal form of Boolean function: x0*x1 + x0 + x2*x3
            Function is bent.
            <BLANKLINE>
            Weight class matrix:
            [0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 1]
            [0 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0]
            [1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1]
            [0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1]
            [0 1 0 0 1 0 1 1 0 1 0 0 0 1 0 0]
            [0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1]
            [1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0]
            [0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0]
            [0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0]
            [0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1]
            [1 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0]
            [0 0 1 0 0 0 1 0 1 1 0 1 0 0 1 0]
            [1 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0]
            [1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1]
            [0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0]
            [1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0]
            <BLANKLINE>
            SDP design incidence structure t-design parameters: (True, (2, 16, 6, 2))
            <BLANKLINE>
            Classification of Cayley graphs and classification of Cayley graphs of duals are the same:
            <BLANKLINE>
            There are 2 extended Cayley classes in the extended translation class.
            <BLANKLINE>
            Matrix of indices of Cayley graphs:
            [0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 1]
            [0 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0]
            [1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 1]
            [0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 1]
            [0 1 0 0 1 0 1 1 0 1 0 0 0 1 0 0]
            [0 0 0 1 1 1 1 0 0 0 0 1 0 0 0 1]
            [1 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0]
            [0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0]
            [0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0]
            [0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1]
            [1 0 0 0 1 0 0 0 0 1 1 1 1 0 0 0]
            [0 0 1 0 0 0 1 0 1 1 0 1 0 0 1 0]
            [1 0 1 1 0 1 0 0 0 1 0 0 0 1 0 0]
            [1 1 1 0 0 0 0 1 0 0 0 1 0 0 0 1]
            [0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0]
            [1 1 0 1 0 0 1 0 0 0 1 0 0 0 1 0]
            <BLANKLINE>
            For each extended Cayley class in the extended translation class:
            Clique polynomial, strongly regular parameters, rank, and order of a representative graph; and
            linear code and generator matrix for a representative bent function:
            <BLANKLINE>
            EC class 0 :
            Algebraic normal form of representative: x0*x1 + x0 + x2*x3
            Clique polynomial: 8*t^4 + 32*t^3 + 48*t^2 + 16*t + 1
            Strongly regular parameters: (16, 6, 2, 2)
            Rank: 6 Order: 1152
            <BLANKLINE>
            Linear code from representative:
            [6, 4] linear code over GF(2)
            Generator matrix:
            [1 0 0 0 0 1]
            [0 1 0 1 0 0]
            [0 0 1 1 0 0]
            [0 0 0 0 1 1]
            Linear code is projective.
            Weight distribution: {0: 1, 2: 6, 4: 9}
            <BLANKLINE>
            EC class 1 :
            Algebraic normal form of representative: x0*x1 + x0 + x1 + x2*x3
            Clique polynomial: 16*t^5 + 120*t^4 + 160*t^3 + 80*t^2 + 16*t + 1
            Strongly regular parameters: (16, 10, 6, 6)
            Rank: 6 Order: 1920
            <BLANKLINE>
            Linear code from representative:
            [10, 4] linear code over GF(2)
            Generator matrix:
            [1 0 1 0 1 0 0 1 0 0]
            [0 1 1 0 1 1 0 1 1 0]
            [0 0 0 1 1 1 0 0 0 1]
            [0 0 0 0 0 0 1 1 1 1]
            Linear code is projective.
            Weight distribution: {0: 1, 4: 5, 6: 10}

        REFERENCES:

        - [Leo2017]_.
        Ncs�dd�}tj}tt�|��}	td�td|	dd�td�t|�}
|dkrHtt�|��}td|dd�td	dd�td
�td|
dd�td�|rhtd�td
�t|�|dkrhtddd�td�t|�|sldStd�td�tddd�td�td�t|
�D�]\}td�td|d�||}
|
dkr�td�q�t|
d�}t|
d�}�|�}|�|||��t	�fdd�t��D��}|�
�}td|�t||�}t|�}tddd�t|j
�tddd�t|j�td|jdd�td|j�|dk�r�|||f}||k�r�td �td!|�t||�}t|�}td"dd�|d#|j
|j
�td�td$dd�|d%|j|j�td�td&dd�|d#|j|j�td'dd�|d#|j|j�td�|�r�t|jtd(�����rutd)�n td�td*dd�|j}t|�|j��r�d#nd+dd�td,�td�td-�|��}t|�td.�t|�����td/dd�t|���r�d#nd+dd�td0�td1dd�|���tt�fd2d�tt���D���q�dS)3z�
            Report on the Cayley graphs and linear codes given by the
            representative bent functions in the extended translation class.
            cSs t||kr	|dn|dd�dS)Nz
 the same.r9r:�rU)Zverb�aror,r,r-�
print_compares

�
�ziBentFunctionCayleyGraphClassification.report.<locals>.graph_and_linear_code_report.<locals>.print_compare�z	There arer9r:z:extended Cayley classes in the extended translation class.Nz.extended Cayley classes of dual bent functionsz"in the extended translation class,�andz0extended Cayley classes in the union of the two.z#Matrix of indices of Cayley graphs:z"Matrix of indices of Cayley graphszof dual bent functions:zAFor each extended Cayley class in the extended translation class:z/Clique polynomial, strongly regular parameters,z.rank, and order of a representative graph; andzDlinear code and generator matrix for a representative bent function:zEC class�:zNo such representative graph.rrEcrFr,r,r?rBr,r-rG;rHzfBentFunctionCayleyGraphClassification.report.<locals>.graph_and_linear_code_report.<locals>.<listcomp>z(Algebraic normal form of representative:zClique polynomial:zStrongly regular parameters:zRank:zOrder:z/Cayley graph of dual of representative differs:zIndex iszClique polynomial�iszStrongly regular parameters�areZRank�Orderr7zOrder is a power of 2.zAutomorphism group�is notzisomorphic.z Linear code from representative:zGenerator matrix:zLinear codezprojective.zWeight distribution:cs$g|]}�|dkr|�|f�qS)rr,)r@�w)�wdr,r-rGxs
�
�)rM�verboserW�np�uniquerUrTrrRrr rr�stored_clique_polynomial�strongly_regular_parameters�rankZgroup_orderr�
is_integer�automorphism_group�
is_isomorphic�linear_code�generator_matrix�echelon_form�
is_projective�weight_distributionr�)rf�report_on_matrix_details�report_on_graph_detailsr!Z
pair_c_b_listr"r#r�r�Znbr_bent_cayley_graph_classesr�Znbr_dual_cayley_graph_classesr��c_brqrorpZbent_fbc�p�g�sZ
dual_indexZdual_gZdual_sZdual_a�lc�rmrj)rCr�r-�graph_and_linear_code_report�s���






��
�

��
��zRBentFunctionCayleyGraphClassification.report.<locals>.graph_and_linear_code_reportz*Algebraic normal form of Boolean function:r7�Functionr�r�zbent.r�zWeight class matrix:z3SDP design incidence structure t-design parameters:r9r:T)�return_parametersz Classification of Cayley graphs:z#Classification of Cayley graphs andz(classification of Cayley graphs of dualsz
are the same:zdiffer in matrices of indexes:r>)
r rUrrRrP�is_bentr$r�is_t_designr!r"r#r�)
r(r�r�r�r�rfri�D�Ir�r�r�r�r,r�r-�reportssr�
���z,BentFunctionCayleyGraphClassification.report�(�cCsJdd�}dd�}|�|j}tt|��D]�}|dkr*||dkr*|�td�|�t|d�t||�}t|�}t|jd�t|jd�|j}	td�t	|	�}
d}|dkr�t|
�|kr�|
�
d	d|�}|dkrot|
d
|��|dkr�|t|
�kr�td�td�|
|d
d
�}
|dkr�t|
�|ks\t|
�td�td�q|�d
S)a�
        Print a table of Cayley classes in LaTeX format.

        For a given classification, print, in LaTeX format, the table
        of selected properties of the Cayley classes of that classification.

        INPUT:

        - ``self`` -- the current object.
        - ``width`` -- integer (default: 40): the table width.
        - ``rows_per_table`` -- integer (default: 6). 
          The number of rows to include before starting a new table.

        OUTPUT:

        (To standard output.) A table in LaTeX format.

        EXAMPLES:

        Print the table of Cayley classes for the classification of the bent
        function defined by the polynomial :math:`x_0 + x_0 x_1 + x_2 x_3`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R4.<x0,x1,x2,x3> = BooleanPolynomialRing(4)
            sage: p = x0+x0*x1+x2*x3
            sage: f = BentFunction(p)
            sage: c = BentFunctionCGC.from_function(f)
            sage: c.print_latex_table_of_cayley_classes()
            \small{}
            \begin{align*}
            \def\arraystretch{1.2}
            \begin{array}{|cccl|}
            \hline
            \text{Class} &
            \text{Parameters} &
            \text{2-rank} &
            \text{Clique polynomial}
            \\
            \hline
            0 &
            (16, 6, 2, 2) &
            6 &
            \begin{array}{l}
            8t^{4} + 32t^{3} + 48t^{2} + 16t + 1
            \end{array}
            \\
            1 &
            (16, 10, 6, 6) &
            6 &
            \begin{array}{l}
            16t^{5} + 120t^{4} + 160t^{3}
            \,+
            \\
            80t^{2} + 16t + 1
            \end{array}
            \\
            \hline
            \end{array}
            \end{align*}
        cSs\td�td�td�td�td�td�td�td�td	�td
�td�dS)Nz\small{}�\begin{align*}�\def\arraystretch{1.2}z\begin{array}{|cccl|}�\hline�\text{Class} &�\text{Parameters} &z\text{2-rank} &z\text{Clique polynomial}�\\r�r,r,r,r-�print_latex_header�szeBentFunctionCayleyGraphClassification.print_latex_table_of_cayley_classes.<locals>.print_latex_headercSstd�td�td�dS)Nr��\end{array}�\end{align*}r�r,r,r,r-�print_latex_footerszeBentFunctionCayleyGraphClassification.print_latex_table_of_cayley_classes.<locals>.print_latex_footerrz\newpage�&z\begin{array}{l}�+Nz\,+r�rEr�)r!rTrWrUrrr�r�r�r�rfind)r(�widthZrows_per_tabler�r�r��nr�Zsrgr��lf�cutr,r,r-�#print_latex_table_of_cayley_classes�s>@
�

zIBentFunctionCayleyGraphClassification.print_latex_table_of_cayley_classescCs�td�td�td�td�td�td�td�td�td�t�}d	d
�|D�}dd
�|D�}t�}dd
�|D�}d
d
�|D�}|j}tt|��D]j}	||	}
tt|��D]+}|
||kr�t|	ddd�t||�tddd�t|ddd�td�td�q[tt|��D]+}|
||kr�t|	ddd�t||�tddd�t|ddd�td�td�q�qOtd�td�td�dS)a�
        Print a table comparing Cayley graphs with graphs from Tonchev's codes.

        Tonchev's codes are binary projective two-weight codes
        as published by Tonchev [Ton1996]_, [Ton2007]_.

        INPUT:

        - ``self`` -- the current object.
        - ``width`` -- integer (default: 40): the table width.
        - ``algorithm`` -- string (default: ``default_algorithm``).
          Algorithm used for canonical labelling.

        OUTPUT:

        (To standard output.) A table in LaTeX format.

        .. NOTE::

            The comparison displayed in this table really only makes sense for
            bent functions in 6 dimensions.

        EXAMPLES:

        The classification for the bent function defined by the polynomial
        :math:`x_0 x_1 + x_2 x_3 + x_4 x_5`.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: R6.<x0,x1,x2,x3,x4,x5> = BooleanPolynomialRing(6)
            sage: p = x0*x1 + x2*x3 + x4*x5
            sage: f = BentFunction(p)
            sage: c = BentFunctionCGC.from_function(f) # long time (60 seconds)
            sage: c.print_latex_table_of_tonchev_graphs() # long time (depends on line above)
            \begin{align*}
            \def\arraystretch{1.2}
            \begin{array}{|ccl|}
            \hline
            \text{Class} &
            \text{Parameters} &
            \text{Reference}
            \\
            \hline
            0 & [35,6,16] & \text{Table 1.156 1 (complement)}
            \\
            0 & [35,6,16] & \text{Table 1.156 2 (complement)}
            \\
            1 & [27,6,12] & \text{Table 1.155 1 }
            \\
            \hline
            \end{array}
            \end{align*}

        REFERENCES:

        - [Ton1996]_.

        - [Ton2007]_.
        r�r�z\begin{array}{|ccl|}r�r�r�z\text{Reference}r�cS�g|]}t|��qSr,r�r@�twr,r,r-rGv���z]BentFunctionCayleyGraphClassification.print_latex_table_of_tonchev_graphs.<locals>.<listcomp>cSs g|]}t|�jtd����qS�r<)r	rYr=r[�r@r�r,r,r-rGys��cSr�r,rr�r,r,r-rG~r�cSs$g|]}t|���jtd����qSr�)r	r_rYr=r[r�r,r,r-rG�s��r�r9r:z& \text{Table 1.155rE�}z& \text{Table 1.156z
(complement)}r�r�N)rUrrr!rTrWr)r(r�Ztw_155Zlc_155Zsr_155Ztw_156Zlc_156Zsr_156r�r�rr�kr,r,r-�#print_latex_table_of_tonchev_graphs-s`>�������	zIBentFunctionCayleyGraphClassification.print_latex_table_of_tonchev_graphs�
gist_sterncCsBd}|j}|D]}tt||�|d�}|�|d|d�qdS)a�
        Plot the matrix attributes to figure files.

        Use ``matrix_plot`` to plot the matrix attributes
        ``bent_cayley_graph_index_matrix``, ``dual_cayley_graph_index_matrix``,
        and ``weight_class_matrix`` to corresponding figure files.

        INPUT:

        - ``self`` -- the current object.
        - ``figure_name`` -- string. 
          The prefix to use in the file names for the figures.
        - ``cmap`` -- string (default: ``'gist_stern'``). 
          The colormap to use with ``matrixplot``.

        OUTPUT:

        (To figure files:
        ``figure_name`` + ``"_bent_cayley_graph_index_matrix.png"``,
        ``figure_name`` + ``"_dual_cayley_graph_index_matrix.png"``,
        ``figure_name`` + ``"_weight_class_matrix.png"``) Plots of the corresponding
        matrix attributes.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import glob
            sage: import os
            sage: bf = BentFunction([1,1,0,1])
            sage: dim = bf.nvariables()
            sage: c = BentFunctionCGC.from_function(bf)
            sage: figure_name = tmp_filename()
            sage: c.save_matrix_plots(figure_name)
            sage: figure_list = glob.glob(figure_name+"*.png")
            sage: for figure in figure_list:
            ....:     print(
            ....:         "_bent_cayley_graph_index_matrix.png" in figure or
            ....:         "_dual_cayley_graph_index_matrix.png" in figure or
            ....:         "_weight_class_matrix.png" in figure)
            ....:     print(os.path.isfile(figure))
            ....:     os.remove(figure)
            True
            True
            True
            True
            True
            True
        )r"r#r$)�cmap�_z.pngN)�__dict__r
r
�save)r(Zfigure_namer�Zmatrix_names�
attributes�name�graphicr,r,r-�save_matrix_plots�s7�z7BentFunctionCayleyGraphClassification.save_matrix_plotscCsz|j}ddg}t|d��'}tj||d�}|��tt|��D]}|�|||d��qWd�dS1s6wYdS)ak
        Save the Cayley graph class list to a csv file.

        INPUT:

        - ``file_name`` -- the name of the csv file.

        OUTPUT:

        None.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([1,0,1,1])
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c2.save_cg_class_list_as_csv(csv_name)
            sage: cgcl_saved = BentFunctionCGC.cg_class_list_from_csv(csv_name)
            sage: print(cgcl_saved == c2.cayley_graph_class_list)
            True
            sage: os.remove(csv_name)
        �cayley_graph_indexrYr��r�)r�rYN)r!r�r��
DictWriter�writeheaderrTrW�writerow)r(r�r�r�Z
cg_class_file�writerr�r,r,r-�save_cg_class_list_as_csv�s"��
��"�z?BentFunctionCayleyGraphClassification.save_cg_class_list_as_csvc	Cs�t|j�}|��}d|}|j}|j}|j}gd�}|dur#|�d�t|d��B}	tj	|	|d�}
|
�
�t|�D])}t|�D]"}|||||f|||fd�}
|dur[|||f|
d<|
�|
�q>q8Wd�dS1smwYdS)a�
        Save the matrices bent_cayley_graph_index_matrix,
        dual_cayley_graph_index_matrix and weight_class_matrix to a csv file.

        INPUT:

        - ``file_name`` -- the name of the csv file.

        OUTPUT:

        None.

        EXAMPLES::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([0,1,1,1])
            sage: dim = bf2.nvariables()
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c2.save_matrices_as_csv(csv_name)
            sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
            sage: print(c2.bent_cayley_graph_index_matrix == ci_matrix)
            True
            sage: print(c2.dual_cayley_graph_index_matrix == di_matrix)
            True
            sage: print(c2.weight_class_matrix == wc_matrix)
            True
            sage: os.remove(csv_name)

        TESTS:

            Test the case where list_dual_graphs=False and dual_cayley_graph_index_matrix is None.

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf = BentFunction([1,0,1,1])
            sage: dim = bf.nvariables()
            sage: c = BentFunctionCGC.from_function(bf, list_dual_graphs=False)
            sage: csv_name = tmp_filename(ext=".csv")
            sage: c.save_matrices_as_csv(csv_name)
            sage: (ci_matrix,di_matrix,wc_matrix) = BentFunctionCGC.matrices_from_csv(dim, csv_name)
            sage: print(c.bent_cayley_graph_index_matrix == ci_matrix)
            True
            sage: print(c.dual_cayley_graph_index_matrix == di_matrix)
            True
            sage: print(c.weight_class_matrix == wc_matrix)
            True
            sage: os.remove(csv_name)

        r7)rorqr�rNr�r�r�)
rr rPr"r#r$r�r�r�r�r�rTr�)r(r�rfrirjr�r�r�r�Zmatrix_filerrqro�row_dictr,r,r-�save_matrices_as_csvsB
:��

�	
����"�z:BentFunctionCayleyGraphClassification.save_matrices_as_csvcCsFt|�}t|j�}|�||j�|�||j�|�||j�dS)a�
        Save the classification as three csv files with a common prefix.

        INPUT:

        - ``self`` -- the current object.
        - ``file_name_prefix`` -- string: the common prefix to use for file names.

        OUTPUT:

        None.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.bent_function import BentFunction
            sage: from boolean_cayley_graphs.bent_function_cayley_graph_classification import BentFunctionCayleyGraphClassification as BentFunctionCGC
            sage: import os
            sage: bf2 = BentFunction([0,0,0,1])
            sage: c2 = BentFunctionCGC.from_function(bf2)
            sage: prefix = tmp_filename()
            sage: c2.save_as_csv(prefix)
            sage: c2_saved = BentFunctionCGC.from_csv(prefix)
            sage: print(c2 == c2_saved)
            True
            sage: bent_function_csv_name = prefix + BentFunctionCGC.bent_function_csv_suffix
            sage: os.remove(bent_function_csv_name)
            sage: cg_class_list_csv_name = prefix + BentFunctionCGC.cg_class_list_csv_suffix
            sage: os.remove(cg_class_list_csv_name)
            sage: matrices_csv_name = prefix + BentFunctionCGC.matrices_csv_suffix
            sage: os.remove(matrices_csv_name)
        N)	r2rr �save_as_csvr�rr�rr�)r(r�rerfr,r,r-rqs$
���z1BentFunctionCayleyGraphClassification.save_as_csv)TF)NF)FF)r�r�)r�)r�)r3r{r|r}r�r�r�r.r6r~r�r�r�rwr�rzr�r�r�r�r�rrrr,r,r,r-r��sHN
*
U
9�g�+.
�
I
st
�B0ar�)=r}r�numpyrr�sage.coding.linear_coder�*sage.combinat.designs.incidence_structuresr�sage.functions.logr�sage.graphs.graphr�sage.graphs.strongly_regular_dbr	�sage.matrix.constructorr
�sage.misc.latexr�sage.misc.persistr�sage.plot.matrix_plotr
�sage.rings.integerr�sage.structure.sage_objectr�sysrr�r��#boolean_cayley_graphs.bent_functionrZ8boolean_cayley_graphs.binary_projective_two_weight_codesrr�*boolean_cayley_graphs.boolean_cayley_graphr�)boolean_cayley_graphs.boolean_linear_coderrZ/boolean_cayley_graphs.boolean_linear_code_graphrZ boolean_cayley_graphs.containersrr�boolean_cayley_graphs.saveablerZ,boolean_cayley_graphs.strongly_regular_graphr�"boolean_cayley_graphs.weight_classr�+boolean_cayley_graphs.cayley_graph_controls�cayley_graph_controlsrMr��os.path�osrrr�r,r,r,r-�<module>sL;