Berlekamp–Massey algorithm

You are encouraged to solve this task according to the task description, using any language you may know.
The Berlekamp–Massey algorithm is an efficient algorithm for finding the shortest linear feedback shift register (LFSR) that generates a given sequence over a finite field. It determines the minimal polynomial of a linearly recurrent sequence, which is crucial in applications like error-correcting codes, cryptography, and sequence analysis.
- Overview
Given a sequence of elements from a finite field, the Berlekamp–Massey algorithm computes the shortest LFSR, characterized by its connection polynomial , such that the sequence satisfies the recurrence relation:
for all valid indices. The degree of the polynomial is the linear complexity of the sequence, representing the length of the shortest LFSR.
- History
The algorithm was independently developed by Elwyn Berlekamp in 1968 for decoding BCH codes and by James Massey in 1969 for cryptographic applications. It remains a cornerstone in coding theory and sequence analysis.
- Algorithm Description
The Berlekamp–Massey algorithm iteratively constructs the connection polynomial by processing the input sequence element by element. It maintains a current polynomial and updates it whenever a discrepancy is found between the predicted and actual sequence values. The key steps are:
1. Initialize , degree , and a temporary polynomial . 2. For each sequence element :
* Compute the discrepancy . * If : * Update . * If the discrepancy indicates a need for a longer LFSR (i.e., ), update and adjust .
3. Output and .
The algorithm runs in time, where is the sequence length, and uses space.
- Applications
- Error Correction: Used in decoding Reed–Solomon codes and BCH codes.
- Cryptography: Analyzes the linear complexity of sequences in stream ciphers to assess security.
- Sequence Analysis: Identifies patterns in sequences for signal processing and data compression.
- Example
For the binary sequence over , the algorithm yields the connection polynomial , indicating a linear complexity of 3.
ALGOL 68
BEGIN # Berlekamp–Massey algorithm - translation of the FreeBASIC sample #
INT mdl = 2;
PROC fp = ( INT a, k )INT:
BEGIN
INT result := 1, bbase := a MOD mdl, expo := k;
WHILE expo > 0 DO
IF ODD expo THEN result *:= bbase MODAB mdl FI;
bbase *:= bbase MODAB mdl;
expo OVERAB 2
OD;
result
END # fp # ;
PROC berlekamp massey = ( []INT a in )[]INT:
BEGIN
[ 0 : -1 ]INT empty row;
REF[]INT ans coef := empty row, lst := empty row;
[]INT a = a in[ AT 0 ];
INT n = UPB a;
INT lst size := 0, w := 0, delta := 0;
FOR i TO n DO
INT tmp := 0;
INT ans len = UPB ans coef;
FOR j FROM 0 TO ans len DO
IF i - 1 - j >= 1 THEN
tmp +:= ( a[ i - 1 - j ] * ans coef[ j ] ) MODAB mdl
FI
OD;
INT discrepancy = ( a[ i ] - tmp + mdl ) MOD mdl;
IF discrepancy = 0
THEN SKIP
ELIF w = 0
THEN
ans coef := HEAP[ 0 : i - 1 ]INT;
FOR j FROM 0 TO i - 1 DO ans coef[ j ] := 0 OD;
w := i;
delta := discrepancy
ELSE
[ 0 : UPB ans coef ]INT ahora := ans coef;
INT inv delta = fp( delta, mdl - 2 );
INT mul = ( discrepancy * inv delta ) MOD mdl;
INT needed len = lst size + i - w;
IF UPB ans coef + 1 < needed len THEN
ans coef := HEAP[ 0 : needed len - 1 ]INT;
ans coef[ 0 : UPB ahora AT 0 ] := ahora;
FOR j FROM UPB ahora + 1 TO UPB ans coef DO ans coef[ j ] := 0 OD
FI;
IF i - w - 1 >= 0 THEN
ans coef( i - w - 1 ) +:= mul MODAB mdl
FI;
FOR j FROM 0 TO lst size - 1 DO
INT idx = i - w + j;
IF idx < UPB ans coef + 1 THEN
INT term to subtract = ( mul * lst[ j ] ) MOD mdl;
ans coef[ idx ] -:= term to subtract +:= mdl MODAB mdl
FI
OD;
IF UPB ans coef > UPB ahora THEN
lst := HEAP[ 0 : UPB ahora ]INT;
lst[ AT 0 ] := ahora;
lst size := UPB ahora + 1;
w := i;
delta := discrepancy
FI
FI;
FOR m FROM 0 TO UPB ans coef DO ans coef[ m ] +:= mdl MODAB mdl OD
OD;
ans coef
END # berlekamp massey # ;
CO # uncomment if calculation of specific terms is required #
PROC calculate term = ( INT m, []INT coef, h )INT:
IF m <= UPB h
THEN ( h[ m ] + mdl ) MOD mdl
ELIF INT k = UPB coef + 1;
k = 0
THEN 0
ELSE [ 0 : k ]INT p coeffs;
p coeffs[ 0 ] := ( mdl - 1 ) MOD mdl;
p coeffs[ 1 : k ] := coef;
INT degree k := k;
[ 0 : degree k - 1 ]INT f, g;
f[ 0 ] := 1;
FOR i TO UPB f DO f[ i ] := 0 OD;
FOR i FROM 0 TO UPB g DO g[ i ] := 0 OD;
IF k = 1 THEN
g[ 0 ] := p coeffs[ 1 ]
ELSE
g[ 1 ] := 1
FI;
INT power := m;
[ 0 : 2 * degree k - 1 ]INT tmp;
INT term := 0;
WHILE power > 0 DO
IF ODD power THEN
FOR i FROM 0 TO UPB tmp DO tmp[ i ] := 0 OD;
FOR i FROM 0 TO degree k - 1 DO
IF f[ i ] /= 0 THEN
FOR j FROM 0 TO UPB f DO
tmp[ i + j ] +:= ( f[ i ] * g[ j ] ) MODAB mdl
OD
FI
OD;
FOR i FROM UPB tmp BY - 1 TO UPB f + 1 DO
IF tmp[ i ] /= 0 THEN
term := tmp[ i ];
tmp[ i ] := 0;
FOR j FROM 0 TO k DO
INT idx = i - j;
IF idx >= 0 THEN
tmp[ idx ] +:= ( term * p coeffs[ j ] ) MODAB mdl
FI
OD
FI
OD;
f := tmp[ 0 : UPB f AT 0 ]
FI;
FOR i FROM 0 TO UPB tmp DO tmp[ i ] := 0 OD;
FOR i FROM 0 TO UPB g DO
IF g[ i ] /= 0 THEN
FOR j FROM 0 TO UPB g DO
tmp[ i + j ] +:= ( g[ i ] * g[ j ] ) MODAB mdl
OD
FI
OD;
FOR i FROM UPB tmp BY -1 TO degree k DO
IF tmp[ i ] /= 0 THEN
term := tmp[ i ];
tmp[ i ] := 0;
FOR j FROM 0 TO k DO
INT idx = i - j;
IF idx >= 0 THEN
tmp[ idx ] +:= ( term * p coeffs[ j ] ) MODAB mdl
FI
OD
FI
OD;
g := tmp[ 0 : UPB g AT 0 ];
power OVERAB 2
OD;
INT final ans := 0;
FOR i FROM 0 TO degree k - 1 DO
IF i + 1 <= UPB h THEN
final ans +:= ( h[ i + 1 ] * f[ i ] ) MODAB mdl
FI
OD;
( final ans + mdl ) MOD mdl
FI # calculate term # ;
CO
PROC solve = VOID:
BEGIN
[]INT h input = []INT( 0, 0, 1, 1, 0, 1, 0 )[ AT 0 ];
INT n = UPB h input + 1;
[ 0 : n ]INT h;
h[ 0 ] := 0; FOR i FROM LWB h TO UPB h - 1 DO h[ i + 1 ] := h input[ i ] OD;
[]INT ans coef = berlekamp massey( h );
print( ( "Coefficients:" ) );
FOR i FROM 0 TO UPB ans coef DO
print( ( " ", whole( ( ans coef[ i ] + mdl ) MOD mdl, 0 ) ) )
OD;
print( ( newline ) )
CO # Uncomment to calculate a specific term #
;
INT m = 10;
INT result = calculate term( m, ans coef(), h() );
print( ( "Term ", whole( m, 0 ) ) );
print( ( ": ", whole( ( result + mdl ) MOD mdl, 0 ), newline ) )
CO
END # solve # ;
solve
END
- Output:
Coefficients: 1 1 0 1
FreeBASIC
Const As Integer MDL = 2
Function fp(a As Integer, k As Integer) As Integer
Dim As Integer result = 1
Dim As Integer bbase = a Mod MDL
Dim As Integer expo = k
While expo > 0
If (expo And 1) Then result = (result * bbase) Mod MDL
bbase = (bbase * bbase) Mod MDL
expo \= 2
Wend
Return result
End Function
Sub Berlekamp_Massey(a() As Integer, ans_coef() As Integer)
Dim As Integer n = Ubound(a)
Dim As Integer lst_size = 0
Dim As Integer w = 0
Dim As Integer delta = 0
Dim As Integer i, j, tmp, idx
Redim ans_coef(-1)
Dim As Integer lst()
Redim lst(-1)
For i = 1 To n
tmp = 0
Dim As Integer ans_len = Ubound(ans_coef)
For j = 0 To ans_len
If i - 1 - j >= 1 Then
tmp = (tmp + a(i - 1 - j) * ans_coef(j)) Mod MDL
End If
Next j
Dim As Integer discrepancy = (a(i) - tmp + MDL) Mod MDL
If discrepancy = 0 Then Continue For
If w = 0 Then
Redim ans_coef(i - 1)
For j = 0 To i - 1
ans_coef(j) = 0
Next j
w = i
delta = discrepancy
Continue For
End If
Dim As Integer Ahora(Ubound(ans_coef))
For j = 0 To Ubound(ans_coef)
Ahora(j) = ans_coef(j)
Next j
Dim As Integer inv_delta = fp(delta, MDL - 2)
Dim As Integer mul = (discrepancy * inv_delta) Mod MDL
Dim As Integer needed_len = lst_size + i - w
If Ubound(ans_coef) + 1 < needed_len Then
Redim Preserve ans_coef(needed_len - 1)
For j = Ubound(Ahora) + 1 To Ubound(ans_coef)
ans_coef(j) = 0
Next j
End If
If i - w - 1 >= 0 Then
ans_coef(i - w - 1) = (ans_coef(i - w - 1) + mul) Mod MDL
End If
For j = 0 To lst_size - 1
idx = i - w + j
If idx < Ubound(ans_coef) + 1 Then
Dim As Integer term_to_subtract = (mul * lst(j)) Mod MDL
ans_coef(idx) = (ans_coef(idx) - term_to_subtract + MDL) Mod MDL
End If
Next j
If Ubound(ans_coef) + 1 > Ubound(Ahora) + 1 Then
Redim lst(Ubound(Ahora))
For j = 0 To Ubound(Ahora)
lst(j) = Ahora(j)
Next j
lst_size = Ubound(Ahora) + 1
w = i
delta = discrepancy
End If
Next i
For i = 0 To Ubound(ans_coef)
ans_coef(i) = (ans_coef(i) + MDL) Mod MDL
Next i
End Sub
Function calculate_term(m As Integer, coef() As Integer, h() As Integer) As Integer
Dim As Integer i, j, k
If m <= Ubound(h) Then Return (h(m) + MDL) Mod MDL
k = Ubound(coef) + 1
If k = 0 Then Return 0
Dim As Integer p_coeffs(k)
p_coeffs(0) = (MDL - 1) Mod MDL
For i = 0 To k - 1
p_coeffs(i + 1) = coef(i)
Next i
Dim As Integer degree_k = k
Dim As Integer f(degree_k - 1), g(degree_k - 1)
f(0) = 1
For i = 1 To degree_k - 1
f(i) = 0
Next i
If k = 1 Then
g(0) = p_coeffs(1)
For i = 1 To degree_k - 1
g(i) = 0
Next i
Else
g(0) = 0
g(1) = 1
For i = 2 To degree_k - 1
g(i) = 0
Next i
End If
Dim As Integer power = m
Dim As Integer tmp(2 * degree_k - 1)
Dim As Integer term, idx
While power > 0
If (power And 1) Then
For i = 0 To 2 * degree_k - 1
tmp(i) = 0
Next i
For i = 0 To degree_k - 1
If f(i) = 0 Then Continue For
For j = 0 To degree_k - 1
tmp(i + j) = (tmp(i + j) + f(i) * g(j)) Mod MDL
Next j
Next i
For i = 2 * degree_k - 1 To degree_k Step -1
If tmp(i) = 0 Then Continue For
term = tmp(i)
tmp(i) = 0
For j = 0 To k
idx = i - j
If idx >= 0 Then
tmp(idx) = (tmp(idx) + term * p_coeffs(j)) Mod MDL
End If
Next j
Next i
For i = 0 To degree_k - 1
f(i) = tmp(i)
Next i
End If
For i = 0 To 2 * degree_k - 1
tmp(i) = 0
Next i
For i = 0 To degree_k - 1
If g(i) = 0 Then Continue For
For j = 0 To degree_k - 1
tmp(i + j) = (tmp(i + j) + g(i) * g(j)) Mod MDL
Next j
Next i
For i = 2 * degree_k - 1 To degree_k Step -1
If tmp(i) = 0 Then Continue For
term = tmp(i)
tmp(i) = 0
For j = 0 To k
idx = i - j
If idx >= 0 Then
tmp(idx) = (tmp(idx) + term * p_coeffs(j)) Mod MDL
End If
Next j
Next i
For i = 0 To degree_k - 1
g(i) = tmp(i)
Next i
power \= 2
Wend
Dim As Integer final_ans = 0
For i = 0 To degree_k - 1
If i + 1 <= Ubound(h) Then
final_ans = (final_ans + h(i + 1) * f(i)) Mod MDL
End If
Next i
Return (final_ans + MDL) Mod MDL
End Function
Sub Solve()
Dim As Integer h_input(6) = {0, 0, 1, 1, 0, 1 ,0}
Dim As Integer i, n
n = Ubound(h_input) + 1
Dim As Integer h(n)
h(0) = 0
For i = 0 To n - 1
h(i + 1) = h_input(i)
Next i
Dim As Integer ans_coef()
Berlekamp_Massey(h(), ans_coef())
Print "Coefficients:";
For i = 0 To Ubound(ans_coef)
Print " " & ((ans_coef(i) + MDL) Mod MDL);
Next i
Print
' Uncomment to calculate a specific term
' Dim As Integer m = 10
' Dim As Integer result = calculate_term(m, ans_coef(), h())
' Print "Term " & m & ": " & ((result + MDL) Mod MDL)
End Sub
Solve()
Sleep
- Output:
Coefficients: 1 1 0 1
Python
MOD = 2
def fp(a, k):
return pow(a, k, MOD)
def berlekamp_massey(a):
n = len(a) - 1
ans_coef = []
lst = []
w = 0
delta = 0
for i in range(1, n + 1):
tmp = 0
for j in range(len(ans_coef)):
if i - 1 - j >= 1:
tmp = (tmp + a[i - 1 - j] * ans_coef[j]) % MOD
discrepancy = (a[i] - tmp + MOD) % MOD
if discrepancy == 0:
continue
if w == 0:
ans_coef = [0] * i
w = i
delta = discrepancy
continue
now = list(ans_coef)
mul = discrepancy * fp(delta, MOD - 2) % MOD
needed_len = len(lst) + i - w
if len(ans_coef) < needed_len:
ans_coef.extend([0] * (needed_len - len(ans_coef)))
if i - w - 1 >= 0:
ans_coef[i - w - 1] = (ans_coef[i - w - 1] + mul) % MOD
for j in range(len(lst)):
idx = i - w + j
if idx < len(ans_coef):
term_to_subtract = (mul * lst[j]) % MOD
ans_coef[idx] = (ans_coef[idx] - term_to_subtract + MOD) % MOD
if len(ans_coef) > len(now):
lst = now
w = i
delta = discrepancy
return [(x + MOD) % MOD for x in ans_coef]
def calculate_term(m, coef, h):
k = len(coef)
if m < len(h):
return (h[m] + MOD) % MOD
if k == 0:
return 0
p_coeffs = [0] * (k + 1)
p_coeffs[0] = (MOD - 1) % MOD
for i in range(k):
p_coeffs[i + 1] = coef[i]
def poly_mul(a, b, degree_k, p_poly):
res = [0] * (2 * degree_k)
for i in range(degree_k):
if a[i] == 0: continue
for j in range(degree_k):
res[i + j] = (res[i + j] + a[i] * b[j]) % MOD
for i in range(2 * degree_k - 1, degree_k - 1, -1):
if res[i] == 0: continue
term = res[i]
res[i] = 0
for j in range(degree_k + 1):
idx = i - j
if idx >= 0:
res[idx] = (res[idx] + term * p_poly[j]) % MOD
return res[:degree_k]
f = [0] * k
g = [0] * k
f[0] = 1
if k == 1:
if k == 1:
g[0] = p_coeffs[1]
else:
g[1] = 1
else:
g[1] = 1
power = m
while power > 0:
if power & 1:
f = poly_mul(f, g, k, p_coeffs)
g = poly_mul(g, g, k, p_coeffs)
power >>= 1
final_ans = 0
for i in range(k):
if i + 1 < len(h):
final_ans = (final_ans + h[i + 1] * f[i]) % MOD
return (final_ans + MOD) % MOD
def solve():
h_input = [0,0,1,1,0,1,0]
n=len(h_input)
h = [0] + h_input
ans_coef = berlekamp_massey(h)
print(*((x + MOD) % MOD for x in ans_coef))
# m=10
# result = calculate_term(m, ans_coef, h)
# print((result + MOD) % MOD)
if __name__ == "__main__":
solve()
- Output:
1 1 0 1
Wren
import "./math" for Int
import "./fmt" for Fmt
var MOD = 2
var fp = Fn.new { |a, k| Int.modPow(a, k, MOD) }
var berlekampMassey = Fn.new { |a|
var n = a.count - 1
var ansCoef = []
var lst = []
var w = 0
var delta = 0
for (i in 1...n + 1) {
var tmp = 0
for (j in 0...ansCoef.count) {
if (i - 1 - j >= 1) tmp = (tmp + a[i - 1 - j] * ansCoef[j]) % MOD
}
var discrepancy = (a[i] - tmp + MOD) % MOD
if (discrepancy == 0) continue
if (w == 0) {
ansCoef = List.filled(i, 0)
w = i
delta = discrepancy
continue
}
var now = ansCoef.toList
var mul = discrepancy * fp.call(delta, MOD - 2) % MOD
var neededLen = lst.count + i - w
if (ansCoef.count < neededLen) {
ansCoef.addAll(List.filled(neededLen - ansCoef.count, 0))
}
if (i - w - 1 >= 0) {
ansCoef[i - w - 1] = (ansCoef[i - w - 1] + mul) % MOD
}
for (j in 0...lst.count) {
var idx = i - w + j
if (idx < ansCoef.count) {
var termToSubtract = (mul * lst[j]) % MOD
ansCoef[idx] = (ansCoef[idx] - termToSubtract + MOD) % MOD
}
}
if (ansCoef.count > now.count) {
lst = now
w = i
delta = discrepancy
}
}
return ansCoef.map { |x| (x + MOD) % MOD }.toList
}
var calculateTerm = Fn.new { |m, coef, h|
var k = coef.count
if (m < h.count) return (h[m] + MOD) % MOD
if (k == 0) return 0
var pCoeffs = List.filled(k + 1, 0)
pCoeffs[0] = (MOD - 1) % MOD
for (i in 0...k) pCoeffs[i + 1] = coef[i]
var polyMul = Fn.new { |a, b, degreeK, pPoly|
var res = List.filled(2 * degreeK, 0)
for (i in 0...degreeK) {
if (a[i] == 0) continue
for (j in 0...degreeK) res[i + j] = (res[i + j] + a[i] * b[j]) % MOD
}
for (i in (2 * degreeK - 1)...(degreeK - 1)) {
if (res[i] == 0) continue
var term = res[i]
res[i] = 0
for (j in 0..degreeK) {
var idx = i - j
if (idx >= 0) res[idx] = (res[idx] + term * pPoly[j]) % MOD
}
}
return res[0...degreeK]
}
var f = List.filled(k, 0)
var g = List.filled(k, 0)
f[0] = 1
if (k == 1) g[0] = pCoeffs[1] else g[1] = 1
var power = m
while (power > 0) {
if (power % 2 == 1) f = polyMul.call(f, g, k, pCoeffs)
g = polyMul.call(g, g, k, pCoeffs)
power = power >> 1
}
var finalAns = 0
for (i in 0...k) if (i + 1 < h.count) finalAns = (finalAns + h[i + 1] * f[i]) % MOD
return (finalAns + MOD) % MOD
}
var solve = Fn.new {
var hInput = [0, 0, 1, 1, 0, 1, 0]
var n = hInput.count
var h = [0] + hInput
var ansCoef = berlekampMassey.call(h)
var coeffs = ansCoef.map { |x| (x + MOD) % MOD }.toList
System.print("Coefficients: %(coeffs) (lowest to highest degree)")
System.write("Hence connection polynomial: ")
Fmt.pprint("$d", coeffs[-1..0], "", "x")
System.print("and linear complexity: %(coeffs.count - 1)")
/* Uncomment the following 3 lines to calculate and show a term. */
// var m = 10
// var result = calculateTerm.call(m, ansCoef, h)
// System.print((result + MOD) % MOD)
}
solve.call()
- Output:
Coefficients: [1, 1, 0, 1] (lowest to highest degree) Hence connection polynomial: x³ + x + 1 and linear complexity: 3