Berlekamp-Massey算法
本文介绍了Berlekamp-Massey算法流程以及对应的一个二元域上的Python实现。
注:本文的实现不适用于
a
0
≠
0
a_0\neq0
a0=0的序列
前置知识
线性综合解
如何理解退化的线性移位寄存器?
在非退化的线性移位寄存器中,我们有 deg ( f N ( x ) ) = l N \deg(f_N(x))=l_N deg(fN(x))=lN,即生成线性移位寄存器序列时,新生成的位一定依赖当前状态中的第一位。
例:0011101的线性综合解为 ( 1 + x + x 3 , 3 ) (1+x+x^3,3) (1+x+x3,3)
给0011101编为 a 0 a 1 a 2 a 3 a 4 a 5 a 6 a_0a_1a_2a_3a_4a_5a_6 a0a1a2a3a4a5a6,则初态应该有3位,是 a 0 a 1 a 2 a_0a_1a_2 a0a1a2即001
注意线性综合解中的多项式是联接多项式(也叫反馈多项式),通过对其求互反多项式可以求得线性移位寄存器序列的特征多项式。
求互反多项式:将联接多项式中的 x x x换成 1 x 1\over x x1,再乘以 x l N x^{l_N} xlN
( 1 + 1 x + 1 x 3 ) x 3 = x 3 + x 2 + 1 (1+{1\over x}+{1\over x^3})x^3=x^3+x^2+1 (1+x1+x31)x3=x3+x2+1,所以依据特征多项式的定义知 a n + 3 = a n + 2 + a n a_{n+3}=a_{n+2}+a_{n} an+3=an+2+an
后面生成新的位的过程应该是: a 3 = a 2 + a 0 = 1 + 0 = 1 a_3=a_2+a_0=1+0=1 a3=a2+a0=1+0=1,依此类推
而退化的线性移位寄存器序列的生成不依赖当前状态的第一位。
例:00101101的线性综合解为 ( 1 + x + x 2 , 4 ) (1+x+x^2,4) (1+x+x2,4)
初态为 a 0 a 1 a 2 a 3 a_0a_1a_2a_3 a0a1a2a3即0010
同理, a 4 = a 3 + a 2 = 0 + 1 = 1 , a 5 = a 4 + a 3 = 1 + 0 = 1 a_4=a_3+a_2=0+1=1,a_5=a_4+a_3=1+0=1 a4=a3+a2=0+1=1,a5=a4+a3=1+0=1,依此类推
算法流程
该算法可以求出关于给定有限长序列 a ( N ) a^{(N)} a(N)的线性综合解。
算法实现思路
给定一个0-1序列(二元域,考虑取余)(采用0,1列表表示)
(1)初始化:
找到第一个不等于0的位作为 a n 0 a_{n_0} an0,顺序查找
a 0 = a 1 = . . . = a n 0 − 1 = 0 a_0=a_1=...=a_{n_0-1}=0 a0=a1=...=an0−1=0
取 d 0 = d 1 = . . . = d n 0 − 1 = 0 , d n 0 = a n 0 d_0=d_1=...=d_{n_0-1}=0,d_{n_0}=a_{n_0} d0=d1=...=dn0−1=0,dn0=an0,需要存储
令 f 1 ( x ) = f 2 ( x ) = . . . = f n 0 ( x ) = 1 f_1(x)=f_2(x)=...=f_{n_0}(x)=1 f1(x)=f2(x)=...=fn0(x)=1
l 1 = l 2 = . . = l n 0 = 0 l_1=l_2=..=l_{n_0}=0 l1=l2=..=ln0=0,需要存储
令 f n 0 + 1 ( x ) = 1 − d n 0 x n 0 + 1 , l n 0 + 1 = n 0 + 1 f_{n_0+1}(x)=1-d_{n_0}x^{n_0+1},l_{n_0+1}=n_0+1 fn0+1(x)=1−dn0xn0+1,ln0+1=n0+1,
设计多项式类,设计线性综合解二元组类
(2)迭代计算:(for循环)
假设 ( f i ( x ) , l i ) , 1 ≤ i ≤ n (f_i(x),l_i),1\le i\le n (fi(x),li),1≤i≤n已经求得。
令 f n ( x ) = 1 + c n , 1 x + . . . + c n , l n x l n f_n(x)=1+c_{n,1}x+...+c_{n,l_n}x^{l_n} fn(x)=1+cn,1x+...+cn,lnxln
计算 d n = a n + c n , 1 a n − 1 + . . . + c n , l n a n − l n d_n=a_n+c_{n,1}a_{n-1}+...+c_{n,l_n}a_{n-l_n} dn=an+cn,1an−1+...+cn,lnan−ln
if判断
如果 d n = 0 d_n=0 dn=0,取 f n + 1 ( x ) = f n ( x ) , l n + 1 = l n f_{n+1}(x)=f_n(x),l_{n+1}=l_n fn+1(x)=fn(x),ln+1=ln
如果 d n ≠ 0 d_n\neq 0 dn=0,存在 1 ≤ m < n 1\le m\lt n 1≤m<n
使 l m < l m + 1 = l m + 2 = . . . = l n l_m\lt l_{m+1}=l_{m+2}=...=l_n lm<lm+1=lm+2=...=ln
找到最后一个 m m m,顺序查找
取 f n + 1 ( x ) = f n ( x ) − d n d m − 1 x n − m f m ( x ) f_{n+1}(x)=f_n(x)-d_nd_m^{-1}x^{n-m}f_m(x) fn+1(x)=fn(x)−dndm−1xn−mfm(x)
l n + 1 = m a x { l n , n + 1 − l n } l_{n+1}=max\{l_n,n+1-l_n\} ln+1=max{ln,n+1−ln}
需要实现多项式的加法
因为只考虑二元域,所以这里的系数的加法都模2取余,且不进位(采用异或实现),算法中的减法统一替换成加法。
算法代码
# author:njw
# 二元域上的Berlekamp-Massey算法
# 二元域上的多项式类
class Polynomial:
def __init__(self, coefficients):
self.coefficients = coefficients
self.degree = len(coefficients) - 1
# 二元域上的多项式的加法,做异或运算
def __add__(self, other):
if self.degree > other.degree:
return Polynomial(
[
self.coefficients[i] ^ other.coefficients[i]
for i in range(other.degree + 1)
]
+ self.coefficients[other.degree + 1 :]
)
else:
return Polynomial(
[
self.coefficients[i] ^ other.coefficients[i]
for i in range(self.degree + 1)
]
+ other.coefficients[self.degree + 1 :]
)
# 线性综合解类(用于存储线性综合解)(二元组)
class LinearCombinationSolution:
def __init__(self, polynomial, order):
self.polynomial = polynomial
self.order = order
# 二元域上的Berlekamp-Massey算法
# 输入:0-1序列(采取0-1列表表示)
def Berlekamp_Massey_algorithm(sequence):
# 初始化
n = 0
# 找到第一个不等于0的位
for i in range(len(sequence)):
if sequence[i] == 1:
n = i
break
d = [0 for i in range(n)]
d.extend([1])
linear_combination_solutions = []
for i in range(n):
linear_combination_solutions.append(
LinearCombinationSolution(Polynomial([1]), 0)
)
linear_combination_solutions.append(
LinearCombinationSolution(Polynomial([1] + [0 for i in range(n)] + [1]), n + 1)
)
# 迭代
for i in range(n, len(sequence) - 1):
# 计算新的d
temp_d = 0
for j in range(linear_combination_solutions[-1].polynomial.degree + 1):
temp_d += (
linear_combination_solutions[-1].polynomial.coefficients[j]
* sequence[i - j + 1]
)
temp_d = temp_d % 2
d.append(temp_d)
# 如果d为0,那么线性综合解不变
if temp_d == 0:
linear_combination_solutions.append(linear_combination_solutions[-1])
# 如果d不为0,那么线性综合解更新
else:
m = len(linear_combination_solutions) - 1
# 寻找当前最后一个跳跃的l
for k in range(len(linear_combination_solutions)):
if (
linear_combination_solutions[m - k].order
< linear_combination_solutions[-1].order
):
# 更新线性综合解
linear_combination_solutions.append(
LinearCombinationSolution(
# 更新线性综合解的联接多项式
linear_combination_solutions[-1].polynomial.__add__(
Polynomial(
[0 for l in range(i - m + k)]
+ linear_combination_solutions[
m - k
].polynomial.coefficients
)
),
# 更新线性综合解的阶
max(
linear_combination_solutions[-1].order,
i + 2 - linear_combination_solutions[-1].order,
),
)
)
break
return linear_combination_solutions[-1]
# 返回线性综合解的联接多项式和阶
# 测试
if __name__ == "__main__":
# test1
# sequence = [0,0,1,0,1,1,0,1]
# test2
sequence = [0,0,1,1,1,0,1]
# test3 都是用之前编写的LFSR产生的序列
# sequence = [0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
# test4
# sequence = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1]
# test5
# sequence = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1]
# sequence =[0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,1,1,1]
linear_combination_solution = Berlekamp_Massey_algorithm(sequence)
print(linear_combination_solution.polynomial.coefficients)
print(linear_combination_solution.order)
# 结果说明:[1,1,0,1],3是指联接多项式为1+x+x^3,阶为3