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

B1�b�_�@s�dZddlZddlZddlmZddlmZddlmZ	ddl
mZddlm
Z
ddlmZdd	lmZdd
lmZddlmZmZddlmZd
ZGdd�dee�ZdS)a�
An improved Boolean function class
==================================

The ``boolean_function_improved`` module defines
the ``BooleanFunctionImproved`` class,
which is a subclass of BooleanFunction that adds extra methods.
One such method is ``cayley_graph``,
which returns the Cayley graph of the Boolean function.

AUTHORS:

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

EXAMPLES:

::

    sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
    sage: bf = BooleanFunctionImproved([0,0,0,1])
    sage: type(bf)
    <class 'boolean_cayley_graphs.boolean_function_improved.BooleanFunctionImproved'>
    sage: bf.truth_table(format='int')
    (0, 0, 0, 1)
�N)�BooleanFunction)�vector)�FiniteField)�Integer)�ZZ)�boolean_cayley_graph)�BooleanGraph)�boolean_linear_code��base2�inner)�SaveablezUTF-8c@s�eZdZdZedd��Zedd��Zedd��Zdd	�Zd
d�Z	dd
�Z
dd�Zdd�Zdd�Z
d%dd�Zd&dd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$S)'�BooleanFunctionImproveda6
    A subclass of BooleanFunction that adds extra methods.

    The class inherits from BooleanFunction is initialized in the same way.
    The class inherits from Saveable to obtain
    load_mangled and save_mangled methods.

    EXAMPLES:

    ::

        sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
        sage: bf1 = BooleanFunctionImproved([0,1,0,0])
        sage: type(bf1)
        <class 'boolean_cayley_graphs.boolean_function_improved.BooleanFunctionImproved'>
        sage: bf1.algebraic_normal_form()
        x0*x1 + x0
        sage: bf1.truth_table()
        (False, True, False, False)

    TESTS:

    ::

        sage: from sage.crypto.boolean_function import BooleanFunction
        sage: bf = BooleanFunctionImproved([0,1,0,0])
        sage: print(bf)
        Boolean function with 2 variables

        sage: from sage.crypto.boolean_function import BooleanFunction
        sage: bf = BooleanFunctionImproved([0,1,0,0])
        sage: latex(bf)
        \text{\texttt{Boolean{ }function{ }with{ }2{ }variables}}
   cCstt�|�t�}|�||�S)a�
        Constructor from the buffer tt_buffer.

        The buffer tt_buffer is assumed to be the result of method tt_buffer(),
        which returns a result of type buffer representing a truth table in hex.

        INPUT:

        - ``cls`` -- the class object.
        - ``dim`` -- integer: the dimension of the Boolean function.
        - ``tt_buffer`` -- buffer: the result of the method tt_buffer()
          for the Boolean function.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,0])
            sage: bf2_tt_buffer = bf2.tt_buffer()
            sage: bf2_test = BooleanFunctionImproved.from_tt_buffer(2, bf2_tt_buffer)
            sage: bf2_test.algebraic_normal_form()
            x0*x1 + x0
            sage: bf2 == bf2_test
            True
            sage: bf3 = BooleanFunctionImproved([0,1,0,0]*2)
            sage: bf3.nvariables()
            3
            sage: bf3_tt_buffer = bf3.tt_buffer()
            sage: bf3_test = BooleanFunctionImproved.from_tt_buffer(3, bf3_tt_buffer)
            sage: bf3 == bf3_test
            True
        )�str�binascii�b2a_hex�encoding�from_tt_hex)�cls�dim�	tt_buffer�tt_hex�r�S/home/user/Boolean-Cayley-graphs/boolean_cayley_graphs/boolean_function_improved.py�from_tt_bufferZs&z&BooleanFunctionImproved.from_tt_buffercCs8|dkr,t|d�}d|}t||�}t|�St|�SdS)a3
        Constructor from the dimension dim, and the string tt_hex.

        The string tt_hex is assumed to be the result of method tt_hex(), which returns
        a string representing a truth table in hex.

        INPUT:

        - ``cls`` -- the class object.
        - ``dim`` -- integer: the dimension of the Boolean function.
        - ``tt_hex`` -- string: the result of the method tt_hex() for the Boolean function.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,0])
            sage: bf2_tt_hex = bf2.tt_hex()
            sage: bf2_test = BooleanFunctionImproved.from_tt_hex(2, bf2_tt_hex)
            sage: bf2_test.algebraic_normal_form()
            x0*x1 + x0
            sage: bf2 == bf2_test
            True

        TESTS:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1])
            sage: bf1_tt_hex = bf1.tt_hex()
            sage: bf1_test = BooleanFunctionImproved.from_tt_hex(1, bf1_tt_hex)
            sage: bf1_test.algebraic_normal_form()
            x
            sage: bf1 == bf1_test
            True
            sage: bf3 = BooleanFunctionImproved([0,1,0,0]*2)
            sage: bf3.nvariables()
            3
            sage: bf3_tt_hex = bf3.tt_hex()
            sage: bf3_test = BooleanFunctionImproved.from_tt_hex(3, bf3_tt_hex)
            sage: bf3 == bf3_test
            True
        ���N)rrr)rrrZ
