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

�Ul_T)�@s�dZddlZddlmmZddlmZddlm	Z	m
Z
ddlmZddl
mZddlmZddlmZdd	lmZdd
lmZddlmZddlmZdd
lmZddlmZddlm Z ddl!m"Z"ddl#Z#ddlZ$ddl%m&Z&ddl'm(Z(ddl'm)Z)ddl*m+Z+ddl,m-Z-ddl,m.Z.ddl/m0Z0ddl1m2Z2ddl1m3Z3ddl4m5Z5ddl6m7Z7ddl8m9Z9ddl:m;Z<ddl=Z=ddl>Z?dZ@Gdd�de e5�ZAGd d!�d!eA�ZBdS)"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]_.
�N)�datetime)�array�argwhere)�
LinearCode)�IncidenceStructure)�log)�Graph)�%strongly_regular_from_two_weight_code)�matrix)�latex)�load)�matrix_plot)�Integer)�
SageObject)�stdout)�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|_WnV|�d�|_|�d�|_|�d�|_|�dd�|_|�d�|_|�d�|_Yn0dS)	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.|
}n
t||
�}|��}|	dksT|	dkrZ|rZt�nt�}||}
t|
|
�}|r�t|
|
�}nd}t|
|
�}|�	�}|�
�}|�	�}t|
�D�]�}|r�tt
��|dd�tt|��t��||�}t||�D�]^}|�	|||��t|	��j|d�}|�|���}|||||f<t�fdd�t|
�D��}t|
|�}|||||f<|�r�|d	k�r�|d
k�r�tdt|���|r�t�fdd
�t|
�D��}|�
�j	|d�}t|	|�j|d�}|�|���}|||||f<|r�|	dkr�t|	��}|d	k�r|j|d�n|��j|d�} | |kr�tdt|�dt|���q�|��q�|��}!|��|� �|�r�|�!�}"||"k�r�tdt|�dt|"���|�r�t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>x�zABentFunctionCayleyGraphClassPart.from_function.<locals>.<genexpr>r�zWeight class is csg|]}�|��qSr,r,r>rAr,r-�
<listcomp>�rDzBBentFunctionCayleyGraphClassPart.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=rLrM�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_indexZblcg�lgr!rbr,rAr-�
from_function�s�c
����


��
������

�����z.BentFunctionCayleyGraphClassPart.from_functioncCsT|durdS|j|jkoR|j|jkoR|j|jkoR|j|jkoR|j|jkoR|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
        NFrJ�r(�otherr,r,r-�__eq__�s!
�
�
�
�
�z'BentFunctionCayleyGraphClassPart.__eq__)
r3�
__module__�__qualname__�__doc__r.r6�classmethod�default_algorithmrvryr,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�Zd-dd�Zd.dd�Zd/d d!�Zd0d#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�z4|d}|j|_|j|_|j|_|j|_|j|_WnJ|�d�|_|�d�|_|�d�|_|�dd�|_|�d�|_Yn0dS)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_cCsRg}t|��2}t�|�}|D]}|�|d�qWd�n1sD0Y|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)

        rWN)�open�csv�
DictReader�append)rc�	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|���}t�|�}|j}t||�}t||�}d|vrHt||�nd}	|D]T}
t|
d�}t|
d�}|
d|||f<|
d|||f<d|vrP|
d|	||f<qPWd�n1s�0Y||	|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_indexNrorm�bent_cayley_graph_indexr)r�r�r��
fieldnamesr
�int)
rcrgr�rhr�r�r��	ci_matrix�	wc_matrix�	di_matrixr�rormr,r,r-�matrices_from_csv�s$@



��0z7BentFunctionCayleyGraphClassification.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_suffixrNr��matrices_csv_suffix)	rc�file_name_prefixrdr r!rgr"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]}
        )rerf)rrv)rcrdrerf�cpr,r,r-rv sa�z3BentFunctionCayleyGraphClassification.from_functionNcCs�tj||d�}t�|d�}|��d}t||�}|j}t|�}	|	��}
d|
}|j�	�|krdt
�|
dksx|
dkr~|r~t�nt�}t
||�}
|jdk}|r�t
||�}nd}t
||�}tt|��D]�}|dkr�t||�}t�}tt|j��D]}|�|j|�}|||<q�|j��}t|�D]j}|j|}t|�D]P}||j||f|
||f<||j||f|||f<|j||f|||f<�q4�qq�|��}|��|��||||
||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 rrNr"�ncolsr[rrr
r#rRrU�dictr!rXr1r%r$r_r`ra)rcZprefix_basenamer�rfZmangled_part_prefixZfile_name_listZpart_nbr�partr rdrgrhrir"rer#r$Zwhole_cg_indexZ
part_cg_indexrqrjZpart_crormr!r,r,r-�
from_parts�szM�����


�


��
��
��z0BentFunctionCayleyGraphClassification.from_partscCsH|durdS|j|jkoF|j|jkoF|j|jkoF|j|jkoF|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�rwr,r,r-rys!
�
�
�
�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-rFhs�zQBentFunctionCayleyGraphClassification.first_matrix_index_list.<locals>.<listcomp>cs:g|]2}�|jddkrdnt�|ddd�f��qS)rN)�shape�tupler�)�ci_wherer,r-rFks��)rUr!r"rrR)r(�tot_cayley_graph_classesr��cb_listr,)r�r�r-�first_matrix_index_listGs

