Zhegalkin matrix
Studies of Boolean functions |
ANF matrix twins |
noble gentle |
smallest Zhegalkin index |
The Zhegalkin matrix is an infinite binary matrix.
It is closely related to the infinite integer matrix of Gray code permutation powers ( A195467) and to the algebraic normal form (ANF) of Boolean functions.
(Ivan Zhegalkin was the inventor of the ANF. The naming choices made here are new.)
Its colums are the truth tables of all Boolean functions. The column index is the Zhegalkin index of the respective Boolean function.
Its rows are a subset of the Walsh functions, namely the XORs of atoms forming a Sierpiński triangle ( A001317).
as rows of a binary Walsh matrix |
---|
This is a 256×256 binary Walsh matrix. Each row is the variadic XOR of the atoms shown in the 256×8 matrix on the left. |
Zhegalkin permutation
edit0 | 1 | 2 | 3 | 4 | |
1×2 | 2×4 | 4×16 | 8×256 | 16×65536 |
For arity the map from ANFs to truth tables gives a finite Zhegalkin matrix of size . (It is the top left corner of the infinite matrix.)
It can be interpreted as a permutation of the integers ,
which shall be called Zhegalkin permutation .
Keys and values in Πn shall be called Zhegalkin twins — e.g. 7 and 9 are Zhegalkin twins for arity 2.
It is a self-inverse Walsh permutation of degree 2n. The corresponding element of GL(2n, 2) is the lower Sierpiński triangle.
Π2 is a Walsh permutation of degree 4, and permutes the integers 0 ... 15.
The corresponding element of GL(4, 2) is the 4×4 lower Sierpiński triangle.
A197819 | ||
---|---|---|
Fixed points are in parentheses. k 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 n 0 (0) (1) 1 (0) 3 (2) 1 2 (0) 15 10 5 12 3 (6) 9 (8) 7 2 13 4 11 (14) 1
|
In a finite Zhegalkin matrix, the columns with even/odd weight are in the left/right half.
(A truth table has a Zhegalkin twin with odd weight, iff its last digit is true.)
Boolean functions whose Zhegalkin index has even/odd weight shall be called evil/odious, which shall be called its depravity.
fixed points
edit1 | 2 | 3 | 4 | 5 | |
2 | 4 | 16 | 256 | 65536 |
The fixed points of Zhegalkin permutations correspond to noble Boolean functions.
A358167 | ||
---|---|---|
k 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
n
0 0
1 0 2
2 0 6 8 14
3 0 30 40 54 72 86 96 126 128 158 168 182 200 214 224 254
|
illustration of fixed points in permutation |
---|
Python code
editPython functions |
---|
from sympy import binomial
def sierpinski(n):
return int(sum([(binomial(n, i) % 2) * 2 ** i for i in range(n + 1)]))
def zhegalkin_perm(n, k):
row_length = 1 << (1 << n) # 2 ** 2 ** n
assert k < row_length
string_length = 1 << n # 2 ** n
k_binary = "{0:b}".format(k).zfill(string_length)
reflected_result = 0
for i, binary_digit in enumerate(k_binary):
if binary_digit == '1':
s = sierpinski(i)
reflected_result ^= s
reflected_result_binary = "{0:b}".format(reflected_result).zfill(string_length)
result_binary = reflected_result_binary[::-1]
return int(result_binary, 2)
def zhegalkin_fixed(n, k):
if n == 0:
assert k < 2
return k
else:
row_length = 1 << (1 << (n-1)) # 2 ** 2 ** (n-1)
assert k < row_length
p = zhegalkin_perm(n-1, k)
p_xor_k = p ^ k
shifted_k = row_length * k
return p_xor_k + shifted_k
|
Walsh permutations and Sierpiński triangles |
---|
This code uses the Python library discrete helpers.
from discretehelpers.walsh_perm import WalshPerm
from discretehelpers.binv import Binv
def anf_int_to_boolf(input_integer):
from discretehelpers.boolf import Boolf
input_indices = Binv(intval=input_integer).indices
if input_indices == set():
return Boolf(False)
result_boolf = Boolf(False)
for i in input_indices:
loop_indices = Binv(intval=i).indices
loop_boolf = Boolf(multi_and=loop_indices)
result_boolf = result_boolf ^ loop_boolf
return result_boolf
def create_sequence(arity):
sequence = []
for i in range(2 ** 2 ** arity):
boolf = anf_int_to_boolf(i)
binv = Binv(boolf.truth_table(arity))
sequence.append(binv.intval)
return sequence
sequence_0 = create_sequence(0)
# [0, 1]
sequence_1 = create_sequence(1)
# [0, 3, 2, 1]
sequence_2 = create_sequence(2)
# [0, 15, 10, 5, 12, 3, 6, 9, 8, 7, 2, 13, 4, 11, 14, 1]
sequence_3 = create_sequence(3)
# [0, 255, 170, 85 ... 84, 171, 254, 1]
sequence_4 = create_sequence(4)
# [0, 65535, 43690, 21845 ... 21844, 43691, 65534, 1]
wp_0 = WalshPerm(perm=sequence_0)
wp_1 = WalshPerm(perm=sequence_1)
wp_2 = WalshPerm(perm=sequence_2)
wp_3 = WalshPerm(perm=sequence_3)
wp_4 = WalshPerm(perm=sequence_4)
wp_0.matrix()
# array([[1]])
wp_1.matrix()
# array([[1, 0],
# [1, 1]])
wp_2.matrix()
# array([[1, 0, 0, 0],
# [1, 1, 0, 0],
# [1, 0, 1, 0],
# [1, 1, 1, 1]])
wp_3.matrix()
# array([[1, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 0, 0, 0, 0, 0, 0],
# [1, 0, 1, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 0, 0, 0, 0],
# [1, 0, 0, 0, 1, 0, 0, 0],
# [1, 1, 0, 0, 1, 1, 0, 0],
# [1, 0, 1, 0, 1, 0, 1, 0],
# [1, 1, 1, 1, 1, 1, 1, 1]])
wp_4.matrix()
# array([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],
# [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0],
# [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
# [1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
# [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
# [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])
|