55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
import numpy
|
|
import numpy as np
|
|
import itertools
|
|
|
|
|
|
class SoftDecisionDecoder:
|
|
"""This class naively implements a soft decision decoder. This decoder calculates
|
|
the posterior probability for each codeword and then chooses the one with the largest
|
|
probability.
|
|
"""
|
|
|
|
def __init__(self, G: np.array, H: np.array):
|
|
"""Construct a new SotDecisionDecoder object.
|
|
|
|
:param G: Generator matrix
|
|
:param H: Parity check matrix
|
|
"""
|
|
self._G = G
|
|
self._H = H
|
|
self._datawords, self._codewords = self._gen_codewords()
|
|
self._codewords_bpsk = self._codewords * 2 - 1 # The codewords, but mapped to [-1, 1]^n
|
|
|
|
def _gen_codewords(self) -> np.array:
|
|
"""Generate a list of all possible codewords.
|
|
|
|
:return: Numpy array of the form [[codeword_1], [codeword_2], ...]
|
|
"""
|
|
k, n = self._G.shape
|
|
|
|
# Generate a list of all possible data words
|
|
u_lst = [list(i) for i in itertools.product([0, 1], repeat=k)]
|
|
u_lst = np.array(u_lst)
|
|
|
|
# Map each data word onto a codeword
|
|
c_lst = np.dot(u_lst, self._G) % 2
|
|
|
|
return u_lst, c_lst
|
|
|
|
def decode(self, y: np.array) -> np.array:
|
|
"""Decode a received signal.
|
|
|
|
This function assumes a BPSK-like modulated signal ([-1, 1]^n instead of [0, 1]^n)
|
|
and an AWGN channel.
|
|
|
|
:param y: Vector of received values. (y = x + n, where 'x' is element of [-1, 1]^m
|
|
and 'n' is noise)
|
|
:return: Most probably sent symbol
|
|
"""
|
|
# TODO: Is there a nice numpy way to implement this for loop?
|
|
correlations = []
|
|
for c in self._codewords_bpsk:
|
|
correlations.append(np.dot(y, c))
|
|
|
|
return self._datawords[numpy.argmax(correlations)]
|