33
44from __future__ import division , print_function # Python 2 compatibility
55
6- from numpy import ones , inf , sqrt , array , identity , zeros , dot , trace , einsum , absolute
6+ from numpy import ones , inf , sqrt , array , identity , zeros , dot , trace , einsum , absolute , exp , pi , fromiter , kron , \
7+ zeros_like
78from numpy .random import seed , choice , randn
89from numpy .testing import run_module_suite , assert_raises , assert_equal , assert_allclose , \
910 assert_array_equal , dec
@@ -274,6 +275,28 @@ def check_chan_gain(mod, chan):
274275 assert_allclose (P_unnoisy , P_msg * chan .nb_tx , rtol = 0.2 ,
275276 err_msg = 'Channel add or remove energy' )
276277
278+ def expo_correlation (t , r ):
279+ # Construct the exponent matrix
280+ expo_tx = fromiter ((j - i for i in range (chan .nb_tx ) for j in range (chan .nb_tx )), int , chan .nb_tx ** 2 )
281+ expo_rx = fromiter ((j - i for i in range (chan .nb_rx ) for j in range (chan .nb_rx )), int , chan .nb_rx ** 2 )
282+
283+ # Reshape
284+ expo_tx = expo_tx .reshape (chan .nb_tx , chan .nb_tx )
285+ expo_rx = expo_rx .reshape (chan .nb_rx , chan .nb_rx )
286+
287+ return t ** expo_tx , r ** expo_rx
288+
289+ def check_correlation (chan , Rt , Rr ):
290+ nb_ant = chan .nb_tx * chan .nb_rx
291+ Rdes = kron (Rt , Rr )
292+ H = chan .channel_gains
293+ Ract = zeros_like (Rdes )
294+ for i in range (len (H )):
295+ Ract += H [i ].T .reshape (nb_ant , 1 ).dot (H [i ].T .reshape (1 , nb_ant ).conj ())
296+ Ract /= len (H )
297+ assert_allclose (Rdes , Ract , atol = 0.05 ,
298+ err_msg = 'Wrong correlation matrix' )
299+
277300 # Test value checking in constructor construction
278301 with assert_raises (ValueError ):
279302 MIMOFlatChannel (nb_tx , nb_tx , 0 , (ones ((nb_tx , nb_tx )), ones ((nb_tx , nb_tx )), ones ((nb_rx , nb_rx ))))
@@ -290,21 +313,26 @@ def check_chan_gain(mod, chan):
290313 # Test with Rayleigh fading
291314 chan .fading_param = (zeros ((nb_rx , nb_tx )), identity (nb_tx ), identity (nb_rx ))
292315 check_chan_gain (mod , chan )
293- assert_allclose (chan .channel_gains .mean (), 0 , atol = 2e-2 ,
294- err_msg = 'Wrong channel mean with real channel' )
295- assert_allclose (chan .channel_gains .var (), 1 , atol = 5e-2 ,
296- err_msg = 'Wrong channel variance with real channel' )
297316
298317 # Test with rician fading
299318 mean = randn (nb_rx , nb_tx )
300319 mean *= sqrt (prod_nb * 0.75 / einsum ('ij,ij->' , absolute (mean ), absolute (mean )))
301- Rs = self .random_SDP_matrix (nb_tx ) * sqrt (prod_nb ) * 0.5
320+ Rt = self .random_SDP_matrix (nb_tx ) * sqrt (prod_nb ) * 0.5
302321 Rr = self .random_SDP_matrix (nb_rx ) * sqrt (prod_nb ) * 0.5
303- chan .fading_param = (mean , Rs , Rr )
322+ chan .fading_param = (mean , Rt , Rr )
304323 check_chan_gain (mod , chan )
305324
306- assert_allclose (chan .channel_gains .mean (0 ), mean , atol = 0.2 ,
307- err_msg = 'Wrong channel mean with real channel' )
325+ # Test helper functions
326+ chan .uncorr_rayleigh_fading (float )
327+ check_chan_gain (mod , chan )
328+ assert_allclose (chan .k_factor , 0 ,
329+ err_msg = 'Wrong k-factor with uncorrelated Rayleigh fading' )
330+
331+ mean = randn (nb_rx , nb_tx )
332+ chan .uncorr_rician_fading (mean , 10 )
333+ check_chan_gain (mod , chan )
334+ assert_allclose (chan .k_factor , 10 ,
335+ err_msg = 'Wrong k-factor with uncorrelated rician fading' )
308336
309337 # Test on complex channel
310338 for mod in self .all_mods :
@@ -323,16 +351,41 @@ def check_chan_gain(mod, chan):
323351 # Test with rician fading
324352 mean = randn (nb_rx , nb_tx ) + 1j * randn (nb_rx , nb_tx )
325353 mean *= sqrt (prod_nb * 0.75 / einsum ('ij,ij->' , absolute (mean ), absolute (mean )))
326- Rs = self .random_SDP_matrix (nb_tx ) * sqrt (prod_nb ) * 0.5
354+ Rt = self .random_SDP_matrix (nb_tx ) * sqrt (prod_nb ) * 0.5
327355 Rr = self .random_SDP_matrix (nb_rx ) * sqrt (prod_nb ) * 0.5
328- chan .fading_param = (mean , Rs , Rr )
356+ chan .fading_param = (mean , Rt , Rr )
329357 check_chan_gain (mod , chan )
330358
331359 assert_allclose (chan .channel_gains .mean (0 ).real , mean .real , atol = 0.1 ,
332360 err_msg = 'Wrong channel mean with complex channel' )
333361 assert_allclose (chan .channel_gains .mean (0 ).imag , mean .imag , atol = 0.1 ,
334362 err_msg = 'Wrong channel mean with complex channel' )
335363
364+ # Test helper functions
365+ chan .uncorr_rayleigh_fading (complex )
366+ check_chan_gain (mod , chan )
367+ assert_allclose (chan .k_factor , 0 ,
368+ err_msg = 'Wrong k-factor with uncorrelated Rayleigh fading' )
369+
370+ mean = randn (nb_rx , nb_tx ) + randn (nb_rx , nb_tx ) * 1j
371+ chan .uncorr_rician_fading (mean , 10 )
372+ check_chan_gain (mod , chan )
373+ assert_allclose (chan .k_factor , 10 ,
374+ err_msg = 'Wrong k-factor with uncorrelated rician fading' )
375+
376+ chan .expo_corr_rayleigh_fading (exp (- 0.2j * pi ), exp (- 0.1j * pi ))
377+ check_chan_gain (mod , chan )
378+ assert_allclose (chan .k_factor , 0 ,
379+ err_msg = 'Wrong k-factor with correlated Rayleigh fading' )
380+ Rt , Rr = expo_correlation (exp (- 0.2j * pi ), exp (- 0.1j * pi ))
381+ check_correlation (chan , Rt , Rr )
382+
383+ mean = randn (nb_rx , nb_tx ) + randn (nb_rx , nb_tx ) * 1j
384+ chan .expo_corr_rician_fading (mean , 10 , exp (- 0.1j * pi ), exp (- 0.2j * pi ))
385+ check_chan_gain (mod , chan )
386+ assert_allclose (chan .k_factor , 10 ,
387+ err_msg = 'Wrong k-factor with correlated rician fading' )
388+
336389
337390@dec .slow
338391class TestMIMONoiseGeneration (MIMOTestCase ):
0 commit comments