Source code for boolean_cayley_graphs.linear

r"""
Tests for GF(2) linear algebra
==============================

The ``linear`` module defines functions that
test for linearity of functions defined on
GF(2) vector spaces.

AUTHORS:

- Paul Leopardi (2023-01-16): initial version

"""
#*****************************************************************************
#       Copyright (C) 2016-2023 Paul Leopardi paul.leopardi@gmail.com
#
#  Distributed under the terms of the GNU General Public License (GPL)
#  as published by the Free Software Foundation; either version 2 of
#  the License, or (at your option) any later version.
#                  http://www.gnu.org/licenses/
#*****************************************************************************


from sage.matrix.constructor import Matrix
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
from sage.rings.integer import Integer
from boolean_cayley_graphs.integer_bits import base2

encoding = "UTF-8"


[docs]def is_linear(dim, perm, certificate=False): r""" Check if a permutation on `range(2**dim)` is linear on `GF(2)**dim`. INPUT: - ``dim`` -- the dimension of the GF(2) linear space. - ``perm`` -- a function from `range(2**dim)` to iself, usually a permutation. - ``certificate`` -- bool (default False). If true, return the GF(2) matrix that corresponds to the permutation. 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 corresponds to the permutation. EXAMPLES: :: sage: from boolean_cayley_graphs.linear import is_linear sage: dim = 2 sage: perm1 = lambda x: x*3 % 4 sage: is_linear(dim, perm1) True sage: is_linear(dim, perm1, certificate=True) ( [1 0] True, [1 1] ) sage: perm2 = lambda x: (x+1) % 4 sage: is_linear(dim, perm2) False sage: is_linear(dim, perm2, certificate=True) (False, None) """ v = 2**dim # If perm(0) != 0 then perm cannot be linear. if perm(0) != 0: return (False, None) if certificate else False # Check that perm is linear on each pair of basis vectors. possibly_linear = True for a in range(dim): for b in range(a + 1, dim): if perm(2**a) ^ perm(2**b) != perm((2**a) ^ (2**b)): possibly_linear = False break if not possibly_linear: break if not possibly_linear: return (False, None) if certificate else False # Create the GF(2) matrix corresponding to perm, assuming linearity. perm_matrix = Matrix(GF(2), [ base2(dim, Integer(perm(2**a))) for a in range(dim)]).transpose() # Check for each vector that the matrix gives the same result as perm. vm = Matrix(GF(2), [ base2(dim, Integer(x)) for x in range(v)]).transpose() linear = perm_matrix * vm == vm[:, [perm(x) for x in range(v)]] if certificate: return (True, perm_matrix) if linear else (False, None) else: return linear