Skip to content

Commit 5bb890f

Browse files
authored
Merge pull request #45 from BastienTr/master
New features (MIMO channel and detection, conv coding) & maintenance task
2 parents f3dba84 + 0464d6b commit 5bb890f

22 files changed

+868
-309
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Available Features
5555
- MIMO Maximum Likelihood (ML) Detection.
5656
- MIMO K-best Schnorr-Euchner Detection.
5757
- Convert channel matrix to Bit-level representation.
58+
- Computation of LogLikelihood ratio using max-log approximation.
5859

5960
[Sequences](https://github.com/veeresht/CommPy/blob/master/commpy/sequences.py)
6061
---------
@@ -100,17 +101,20 @@ Requirements/Dependencies
100101
Installation
101102
------------
102103

103-
- To use the released version on PyPi, use pip or conda to install as follows::
104+
- To use the released version on PyPi, use pip to install as follows::
104105
```
105106
$ pip install scikit-commpy
106-
$ conda install -c https://conda.binstar.org/veeresht scikit-commpy
107107
```
108108
- To work with the development branch, clone from github and install as follows::
109109
```
110110
$ git clone https://github.com/veeresht/CommPy.git
111111
$ cd CommPy
112112
$ python setup.py install
113113
```
114+
- conda version is curently outdated but v0.3 is still available using::
115+
```
116+
$ conda install -c https://conda.binstar.org/veeresht scikit-commpy
117+
```
114118

115119
Citing CommPy
116120
-------------

commpy/channelcoding/algcode.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
2-
3-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
42
# License: BSD 3-Clause
53

6-
from fractions import gcd
74
from numpy import array, arange, concatenate, convolve
85

9-
from commpy.channelcoding.gfields import GF, polymultiply, poly_to_string
6+
from commpy.channelcoding.gfields import GF, poly_to_string
107
from commpy.utilities import dec2bitarray, bitarray2dec
118

129
__all__ = ['cyclic_code_genpoly']

commpy/channelcoding/convcode.py

Lines changed: 295 additions & 125 deletions
Large diffs are not rendered by default.

commpy/channelcoding/gfields.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
2-
3-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
42
# License: BSD 3-Clause
53

64
""" Galois Fields """
75

86
from fractions import gcd
7+
98
from numpy import array, zeros, arange, convolve, ndarray, concatenate
10-
from itertools import *
9+
1110
from commpy.utilities import dec2bitarray, bitarray2dec
1211

1312
__all__ = ['GF', 'polydivide', 'polymultiply', 'poly_to_string']

commpy/channelcoding/interleavers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
32
# License: BSD 3-Clause
43

54
""" Interleavers and De-interleavers """
@@ -9,7 +8,6 @@
98

109
__all__ = ['RandInterlv']
1110

12-
1311
class _Interleaver:
1412

1513
def interlv(self, in_array):

commpy/channelcoding/ldpc.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
2-
3-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
42
# License: BSD 3-Clause
53

64
""" LDPC Codes """
Lines changed: 127 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,159 @@
1-
2-
3-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
42
# License: BSD 3-Clause
53

6-
from numpy import array
7-
from numpy.random import randint
8-
from numpy.testing import assert_array_equal
4+
from numpy import array, inf
5+
from numpy.random import randint, randn, seed
6+
from numpy.testing import assert_array_equal, dec, run_module_suite
7+
98
from commpy.channelcoding.convcode import Trellis, conv_encode, viterbi_decode
109

10+
1111
class TestConvCode(object):
1212

1313
@classmethod
1414
def setup_class(cls):
15+
cls.trellis = []
16+
cls.desired_next_state_table = []
17+
cls.desired_output_table = []
18+
cls.desired_encode_msg = []
19+
cls.mes = array((0, 0, 1, 0))
20+
21+
### 1/2 - rate codes ###
22+
1523
# Convolutional Code 1: G(D) = [1+D^2, 1+D+D^2]
1624
memory = array([2])
17-
g_matrix = array([[0o5, 0o7]])
18-
cls.code_type_1 = 'default'
19-
cls.trellis_1 = Trellis(memory, g_matrix, 0, cls.code_type_1)
20-
cls.desired_next_state_table_1 = array([[0, 2],
21-
[0, 2],
22-
[1, 3],
23-
[1, 3]])
24-
cls.desired_output_table_1 = array([[0, 3],
25-
[3, 0],
26-
[1, 2],
27-
[2, 1]])
28-
25+
g_matrix = array([[5, 7]])
26+
cls.trellis.append(Trellis(memory, g_matrix, code_type='default'))
27+
cls.desired_next_state_table.append(array([[0, 2],
28+
[0, 2],
29+
[1, 3],
30+
[1, 3]]))
31+
cls.desired_output_table.append(array([[0, 3],
32+
[3, 0],
33+
[1, 2],
34+
[2, 1]]))
35+
cls.desired_encode_msg.append(array([0., 0., 0., 0., 1., 1., 0., 1.]))
2936

3037
# Convolutional Code 2: G(D) = [1 1+D+D^2/1+D]
3138
memory = array([2])
32-
g_matrix = array([[0o1, 0o7]])
33-
feedback = 0o5
34-
cls.code_type_2 = 'rsc'
35-
cls.trellis_2 = Trellis(memory, g_matrix, feedback, cls.code_type_2)
36-
cls.desired_next_state_table_2 = array([[0, 2],
37-
[2, 0],
38-
[1, 3],
39-
[3, 1]])
40-
cls.desired_output_table_2 = array([[0, 3],
41-
[0, 3],
42-
[1, 2],
43-
[1, 2]])
44-
39+
g_matrix = array([[1, 7]])
40+
feedback = 5
41+
cls.trellis.append(Trellis(memory, g_matrix, feedback, 'rsc'))
42+
cls.desired_next_state_table.append(array([[0, 2],
43+
[2, 0],
44+
[1, 3],
45+
[3, 1]]))
46+
cls.desired_output_table.append(array([[0, 3],
47+
[0, 3],
48+
[1, 2],
49+
[1, 2]]))
50+
cls.desired_encode_msg.append(array([0., 0., 0., 0., 1., 1., 0., 1.]))
51+
52+
### 2/3 - rate codes ###
53+
54+
# Convolutional Code 1: G(D) = [[1+D^2, 1+D+D^2 0], [0, D, 1+D]]
55+
memory = array([2, 1])
56+
g_matrix = array([[5, 7, 0], [0, 2, 3]])
57+
cls.trellis.append(Trellis(memory, g_matrix, code_type='default'))
58+
cls.desired_next_state_table.append(array([[0, 1, 4, 5],
59+
[0, 1, 4, 5],
60+
[0, 1, 4, 5],
61+
[0, 1, 4, 5],
62+
[2, 3, 6, 7],
63+
[2, 3, 6, 7],
64+
[2, 3, 6, 7],
65+
[2, 3, 6, 7]]))
66+
cls.desired_output_table.append(array([[0, 1, 6, 7],
67+
[3, 2, 5, 4],
68+
[6, 7, 0, 1],
69+
[5, 4, 3, 2],
70+
[2, 3, 4, 5],
71+
[1, 0, 7, 6],
72+
[4, 5, 2, 3],
73+
[7, 6, 1, 0]]))
74+
cls.desired_encode_msg.append(array([0., 0., 0., 1., 1., 0.]))
75+
76+
# Convolutional Code 2: G(D) = [[1, 0, 0], [0, 1, 1+D]]; F(D) = [[D, D], [1+D, 1]]
77+
memory = array([1, 1])
78+
g_matrix = array([[1, 0, 0], [0, 1, 3]])
79+
feedback = array([[2, 2], [3, 1]])
80+
cls.trellis.append(Trellis(memory, g_matrix, feedback, 'rsc'))
81+
cls.desired_next_state_table.append(array([[0, 1, 1, 0],
82+
[2, 3, 3, 2],
83+
[3, 2, 2, 3],
84+
[1, 0, 0, 1]]))
85+
cls.desired_output_table.append(array([[0, 3, 4, 7],
86+
[1, 2, 5, 6],
87+
[0, 3, 4, 7],
88+
[1, 2, 5, 6]]))
89+
cls.desired_encode_msg.append(array([0., 0., 0., 1., 0., 0.]))
4590

4691
@classmethod
4792
def teardown_class(cls):
4893
pass
4994

5095
def test_next_state_table(self):
51-
assert_array_equal(self.trellis_1.next_state_table, self.desired_next_state_table_1)
52-
assert_array_equal(self.trellis_2.next_state_table, self.desired_next_state_table_2)
96+
for i in range(len(self.trellis)):
97+
assert_array_equal(self.trellis[i].next_state_table, self.desired_next_state_table[i])
5398

5499
def test_output_table(self):
55-
assert_array_equal(self.trellis_1.output_table, self.desired_output_table_1)
56-
assert_array_equal(self.trellis_2.output_table, self.desired_output_table_2)
100+
for i in range(len(self.trellis)):
101+
assert_array_equal(self.trellis[i].output_table, self.desired_output_table[i])
57102

58103
def test_conv_encode(self):
59-
pass
104+
for i in range(len(self.trellis)):
105+
assert_array_equal(conv_encode(self.mes, self.trellis[i],'cont'), self.desired_encode_msg[i])
60106

61107
def test_viterbi_decode(self):
62-
pass
108+
pass # Tested below
63109

110+
@dec.slow
64111
def test_conv_encode_viterbi_decode(self):
65112
niters = 10
66113
blocklength = 1000
67114

68-
for i in range(niters):
115+
for n in range(niters):
69116
msg = randint(0, 2, blocklength)
70117

71-
coded_bits = conv_encode(msg, self.trellis_1)
72-
decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_1, 15)
73-
assert_array_equal(decoded_bits[:-2], msg)
74-
75-
coded_bits = conv_encode(msg, self.trellis_1, termination = 'cont')
76-
decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_1, 15)
77-
assert_array_equal(decoded_bits, msg)
78-
79-
coded_bits = conv_encode(msg, self.trellis_1)
80-
coded_syms = 2.0*coded_bits - 1
81-
decoded_bits = viterbi_decode(coded_syms, self.trellis_1, 15, 'unquantized')
82-
assert_array_equal(decoded_bits[:-2], msg)
83-
84-
coded_bits = conv_encode(msg, self.trellis_2)
85-
decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_2, 15)
86-
assert_array_equal(decoded_bits[:-2], msg)
87-
88-
coded_bits = conv_encode(msg, self.trellis_2)
89-
coded_syms = 2.0*coded_bits - 1
90-
decoded_bits = viterbi_decode(coded_syms, self.trellis_2, 15, 'unquantized')
91-
assert_array_equal(decoded_bits[:-2], msg)
118+
# Previous tests
119+
for i in range(len(self.trellis)):
120+
coded_bits = conv_encode(msg, self.trellis[i])
121+
decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis[i], 15)
122+
assert_array_equal(decoded_bits[:len(msg)], msg)
123+
124+
coded_bits = conv_encode(msg, self.trellis[i], termination='cont')
125+
decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis[i], 15)
126+
assert_array_equal(decoded_bits, msg)
127+
128+
coded_bits = conv_encode(msg, self.trellis[i])
129+
coded_syms = 2.0 * coded_bits - 1
130+
decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'unquantized')
131+
assert_array_equal(decoded_bits[:len(msg)], msg)
132+
133+
coded_bits = conv_encode(msg, self.trellis[i])
134+
coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2
135+
decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft')
136+
assert_array_equal(decoded_bits[:len(msg)], msg)
137+
138+
coded_bits = conv_encode(msg, self.trellis[i], termination='cont')
139+
coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2
140+
decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft')
141+
assert_array_equal(decoded_bits, msg)
142+
143+
coded_bits = conv_encode(msg, self.trellis[i])
144+
coded_syms = (2.0 * coded_bits - 1) * inf
145+
decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft')
146+
assert_array_equal(decoded_bits[:len(msg)], msg)
147+
148+
coded = conv_encode(msg, self.trellis[i], termination='cont')
149+
coded_bits = coded.astype(float)
150+
coded_bits[coded_bits == 1.0] = inf
151+
coded_bits[coded_bits == 0.0] = -inf
152+
decoded_bits = viterbi_decode(coded_bits, self.trellis[i], 15, 'soft')
153+
assert_array_equal(decoded_bits, msg)
154+
155+
156+
if __name__ == "__main__":
157+
seed(17121996)
158+
run_module_suite()
159+