tt_integer�vZtt_bitsrrrr�s2

z#BooleanFunctionImproved.from_tt_hexcCsVt|��:}t�|�}t|�}t�t|d�|d�Wd�S1sH0YdS)a4
        Constructor from a csv file.

        The csv file is assumed to be produced by the method save_as_csv().

        INPUT:

        - ``cls`` -- the class object.
        - ``csv_file_name`` -- string: the name of the csv file to read from.

        EXAMPLES:

        ::

            sage: import csv
            sage: import os
            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([1,0,1,1])
            sage: bf2_csv_name = tmp_filename(ext='.csv')
            sage: bf2.save_as_csv(bf2_csv_name)
            sage: bf2_test = BooleanFunctionImproved.from_csv(bf2_csv_name)
            sage: bf2 == bf2_test
            True
            sage: os.remove(bf2_csv_name)
            sage: bf3 = BooleanFunctionImproved([0,1,0,0]*2)
            sage: bf3_csv_name = tmp_filename(ext='.csv')
            sage: bf3.save_as_csv(bf3_csv_name)
            sage: bf3_test = BooleanFunctionImproved.from_csv(bf3_csv_name)
            sage: bf3 == bf3_test
            True
        �
nvariablesrN)�open�csvZ
DictReader�nextrr�int)rZ
csv_file_nameZcsv_file�reader�rowrrr�from_csv�s#


�z BooleanFunctionImproved.from_csvcCst|�}t|�|�S)ag
        Return the complement Boolean function of `self`.

        INPUT:

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

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,1])
            sage: bf1 = ~bf0
            sage: type(bf1)
            <class 'boolean_cayley_graphs.boolean_function_improved.BooleanFunctionImproved'>
            sage: bf1.algebraic_normal_form()
            x0*x1 + x0
            sage: bf1.truth_table()
            (False, True, False, False)
        �r�type)�self�bf_selfrrr�
