61 lines
1.7 KiB
Python
61 lines
1.7 KiB
Python
# decoder.py
|
||
import numpy as np
|
||
from encoder import ALPHABET, G
|
||
|
||
|
||
def decode_blocks(Y: np.ndarray, C: np.ndarray) -> str:
|
||
"""
|
||
Decode received samples by maximum correlation score (state unknown, per-block).
|
||
"""
|
||
n = C.shape[1]
|
||
half = n // 2
|
||
num = Y.size // n
|
||
C1 = C[:, :half]
|
||
C2 = C[:, half:]
|
||
sqrtG = np.sqrt(G)
|
||
recovered = []
|
||
for k in range(num):
|
||
Yb = Y[k * n:(k + 1) * n]
|
||
Ye, Yo = Yb[0::2], Yb[1::2]
|
||
s1 = sqrtG * (Ye @ C1.T) + (Yo @ C2.T)
|
||
s2 = (Ye @ C1.T) + sqrtG * (Yo @ C2.T)
|
||
score = np.maximum(s1, s2)
|
||
best = int(np.argmax(score))
|
||
recovered.append(ALPHABET[best])
|
||
return "".join(recovered)
|
||
|
||
|
||
def decode_blocks_with_state(Y: np.ndarray, C: np.ndarray) -> (str, int):
|
||
"""
|
||
1) Estimate the single channel state s∈{1,2} by comparing total energy
|
||
on even vs odd positions across the entire Y.
|
||
2) Decode **all** blocks using that one state’s scoring rule.
|
||
|
||
Returns (decoded_string, estimated_state).
|
||
"""
|
||
n = C.shape[1]
|
||
half = n // 2
|
||
num = Y.size // n
|
||
C1 = C[:, :half]
|
||
C2 = C[:, half:]
|
||
sqrtG = np.sqrt(G)
|
||
|
||
# 1) state estimate from full-length energies
|
||
Ye_all = Y[0::2]
|
||
Yo_all = Y[1::2]
|
||
E_even = np.sum(Ye_all ** 2)
|
||
E_odd = np.sum(Yo_all ** 2)
|
||
s_est = 1 if E_even > E_odd else 2
|
||
|
||
recovered = []
|
||
for k in range(num):
|
||
Yb = Y[k * n:(k + 1) * n]
|
||
Ye, Yo = Yb[0::2], Yb[1::2]
|
||
if s_est == 1:
|
||
score = sqrtG * (Ye @ C1.T) + (Yo @ C2.T)
|
||
else:
|
||
score = (Ye @ C1.T) + sqrtG * (Yo @ C2.T)
|
||
best = int(np.argmax(score))
|
||
recovered.append(ALPHABET[best])
|
||
|
||
return "".join(recovered), s_est
|