�
�z=BentFunctionCayleyGraphClassification.first_matrix_index_listc
sJd��fdd�	}|j}td|�t|�}|���|��}d|�td|��rPdndd	�td
�|j}|rztd�t|�td
�tdd
d�t|�}t|jdd��|j	}	|j
}
|j}|��}td
�|dkr�td�|||||	||
�nZtdd
d�tdd
d�|
|k�r*td�|||||	||
�ntd�|||||	||
|�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|�}
|dkr�tt�|��}td|dd�td	dd�td
�td|
dd�td�|r�td�td
�t|�|dkr�tddd�td�t|�|s�dStd�td�tddd�td�td�t|
�D�]�}td�td|d�||}
|
dk�rDtd��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(�����r�td)�n@td�td*dd�|j}t|�|j��rd#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:�rS)�verb�armr,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.rrEcsg|]}�|��qSr,r,r>rAr,r-rF;rDzfBentFunctionCayleyGraphClassification.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-rFxs)rK�verboserU�np�uniquerSrRrrPrr rr�stored_clique_polynomial�strongly_regular_parameters�rank�group_orderr�
is_integer�automorphism_group�
is_isomorphic�linear_code�generator_matrix�echelon_form�
is_projective�weight_distributionr�)rd�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�Zc_brormrnZbent_fbc�p�g�sZ
dual_indexZdual_gZdual_sZdual_a�lc�rkrh)rBr�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:)N)
r rSrrPrN�is_bentr$r�is_t_designr!r"r#r�)
r(r�r�r�r�rdrg�D�Ir�r�r�r�r,r�r-�reportssr�
�
��z,BentFunctionCayleyGraphClassification.report�(�cCsBdd�}dd�}|�|j}tt|��D�]}|dkrV||dkrV|�td�|�t|d�t||�}t|�}t|jd�t|jd�|j}	td�t	|	�}
d}|dk�rt|
�|k�r|
�
d	d|�}|dkr�t|
d
|��|dk�r|t|
�k�rtd�td�|
|d
d
�}
q�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�szeBentFunctionCayleyGraphClassification.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_footerszeBentFunctionCayleyGraphClassification.print_latex_table_of_cayley_classes.<locals>.print_latex_footerrz\newpage�&z\begin{array}{l}�+Nz\,+r�rEr�)r!rRrUrSrrr�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]�}	||	}
tt|��D]V}|
||kr�t|	ddd�t||�tddd�t|ddd�td�td�q�tt|��D]Z}|
||k�rt|	ddd�t||�tddd�t|ddd�td�td��qq�td�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�cSsg|]}t|��qSr,r�r?�twr,r,r-rFvs�z]BentFunctionCayleyGraphClassification.print_latex_table_of_tonchev_graphs.<locals>.<listcomp>cSs g|]}t|�jtd����qS�r<)r	rWr=rY�r?r�r,r,r-rFys�cSsg|]}t|��qSr,rr�r,r,r-rF~s�cSs$g|]}t|���jtd����qSr�)r	r]rWr=rYr�r,r,r-rF�s�r�r9r:z& \text{Table 1.155rE�}z& \text{Table 1.156z
(complement)}r�r�N)rSrrr!rRrUr)r(r�Ztw_155Zlc_155Zsr_155Ztw_156Zlc_156Zsr_156r�r�rp�kr,r,r-�#print_latex_table_of_tonchev_graphs-sZ>����
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
7z7BentFunctionCayleyGraphClassification.save_matrix_plotscCsx|j}ddg}t|d��L}tj||d�}|��tt|��D]}|�|||d��q<Wd�n1sj0YdS)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_indexrWr��r�)r�rWN)r!r�r��
DictWriter�writeheaderrRrU�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�}|durF|�d�t|d���}	tj	|	|d�}
|
�
�t|�D]R}t|�D]D}|||||f|||fd�}
|dur�|||f|
d<|
�|
�q|qpWd�n1s�0YdS)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)rmror�rNr�r�r�)
rr rNr"r#r$r�r�r�r�r�rRr�)r(r�rdrgrhr�r�r�r�Zmatrix_filer�rorm�row_dictr,r,r-�save_matrices_as_csvs<:
��

�	
��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�r�r�rr�)r(r�rcrdr,r,r-rqs$
���z1BentFunctionCayleyGraphClassification.save_as_csv)TF)NF)FF)r�r�)r�)r�)r3rzr{r|r�r�r�r.r6r}r�r�r�rvr�ryr�r�r�r�r�r�rrr,r,r,r-r�sFN
*
U
9�g�+.�
I
s
t�
B0ar)Cr|�builtins�@py_builtins�_pytest.assertion.rewrite�	assertion�rewrite�
@pytest_arr�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�Z#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_classrZ+boolean_cayley_graphs.cayley_graph_controlsZcayley_graph_controlsrKr��os.path�osr~rrr,r,r,r-�<module>sJ;&