__invert__�sz"BooleanFunctionImproved.__invert__cCst|�}t|�||�S)a�
        Return the elementwise sum of `self`and `other` which must have the same number of variables.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another Boolean function.

        OUTPUT:

        The elementwise sum of `self`and `other`

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,0])
            sage: bf1 = BooleanFunctionImproved([1,1,0,0])
            sage: (bf0+bf1).truth_table(format='int')
            (0, 1, 1, 0)
            sage: S = bf0.algebraic_normal_form() + bf1.algebraic_normal_form()
            sage: (bf0+bf1).algebraic_normal_form() == S
            True

        TESTS:

        ::

            sage: bf0+BooleanFunctionImproved([0,1])
            Traceback (most recent call last):
            ...
            ValueError: the two Boolean functions must have the same number of variables
        r'�r)�otherr*rrr�__add__s#zBooleanFunctionImproved.__add__cCst|�}t|�||�S)a�
        Return the elementwise product of `self`and `other` which must have the same number of variables.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another Boolean function.

        OUTPUT:

        The elementwise product of `self`and `other`

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,0])
            sage: bf1 = BooleanFunctionImproved([1,1,0,0])
            sage: (bf0*bf1).truth_table(format='int')
            (1, 0, 0, 0)
            sage: P = bf0.algebraic_normal_form() * bf1.algebraic_normal_form()
            sage: (bf0*bf1).algebraic_normal_form() == P
            True

        TESTS:

        ::

            sage: bf0*BooleanFunctionImproved([0,1])
            Traceback (most recent call last):
            ...
            ValueError: the two Boolean functions must have the same number of variables
        r'r,rrr�__mul__-s#zBooleanFunctionImproved.__mul__cCst|�}t|�||B�S)a�
        Return the concatenation of `self` and `other` which must have the same number of variables.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another Boolean function.

        OUTPUT:

        The concatenation of `self`and `other`

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf0 = BooleanFunctionImproved([1,0,1,0])
            sage: bf1 = BooleanFunctionImproved([1,1,0,0])
            sage: (bf0|bf1).truth_table(format='int')
            (1, 0, 1, 0, 1, 1, 0, 0)
            sage: C = bf0.truth_table() + bf1.truth_table()
            sage: (bf0|bf1).truth_table(format='int') == C
            True

        TESTS:

        ::

            sage: bf0|BooleanFunctionImproved([0,1])
            Traceback (most recent call last):
            ...
            ValueError: the two Boolean functions must have the same number of variables
        r'r,rrr�__or__Ts#zBooleanFunctionImproved.__or__cCs|��}|��}t||�S)a*
        Return the Cayley graph of ``self``.

        INPUT:

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

        OUTPUT:

        The Cayley graph of ``self`` as an object of class ``Graph``.

        EXAMPLES::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1,0,0])
            sage: g1 = bf1.cayley_graph()
            sage: g1.adjacency_matrix()
            [0 1 0 0]
            [1 0 0 0]
            [0 0 0 1]
            [0 0 1 0]

        )r�extended_translater�r)r�frrr�cayley_graph{sz$BooleanFunctionImproved.cayley_graphcCs|d�r|��S|��S)a�
        Return the extended Cayley graph of ``self``.

        INPUT:

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

        OUTPUT:

        The extended Cayley graph of ``self`` as an object of class ``Graph``.
        This is the Cayley graph of ``self`` if ``self(0) == False``,
        otherwise it is the Cayley graph of ``~self``.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1,0,0])
            sage: g1 = bf1.extended_cayley_graph()
            sage: g1.adjacency_matrix()
            [0 1 0 0]
            [1 0 0 0]
            [0 0 0 1]
            [0 0 1 0]
            sage: bf2 = BooleanFunctionImproved([1,0,1,1])
            sage: g2 = bf2.extended_cayley_graph()
            sage: g2.adjacency_matrix()
            [0 1 0 0]
            [1 0 0 0]
            [0 0 0 1]
            [0 0 1 0]

        r)r4�r)rrr�extended_cayley_graph�s$��z-BooleanFunctionImproved.extended_cayley_graphrcs���������fdd�S)a�
        Return an extended translation equivalent function of ``self``.

        Given the non-negative numbers `b`, `c` and `d`, the function
        `extended_translate` returns the Python function

        :math:`x \mapsto \mathtt{self}(x + b) + \langle c, x \rangle + d`,

        as decribed below.

        INPUT:

        - ``self`` -- the current object.
        - ``b`` -- non-negative integer (default: 0)
          which is mapped to :math:`\mathbb{F}_2^{dim}`.
        - ``c`` -- non-negative integer (default: 0).
        - ``d`` -- integer, 0 or 1 (default: 0).

        OUTPUT:

        The Python function

        :math:`x \mapsto \mathtt{self}(x + b) + \langle c, x \rangle + d`,

        where `b` and `c` are mapped to :math:`\mathbb{F}_2^{dim}` by the
        lexicographical ordering implied by the ``base2`` function, and
        where ``dim`` is the number of variables of ``self`` as a
        ``BooleanFunction.``

        .. NOTE::

            While ``self`` is a ``BooleanFunction``, the result of
            ``extended_translate`` is *not* a ``BooleanFunction``,
            but rather a Python function that takes an ``Integer`` argument.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1,0,0])
            sage: f001 = bf1.extended_translate(b=0,c=0,d=1)
            sage: [f001(x) for x in range(4)]
            [1, 0, 1, 1]
        cs,�t�|�A���dkrdnt�|�A�AS)Nrr
)�x��b�c�drr)rr�<lambda>��z<BooleanFunctionImproved.extended_translate.<locals>.<lambda>)r)r)r9r:r;rr8rr1�s.z*BooleanFunctionImproved.extended_translateFcCs�|��}t|���}t|���}|j|dd�\}}|sB|r>dSdS|��}d|}	t|	�D]V}
ttd�t||
��}t	|t
||���||
�kr�|r�dndS|r�d|fndSdS)aa
        Check if there is a linear equivalence between ``self`` and ``other``:

        :math:`\mathtt{other}(M x) = \mathtt{self}(x)`,

        where M is a GF(2) matrix.

        INPUT:

        - ``self`` -- the current object.
        - ``other`` -- another object of class BooleanFunctionImproved.
        - ``certificate`` -- bool (default False). If true, return a GF(2) matrix
           that defines the isomorphism.

        OUTPUT:

        If ``certificate`` is false, a bool value.
        If ``certificate`` is true, a tuple consisting of either (False, None)
        or (True, M), where M is a GF(2) matrix that defines the equivalence.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1,0,0])
            sage: bf2 = BooleanFunctionImproved([0,0,1,0])
            sage: bf1.is_linear_equivalent(bf2)
            True
            sage: bf2.is_linear_equivalent(bf1, certificate=True)
            (
                  [0 1]
            True, [1 0]
            )

        T)�certificate)FNFrN)rrr4�is_linear_isomorphicr1�ranger�GFrr�list)r)r-r>rZself_bgZother_bgr?�MZself_etr�ixr7rrr�is_linear_equivalent�s %�
z,BooleanFunctionImproved.is_linear_equivalentcCs|��}|��}t||�S)a~
        Return the Boolean linear code corresponding to ``self``.

        INPUT:

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

        OUTPUT:

        An object of class ``LinearCode`` representing the Boolean linear code
        corresponding to self.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,1])
            sage: bf2.algebraic_normal_form()
            x0*x1*x2*x3 + x0*x1 + x0*x2*x3 + x0 + x1*x3 + x2*x3 + x3
            sage: c2 = bf2.linear_code()
            sage: c2.generator_matrix().echelon_form()
            [1 0 0 0 1]
            [0 1 0 0 0]
            [0 0 1 0 0]
            [0 0 0 1 1]

        REFERENCES:

        .. Carlet [Car2010]_ Section 8.6.

        .. Ding [Ding2015]_ Corollary 10.

        )rr1r	r2rrr�linear_code)s#z#BooleanFunctionImproved.linear_codecCsdddg}t|d��>}tj||d�}|��|�|��|��d��Wd�n1sV0YdS)aO
        Save the current object as a csv file.

        INPUT:

        - ``self`` -- the current object.
        - ``file_name`` -- the file name.

        OUTPUT:

        None.

        EXAMPLES:

        ::

            sage: import csv
            sage: import os
            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,1])
            sage: bf2_csv_name = tmp_filename(ext='.csv')
            sage: bf2.save_as_csv(bf2_csv_name)
            sage: with open(bf2_csv_name) as bf2_csv_file:
            ....:     reader = csv.DictReader(bf2_csv_file)
            ....:     for row in reader:
            ....:         print(row["nvariables"], row["tt_hex"])
            ....:
            2 a
            sage: os.remove(bf2_csv_name)
        rr�w)�
