Skip to content

Commit ee289ae

Browse files
authored
[Bug fix] Bad typing in links.py introduced in bcc36dd (#88)
[Bug fix] Bad typing in links.py introduced in bcc36dd
1 parent 292b4e5 commit ee289ae

File tree

2 files changed

+75
-33
lines changed

2 files changed

+75
-33
lines changed

commpy/links.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from __future__ import division # Python 2 compatibility
1717

1818
import math
19-
from inspect import getfullargspec
2019
from fractions import Fraction
20+
from inspect import getfullargspec
2121

2222
import numpy as np
2323

@@ -95,7 +95,7 @@ class LinkModel:
9595
*Default* Es=1.
9696
9797
decoder : function with prototype decoder(array) or decoder(y, H, constellation, noise_var, array) that return a
98-
binary array.
98+
binary ndarray.
9999
*Default* is no process.
100100
101101
rate : float or Fraction in (0,1]
@@ -127,7 +127,7 @@ class LinkModel:
127127
Es : float
128128
Average energy per symbols.
129129
130-
decoder : function with prototype decoder(binary array) that return a binary array.
130+
decoder : function with prototype decoder(binary array) that return a binary ndarray.
131131
*Default* is no process.
132132
133133
rate : float
@@ -233,7 +233,7 @@ def link_performance_full_metrics(self, SNRs, tx_max, err_min, send_chunk=None,
233233
# Deals with MIMO channel
234234
if isinstance(self.channel, MIMOFlatChannel):
235235
nb_symb_vector = len(channel_output)
236-
received_msg = np.empty(int(math.ceil(len(msg) / float(self.rate))), dtype=np.int8)
236+
received_msg = np.empty(int(math.ceil(len(msg) / float(self.rate))))
237237
for i in range(nb_symb_vector):
238238
received_msg[receive_size * i:receive_size * (i + 1)] = \
239239
self.receive(channel_output[i], self.channel.channel_gains[i],
@@ -251,7 +251,7 @@ def link_performance_full_metrics(self, SNRs, tx_max, err_min, send_chunk=None,
251251
# calculate number of error frames
252252
for i in range(number_chunks_per_send):
253253
errors = np.bitwise_xor(msg[send_chunk * i:send_chunk * (i + 1)],
254-
decoded_bits[send_chunk * i:send_chunk * (i + 1)]).sum()
254+
decoded_bits[send_chunk * i:send_chunk * (i + 1)].astype(int)).sum()
255255
bit_err[id_tx] += errors
256256
chunk_loss[id_tx] += 1 if errors > 0 else 0
257257

@@ -319,7 +319,7 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
319319
# Deals with MIMO channel
320320
if isinstance(self.channel, MIMOFlatChannel):
321321
nb_symb_vector = len(channel_output)
322-
received_msg = np.empty(int(math.ceil(len(msg) / float(self.rate))), dtype=np.int8)
322+
received_msg = np.empty(int(math.ceil(len(msg) / float(self.rate))))
323323
for i in range(nb_symb_vector):
324324
received_msg[receive_size * i:receive_size * (i + 1)] = \
325325
self.receive(channel_output[i], self.channel.channel_gains[i],
@@ -332,9 +332,9 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
332332
decoded_bits = self.decoder(channel_output, self.channel.channel_gains,
333333
self.constellation, self.channel.noise_std ** 2,
334334
received_msg, self.channel.nb_tx * self.num_bits_symbol)
335-
bit_err += np.bitwise_xor(msg, decoded_bits[:len(msg)]).sum()
335+
bit_err += np.bitwise_xor(msg, decoded_bits[:len(msg)].astype(int)).sum()
336336
else:
337-
bit_err += np.bitwise_xor(msg, self.decoder(received_msg)[:len(msg)]).sum()
337+
bit_err += np.bitwise_xor(msg, self.decoder(received_msg)[:len(msg)].astype(int)).sum()
338338
bit_send += send_chunk
339339
BERs[id_SNR] = bit_err / bit_send
340340
if bit_err < err_min:

commpy/tests/test_links.py

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,52 +8,94 @@
88
from numpy.testing import run_module_suite, assert_allclose, dec
99
from scipy.special import erfc
1010

11+
from commpy.channelcoding.ldpc import get_ldpc_code_params, triang_ldpc_systematic_encode, ldpc_bp_decode
1112
from commpy.channels import MIMOFlatChannel, SISOFlatChannel
1213
from commpy.links import link_performance, LinkModel
13-
from commpy.modulation import QAMModem, kbest
14+
from commpy.modulation import QAMModem, kbest, best_first_detector
1415

1516

1617
@dec.slow
1718
def test_link_performance():
1819
# Set seed
19-
seed(17121996)
20+
seed(8071996)
21+
######################################
22+
# Build models & desired solutions
23+
######################################
24+
models = []
25+
desired_bers = []
26+
snr_range = []
27+
labels = []
28+
rtols = []
29+
code_rates = []
2030

21-
# Apply link_performance to SISO QPSK and AWGN channel
31+
# SISO QPSK and AWGN channel
2232
QPSK = QAMModem(4)
2333

2434
def receiver(y, h, constellation, noise_var):
2535
return QPSK.demodulate(y, 'hard')
2636

27-
model = LinkModel(QPSK.modulate, SISOFlatChannel(fading_param=(1 + 0j, 0)), receiver,
28-
QPSK.num_bits_symbol, QPSK.constellation, QPSK.Es)
37+
models.append(LinkModel(QPSK.modulate, SISOFlatChannel(fading_param=(1 + 0j, 0)), receiver,
38+
QPSK.num_bits_symbol, QPSK.constellation, QPSK.Es))
39+
snr_range.append(arange(0, 9, 2))
40+
desired_bers.append(erfc(sqrt(10 ** (snr_range[-1] / 10) / 2)) / 2)
41+
labels.append('SISO QPSK and AWGN channel')
42+
rtols.append(.25)
43+
code_rates.append(1)
2944

30-
BERs = link_performance(model, range(0, 9, 2), 600e4, 600)
31-
desired = erfc(sqrt(10 ** (arange(0, 9, 2) / 10) / 2)) / 2
32-
assert_allclose(BERs, desired, rtol=0.25,
33-
err_msg='Wrong performance for SISO QPSK and AWGN channel')
34-
full_metrics = model.link_performance_full_metrics(range(0, 9, 2), 1000, 600)
35-
assert_allclose(full_metrics[0], desired, rtol=0.25,
36-
err_msg='Wrong performance for SISO QPSK and AWGN channel')
37-
38-
# Apply link_performance to MIMO 16QAM and 4x4 Rayleigh channel
45+
# MIMO 16QAM, 4x4 Rayleigh channel and hard-output K-Best
3946
QAM16 = QAMModem(16)
4047
RayleighChannel = MIMOFlatChannel(4, 4)
4148
RayleighChannel.uncorr_rayleigh_fading(complex)
4249

4350
def receiver(y, h, constellation, noise_var):
4451
return QAM16.demodulate(kbest(y, h, constellation, 16), 'hard')
4552

46-
model = LinkModel(QAM16.modulate, RayleighChannel, receiver,
47-
QAM16.num_bits_symbol, QAM16.constellation, QAM16.Es)
48-
SNRs = arange(0, 21, 5) + 10 * log10(QAM16.num_bits_symbol)
49-
50-
BERs = link_performance(model, SNRs, 600e4, 600)
51-
desired = (2e-1, 1e-1, 3e-2, 2e-3, 4e-5) # From reference
52-
assert_allclose(BERs, desired, rtol=1.25,
53-
err_msg='Wrong performance for MIMO 16QAM and 4x4 Rayleigh channel')
54-
full_metrics = model.link_performance_full_metrics(SNRs, 1000, 600)
55-
assert_allclose(full_metrics[0], desired, rtol=1.25,
56-
err_msg='Wrong performance for MIMO 16QAM and 4x4 Rayleigh channel')
53+
models.append(LinkModel(QAM16.modulate, RayleighChannel, receiver,
54+
QAM16.num_bits_symbol, QAM16.constellation, QAM16.Es))
55+
snr_range.append(arange(0, 21, 5) + 10 * log10(QAM16.num_bits_symbol))
56+
desired_bers.append((2e-1, 1e-1, 3e-2, 2e-3, 4e-5)) # From reference
57+
labels.append('MIMO 16QAM, 4x4 Rayleigh channel and hard-output K-Best')
58+
rtols.append(1.25)
59+
code_rates.append(1)
60+
61+
# MIMO 16QAM, 4x4 Rayleigh channel and soft-output best-first
62+
QAM16 = QAMModem(16)
63+
RayleighChannel = MIMOFlatChannel(4, 4)
64+
RayleighChannel.uncorr_rayleigh_fading(complex)
65+
ldpc_params = get_ldpc_code_params('commpy/channelcoding/designs/ldpc/wimax/1440.720.txt', True)
66+
67+
def modulate(bits):
68+
return QAM16.modulate(triang_ldpc_systematic_encode(bits, ldpc_params, False).reshape(-1, order='F'))
69+
70+
def decoder(llrs):
71+
return ldpc_bp_decode(llrs, ldpc_params, 'MSA', 15)[0][:720].reshape(-1, order='F')
72+
73+
def demode(symbs):
74+
return QAM16.demodulate(symbs, 'hard')
75+
76+
def receiver(y, h, constellation, noise_var):
77+
return best_first_detector(y, h, constellation, (1, 3, 5), noise_var, demode, 500)
78+
79+
models.append(LinkModel(modulate, RayleighChannel, receiver,
80+
QAM16.num_bits_symbol, QAM16.constellation, QAM16.Es,
81+
decoder, 0.5))
82+
snr_range.append(arange(17, 20, 1))
83+
desired_bers.append((1.7e-1, 1e-1, 2.5e-3)) # From reference
84+
labels.append('MIMO 16QAM, 4x4 Rayleigh channel and soft-output best-first')
85+
rtols.append(2)
86+
code_rates.append(.5)
87+
88+
######################################
89+
# Make tests
90+
######################################
91+
92+
for test in range(len(models)):
93+
BERs = link_performance(models[test], snr_range[test], 5e5, 200, 720, models[test].rate)
94+
assert_allclose(BERs, desired_bers[test], rtol=rtols[test],
95+
err_msg='Wrong performance for ' + labels[test])
96+
full_metrics = models[test].link_performance_full_metrics(snr_range[test], 2500, 200, 720, models[test].rate)
97+
assert_allclose(full_metrics[0], desired_bers[test], rtol=rtols[test],
98+
err_msg='Wrong performance for ' + labels[test])
5799

58100

59101
if __name__ == "__main__":

0 commit comments

Comments
 (0)