commpy/channelcoding/tests/test_gfields.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
2-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
32
# License: BSD 3 clause
43

5-
from numpy import array, ones_like, arange
6-
from numpy.testing import assert_array_almost_equal, assert_array_equal, assert_, assert_equal
4+
from numpy import array, arange
5+
from numpy.testing import assert_array_equal, assert_
6+
77
from commpy.channelcoding.gfields import GF
88

99

commpy/channelcoding/tests/test_ldpc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
22
# License: BSD 3-Clause
33

44
import os

commpy/channelcoding/turbo.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
2-
3-
# Authors: Veeresh Taranalli <veeresht@gmail.com>
1+
# Authors: CommPy contributors
42
# License: BSD 3-Clause
53

64
""" Turbo Codes """
75

8-
from numpy import array, append, zeros, exp, pi, log, empty
9-
from commpy.channelcoding import Trellis, conv_encode
10-
from commpy.utilities import dec2bitarray, bitarray2dec
6+
from numpy import array, zeros, exp, log, empty
7+
8+
from commpy.channelcoding import conv_encode
9+
from commpy.utilities import dec2bitarray
10+
11+
1112
#from commpy.channelcoding.map_c import backward_recursion, forward_recursion_decoding
1213

1314
def turbo_encode(msg_bits, trellis1, trellis2, interleaver):

0 commit comments

Comments
 (0)