fieldnames)rrN)r r!Z
DictWriterZwriteheaderZwriterowrr)r)�	file_namerH�file�writerrrr�save_as_csvQs ��z#BooleanFunctionImproved.save_as_csvcCs2|��}|��}t|�dkr$d|n|}t�|�S)a�
        Return a buffer containing a compressed version of the truth table.

        INPUT:

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

        OUTPUT:

        A buffer containing a compressed version of the truth table of ``self``.

        EXAMPLES:

        ::

            sage: import binascii
            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,0])
            sage: buff_bf2 = bf2.tt_buffer()
            sage: type(buff_bf2)
            <class 'bytes'>
            sage: encoding = "UTF-8"
            sage: print(str(binascii.b2a_hex(buff_bf2), encoding))
            02

        TESTS:

        ::

            sage: bf3 = BooleanFunctionImproved([0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,1])
            sage: buff_bf3 = bf3.tt_buffer()
            sage: type(buff_bf3)
            <class 'bytes'>
            sage: encoding = "UTF-8"
            sage: print(str(binascii.b2a_hex(buff_bf3), encoding))
            c122
            sage: from_buff_bf3 = BooleanFunctionImproved.from_tt_buffer(3, buff_bf3)
            sage: from_buff_bf3 == buff_bf3
            False
            sage: from_buff_bf3 == bf3
            True
            sage: hex_str6 = "0123456789112345678921234567893123456789412345678951234567896123"
            sage: bf6 = BooleanFunctionImproved(hex_str6)
            sage: buff_bf6 = bf6.tt_buffer()
            sage: from_buff_bf6 = BooleanFunctionImproved.from_tt_buffer(6, buff_bf6)
            sage: from_buff_bf6 == bf6
            True
            sage: str(binascii.b2a_hex(buff_bf6), encoding) == hex_str6
            True
        r�0)rr�lenr�a2b_hex)r)rrZ	tt_stringrrrr}s3
�
�z!BooleanFunctionImproved.tt_buffercCsR|��}t|��d�}|�d�}|dkr.d}nd|d>}d|t|�}||S)a

        Return a hex string representing the truth table of the Boolean function.

        INPUT:

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

        OUTPUT:

        A string representing the truth table of ``self`` in hex.

        EXAMPLES:

        ::

            sage: import binascii
            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf2 = BooleanFunctionImproved([0,1,0,0])
            sage: str_bf2 = bf2.tt_hex()
            sage: type(str_bf2)
            <class 'str'>
            sage: print(str_bf2)
            2
            sage: bf3 = BooleanFunctionImproved([0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,1])
            sage: str_bf3 = bf3.tt_hex()
            sage: print(str_bf3)
            c122
        rr�rM)rr�truth_tablerrN)r)rZZZ_truth_table_2�ttZ
buffer_len�paddingrrrr�s
	zBooleanFunctionImproved.tt_hexcCst|jdd��S)a�
        Return the Hamming weight of ``self``.

        INPUT:

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

        OUTPUT:

        A positive integer giving the number of 1 bits in the truth table of ``self``,
        in other words, the cardinality of the support of ``self`` as a
        Boolean function.

        EXAMPLES:

        ::

            sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
            sage: bf1 = BooleanFunctionImproved([0,1,0,0])
            sage: bf2 = BooleanFunctionImproved([0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,1])
            sage: bf1.truth_table()
            (False, True, False, False)
            sage: bf1.weight()
            1
            sage: bf2.truth_table(format='int')
            (0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1)
            sage: sum([int(bf2(x)) for x in range(16)])
            5
            sage: bf2.weight()
            5
        r#)�format)�sumrQr5rrr�weight�s zBooleanFunctionImproved.weightN)rrr)F)�__name__�
__module__�__qualname__�__doc__�classmethodrrr&r+r.r/r0r4r6r1rErFrLrrrVrrrrr5s($
)
<
*'''(
2
7(,@3r)rZrr!�sage.crypto.boolean_functionr�sage.modules.vector_mod2_denser�0sage.rings.finite_rings.finite_field_constructorrrA�sage.rings.integerr�sage.rings.integer_ringrZ*boolean_cayley_graphs.boolean_cayley_graphrZ#boolean_cayley_graphs.boolean_graphrZ)boolean_cayley_graphs.boolean_linear_coder	Z"boolean_cayley_graphs.integer_bitsrrZboolean_cayley_graphs.saveabler
rrrrrr�<module>s#