Skip to content

Commit 9dfe948

Browse files
authored
Merge pull request #63 from BastienTr/master
Specifies in the doc the bit ordering when building triellis (fix #62)
2 parents f4c68b9 + 2373473 commit 9dfe948

File tree

3 files changed

+78
-16
lines changed

3 files changed

+78
-16
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.
36+
G(D) represents a polynomial with a MSB first 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', 'Matlab'}, optional
52+
Defines how to interpret g_matrix and feedback. In MSB format, we have 1+D <-> 3 <-> 011.
53+
In LSB format, which is used in Matlab, 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

commpy/examples/conv_encode_decode.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,42 @@
2020
# =============================================================================
2121

2222
# Number of delay elements in the convolutional encoder
23-
memory1 = np.array(2, ndmin=1)
23+
memory = np.array(2, ndmin=1)
2424

2525
# Generator matrix
26-
g_matrix1 = np.array((0o5, 0o7), ndmin=2)
26+
g_matrix = np.array((0o5, 0o7), ndmin=2)
2727

2828
# Create trellis data structure
29-
trellis1 = cc.Trellis(memory1, g_matrix1)
29+
trellis1 = cc.Trellis(memory, g_matrix)
30+
31+
# =============================================================================
32+
# Convolutional Code 1: G(D) = [1+D^2, 1+D^2+D^3]
33+
# Standard code with rate 1/2
34+
# =============================================================================
35+
36+
# Number of delay elements in the convolutional encoder
37+
memory = np.array(3, ndmin=1)
38+
39+
# Generator matrix (1+D^2+D^3 <-> 13 or 0o15)
40+
g_matrix = np.array((0o5, 0o15), ndmin=2)
41+
42+
# Create trellis data structure
43+
trellis2 = cc.Trellis(memory, g_matrix)
3044

3145
# =============================================================================
3246
# Convolutional Code 2: G(D) = [[1, 0, 0], [0, 1, 1+D]]; F(D) = [[D, D], [1+D, 1]]
3347
# RSC with rate 2/3
3448
# =============================================================================
3549

3650
# Number of delay elements in the convolutional encoder
37-
memory2 = np.array((1, 1))
51+
memory = np.array((1, 1))
3852

3953
# Generator matrix & feedback matrix
40-
g_matrix2 = np.array(((1, 0, 0), (0, 1, 3)))
54+
g_matrix = np.array(((1, 0, 0), (0, 1, 3)))
4155
feedback = np.array(((2, 2), (3, 1)))
4256

4357
# Create trellis data structure
44-
trellis2 = cc.Trellis(memory2, g_matrix2, feedback, 'rsc')
58+
trellis3 = cc.Trellis(memory, g_matrix, feedback, 'rsc')
4559

4660
# =============================================================================
4761
# Basic example using homemade counting and hard decoding
@@ -50,7 +64,7 @@
5064
# Traceback depth of the decoder
5165
tb_depth = None # Default value is 5 times the number or memories
5266

53-
for trellis in (trellis1, trellis2):
67+
for trellis in (trellis1, trellis2, trellis3):
5468
for i in range(10):
5569
# Generate random message bits to be encoded
5670
message_bits = np.random.randint(0, 2, 1000)

0 commit comments

Comments
 (0)