Source code for boolean_cayley_graphs.boolean_graph
r"""
Boolean graphs
==============
The ``boolean_graph`` module defines
the ``BooleanGraph`` class,
which represents a Graph whose order is a power of 2.
AUTHORS:
- Paul Leopardi (2017-11-11): initial version
"""
#*****************************************************************************
# Copyright (C) 2017 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 math import log
from sage.graphs.graph import Graph
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
from boolean_cayley_graphs.linear import is_linear
from boolean_cayley_graphs.saveable import Saveable
default_algorithm = "sage"
[docs]class BooleanGraph(Graph, Saveable):
"""
A Graph whose order is a power of 2.
EXAMPLES:
::
sage: from boolean_cayley_graphs.boolean_graph import BooleanGraph
sage: g16 = BooleanGraph(16)
sage: g16.order()
16
TESTS:
::
sage: from boolean_cayley_graphs.boolean_graph import BooleanGraph
sage: g16 = BooleanGraph(16)
sage: print(g16)
Graph on 16 vertices
"""
def __init__(self, *args, **kwargs):
"""
A Graph whose order is a power of 2.
EXAMPLES:
::
sage: from boolean_cayley_graphs.boolean_graph import BooleanGraph
sage: g16 = BooleanGraph(8)
sage: g16.order()
8
"""
super(BooleanGraph, self).__init__(*args, **kwargs)
if not log(self.order(),2).is_integer():
raise ValueError
[docs] def is_linear_isomorphic(
self,
other,
certificate=False,
algorithm=default_algorithm):
r"""
Check that the two BooleanGraphs ``self`` and ``other`` are isomorphic
and that the isomorphism is given by a GF(2) linear mapping on the
vector space of vertices.
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 isomorphism.
EXAMPLES:
::
sage: from boolean_cayley_graphs.boolean_function_improved import BooleanFunctionImproved
sage: from boolean_cayley_graphs.boolean_graph import BooleanGraph
sage: bf1 = BooleanFunctionImproved([0,1,0,0])
sage: cg1 = BooleanGraph(bf1.cayley_graph())
sage: bf2 = BooleanFunctionImproved([0,0,1,0])
sage: cg2 = BooleanGraph(bf2.cayley_graph())
sage: cg1.is_linear_isomorphic(cg2)
True
sage: cg2.is_linear_isomorphic(cg1, certificate=True)
(
[0 1]
True, [1 0]
)
"""
# Check the isomorphism between self and other via canonical labels.
# This is to work around the slow speed of is_isomorphic in some cases.
if self.canonical_label() != other.canonical_label():
return (False, None) if certificate else False
# Obtain the mapping that defines the isomorphism.
is_isomorphic, mapping_dict = self.is_isomorphic(other, certificate=True)
# If self is not isomorphic to other, it is not linear equivalent.
if not is_isomorphic:
return (False, None) if certificate else False
mapping = lambda x: mapping_dict[x]
v = self.order()
dim = Integer(log(v, 2))
# Check that mapping is linear.
if certificate:
linear, mapping_matrix = is_linear(dim, mapping, certificate)
else:
linear = is_linear(dim, mapping)
if linear:
return (True, mapping_matrix) if certificate else True
# For each permutation p in the automorphism group of self,
# check that the permuted mapping is linear.
auto_group = self.automorphism_group()
test_group = auto_group.stabilizer(0) if mapping(0) == 0 else auto_group
linear = False
for p in test_group:
p_mapping = lambda x: p(mapping(x))
# Check that p_mapping is linear.
if certificate:
linear, mapping_matrix = is_linear(dim, p_mapping, certificate)
else:
linear = is_linear(dim, p_mapping)
# We only need to find one linear p_mapping that preserves other.
if linear:
break
if certificate:
return (True, mapping_matrix) if linear else (False, None)
else:
return linear