Skip to content

Commit dbed95d

Browse files
committed
Add 'MSB' and 'LSB' argument to Treillis
1 parent f2bd540 commit dbed95d

File tree

2 files changed

+57
-9
lines changed

2 files changed

+57
-9
lines changed

commpy/channelcoding/convcode.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Trellis:
3333
Number of memory elements per input of the convolutional encoder.
3434
g_matrix : 2D ndarray of ints (decimal representation)
3535
Generator matrix G(D) of the convolutional encoder. Each element of
36-
G(D) represents a polynomial with a MSB first convention (ie, 1+D^2+D^3 <-> 1101 <-> 13 or 0o15).
36+
G(D) represents a polynomial with a MSB first decimal convention (ie, 1+D^2+D^3 <-> 1101 <-> 13 or 0o15).
3737
Coef [i,j] is the influence of input i on output j.
3838
feedback : 2D ndarray of ints (decimal representation), optional
3939
Feedback matrix F(D) of the convolutional encoder. Each element of
@@ -47,6 +47,12 @@ class Trellis:
4747
If 'rsc' is specified, then the first 'k x k' sub-matrix of
4848
G(D) must represent a identity matrix along with a non-zero
4949
feedback polynomial.
50+
*Default* is 'default'.
51+
polynomial_format : {'MSB', 'LSB'}, optional
52+
Defines how to interpret g_matrix and feedback. In MSB format, we have 1+D <-> 3 <-> 011.
53+
In LSB format, we have 1+D <-> 6 <-> 110.
54+
*Default* is 'MSB' format.
55+
5056
Attributes
5157
----------
5258
k : int
@@ -71,6 +77,12 @@ class Trellis:
7177
Table representing the output matrix of the convolutional code trellis.
7278
Rows represent current states and columns represent current inputs in
7379
decimal. Elements represent corresponding outputs in decimal.
80+
81+
Raises
82+
------
83+
ValueError
84+
polynomial_format is not 'MSB', 'LSB' or 'Matlab'.
85+
7486
Examples
7587
--------
7688
>>> from numpy import array
@@ -103,7 +115,7 @@ class Trellis:
103115
[1] S. Benedetto, R. Garello et G. Montorsi, "A search for good convolutional codes to be used in the
104116
construction of turbo codes", IEEE Transactions on Communications, vol. 46, n. 9, p. 1101-1005, spet. 1998
105117
"""
106-
def __init__(self, memory, g_matrix, feedback = None, code_type = 'default'):
118+
def __init__(self, memory, g_matrix, feedback=None, code_type='default', polynomial_format='MSB'):
107119

108120
[self.k, self.n] = g_matrix.shape
109121
self.code_type = code_type
@@ -118,7 +130,8 @@ def __init__(self, memory, g_matrix, feedback = None, code_type = 'default'):
118130

119131
if isinstance(feedback, int):
120132
warn('Trellis will only accept feedback as a matrix in the future. '
121-
'Using the backwards compatibility version that may contain bugs for k > 1.', DeprecationWarning)
133+
'Using the backwards compatibility version that may contain bugs for k > 1 or with LSB format.',
134+
DeprecationWarning)
122135

123136
if code_type == 'rsc':
124137
for i in range(self.k):
@@ -181,24 +194,37 @@ def __init__(self, memory, g_matrix, feedback = None, code_type = 'default'):
181194
bitarray2dec(shift_register)
182195

183196
else:
197+
if polynomial_format == 'MSB':
198+
bit_order = -1
199+
elif polynomial_format in ('LSB', 'Matlab'):
200+
bit_order = 1
201+
else:
202+
raise ValueError('polynomial_format must be "LSB", "MSB" or "Matlab"')
203+
184204
if feedback is None:
185205
feedback = np.identity(self.k, int)
206+
if polynomial_format in ('LSB', 'Matlab'):
207+
feedback *= 2**memory.max()
208+
209+
max_values_lign = memory.max() + 1 # Max number of value on a delay lign
186210

187211
# feedback_array[i] holds the i-th bit corresponding to each feedback polynomial.
188-
feedback_array = np.empty((self.total_memory + self.k, self.k, self.k), np.int8)
212+
feedback_array = np.zeros((max_values_lign, self.k, self.k), np.int8)
189213
for i in range(self.k):
190214
for j in range(self.k):
191-
feedback_array[:, i, j] = dec2bitarray(feedback[i, j], self.total_memory + self.k)[::-1]
215+
binary_view = dec2bitarray(feedback[i, j], max_values_lign)[::bit_order]
216+
feedback_array[:max_values_lign, i, j] = binary_view[-max_values_lign-2:]
192217

193218
# g_matrix_array[i] holds the i-th bit corresponding to each g_matrix polynomial.
194-
g_matrix_array = np.empty((self.total_memory + self.k, self.k, self.n), np.int8)
219+
g_matrix_array = np.zeros((max_values_lign, self.k, self.n), np.int8)
195220
for i in range(self.k):
196221
for j in range(self.n):
197-
g_matrix_array[:, i, j] = dec2bitarray(g_matrix[i, j], self.total_memory + self.k)[::-1]
222+
binary_view = dec2bitarray(g_matrix[i, j], max_values_lign)[::bit_order]
223+
g_matrix_array[:max_values_lign, i, j] = binary_view[-max_values_lign-2:]
198224

199225
# shift_regs holds on each column the state of a shift register.
200226
# The first row is the input of each shift reg.
201-
shift_regs = np.empty((self.total_memory + self.k, self.k), np.int8)
227+
shift_regs = np.empty((max_values_lign, self.k), np.int8)
202228

203229
# Compute the entries in the next state table and the output table
204230
for current_state in range(self.number_states):

commpy/channelcoding/tests/test_convcode.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,28 @@ def setup_class(cls):
7373
[7, 6, 1, 0]]))
7474
cls.desired_encode_msg.append(array([0., 0., 0., 1., 1., 0.]))
7575

76+
# Convolutional Code 1: G(D) = [[1+D^2, 1+D+D^2 0], [0, D, 1+D]] with LSB format
77+
memory = array([2, 1])
78+
g_matrix = array([[5, 7, 0], [0, 2, 6]])
79+
cls.trellis.append(Trellis(memory, g_matrix, code_type='default', polynomial_format='LSB'),)
80+
cls.desired_next_state_table.append(array([[0, 1, 4, 5],
81+
[0, 1, 4, 5],
82+
[0, 1, 4, 5],
83+
[0, 1, 4, 5],
84+
[2, 3, 6, 7],
85+
[2, 3, 6, 7],
86+
[2, 3, 6, 7],
87+
[2, 3, 6, 7]]))
88+
cls.desired_output_table.append(array([[0, 1, 6, 7],
89+
[3, 2, 5, 4],
90+
[6, 7, 0, 1],
91+
[5, 4, 3, 2],
92+
[2, 3, 4, 5],
93+
[1, 0, 7, 6],
94+
[4, 5, 2, 3],
95+
[7, 6, 1, 0]]))
96+
cls.desired_encode_msg.append(array([0., 0., 0., 1., 1., 0.]))
97+
7698
# Convolutional Code 2: G(D) = [[1, 0, 0], [0, 1, 1+D]]; F(D) = [[D, D], [1+D, 1]]
7799
memory = array([1, 1])
78100
g_matrix = array([[1, 0, 0], [0, 1, 3]])
@@ -102,7 +124,7 @@ def test_output_table(self):
102124

103125
def test_conv_encode(self):
104126
for i in range(len(self.trellis)):
105-
assert_array_equal(conv_encode(self.mes, self.trellis[i],'cont'), self.desired_encode_msg[i])
127+
assert_array_equal(conv_encode(self.mes, self.trellis[i], 'cont'), self.desired_encode_msg[i])
106128

107129
def test_viterbi_decode(self):
108130
pass # Tested below

0 commit comments

Comments
 (0)