1717
1818import math
1919from inspect import getfullargspec
20+ from fractions import Fraction
2021
2122import numpy as np
2223
@@ -49,7 +50,7 @@ def link_performance(link_model, SNRs, send_max, err_min, send_chunk=None, code_
4950 so it should be large enough regarding the code type.
5051 *Default*: send_chunck = err_min
5152
52- code_rate : float in (0,1]
53+ code_rate : float or Fraction in (0,1]
5354 Rate of the used code.
5455 *Default*: 1 i.e. no code.
5556
@@ -97,9 +98,9 @@ class LinkModel:
9798 binary array.
9899 *Default* is no process.
99100
100- rate : float
101- Code rate .
102- *Default* is 1 .
101+ rate : float or Fraction in (0,1]
102+ Rate of the used code .
103+ *Default*: 1 i.e. no code .
103104
104105 Attributes
105106 ----------
@@ -134,13 +135,15 @@ class LinkModel:
134135 *Default* is 1.
135136 """
136137
137- def __init__ (self , modulate , channel , receive , num_bits_symbol , constellation , Es = 1 , decoder = None , rate = 1. ):
138+ def __init__ (self , modulate , channel , receive , num_bits_symbol , constellation , Es = 1 , decoder = None , rate = Fraction ( 1 , 1 ) ):
138139 self .modulate = modulate
139140 self .channel = channel
140141 self .receive = receive
141142 self .num_bits_symbol = num_bits_symbol
142143 self .constellation = constellation
143144 self .Es = Es
145+ if type (rate ) is float :
146+ rate = Fraction (rate ).limit_denominator (100 )
144147 self .rate = rate
145148
146149 if decoder is None :
@@ -149,7 +152,7 @@ def __init__(self, modulate, channel, receive, num_bits_symbol, constellation, E
149152 self .decoder = decoder
150153 self .full_simulation_results = None
151154
152- def link_performance_full_metrics (self , SNRs , tx_max , err_min , send_chunk = None , code_rate : float = 1. ,
155+ def link_performance_full_metrics (self , SNRs , tx_max , err_min , send_chunk = None , code_rate : Fraction = Fraction ( 1 , 1 ) ,
153156 number_chunks_per_send = 1 , stop_on_surpass_error = True ):
154157 """
155158 Estimate the BER performance of a link model with Monte Carlo simulation.
@@ -171,7 +174,7 @@ def link_performance_full_metrics(self, SNRs, tx_max, err_min, send_chunk=None,
171174 so it should be large enough regarding the code type.
172175 *Default*: send_chunck = err_min
173176
174- code_rate : float in (0,1]
177+ code_rate : Fraction in (0,1]
175178 Rate of the used code.
176179 *Default*: 1 i.e. no code.
177180
@@ -200,18 +203,21 @@ def link_performance_full_metrics(self, SNRs, tx_max, err_min, send_chunk=None,
200203 BEs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Bit errors per tx
201204 CEs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Chunk Errors per tx
202205 NCs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Number of Chunks per tx
203- # Set chunk size and round it to be a multiple of num_bits_symbol*nb_tx to avoid padding
206+ # Set chunk size and round it to be a multiple of num_bits_symbol* nb_tx to avoid padding taking in to account the coding rate
204207 if send_chunk is None :
205208 send_chunk = err_min
206- divider = self .num_bits_symbol * self .channel .nb_tx
209+ if type (code_rate ) is float :
210+ code_rate = Fraction (code_rate ).limit_denominator (100 )
211+ self .rate = code_rate
212+ divider = (Fraction (1 , self .num_bits_symbol * self .channel .nb_tx ) * 1 / code_rate ).denominator
207213 send_chunk = max (divider , send_chunk // divider * divider )
208214
209215 receive_size = self .channel .nb_tx * self .num_bits_symbol
210216 full_args_decoder = len (getfullargspec (self .decoder ).args ) > 1
211217
212218 # Computations
213219 for id_SNR in range (len (SNRs )):
214- self .channel .set_SNR_dB (SNRs [id_SNR ], code_rate , self .Es )
220+ self .channel .set_SNR_dB (SNRs [id_SNR ], float ( code_rate ) , self .Es )
215221 total_tx_send = 0
216222 bit_err = np .zeros (tx_max , dtype = int )
217223 chunk_loss = np .zeros (tx_max , dtype = int )
@@ -227,7 +233,7 @@ def link_performance_full_metrics(self, SNRs, tx_max, err_min, send_chunk=None,
227233 # Deals with MIMO channel
228234 if isinstance (self .channel , MIMOFlatChannel ):
229235 nb_symb_vector = len (channel_output )
230- received_msg = np .empty (int (math .ceil (len (msg ) / self .rate )), dtype = np .int8 )
236+ received_msg = np .empty (int (math .ceil (len (msg ) / float ( self .rate ) )), dtype = np .int8 )
231237 for i in range (nb_symb_vector ):
232238 received_msg [receive_size * i :receive_size * (i + 1 )] = \
233239 self .receive (channel_output [i ], self .channel .channel_gains [i ],
@@ -276,7 +282,7 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
276282 Number of bits to be send at each iteration. This is also the frame length of the decoder if available
277283 so it should be large enough regarding the code type.
278284 *Default*: send_chunck = err_min
279- code_rate : float in (0,1]
285+ code_rate : float or Fraction in (0,1]
280286 Rate of the used code.
281287 *Default*: 1 i.e. no code.
282288 Returns
@@ -290,15 +296,18 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
290296 # Set chunk size and round it to be a multiple of num_bits_symbol*nb_tx to avoid padding
291297 if send_chunk is None :
292298 send_chunk = err_min
293- divider = self .num_bits_symbol * self .channel .nb_tx
299+ if type (code_rate ) is float :
300+ code_rate = Fraction (code_rate ).limit_denominator (100 )
301+ self .rate = code_rate
302+ divider = (Fraction (1 , self .num_bits_symbol * self .channel .nb_tx ) * 1 / code_rate ).denominator
294303 send_chunk = max (divider , send_chunk // divider * divider )
295304
296305 receive_size = self .channel .nb_tx * self .num_bits_symbol
297306 full_args_decoder = len (getfullargspec (self .decoder ).args ) > 1
298307
299308 # Computations
300309 for id_SNR in range (len (SNRs )):
301- self .channel .set_SNR_dB (SNRs [id_SNR ], code_rate , self .Es )
310+ self .channel .set_SNR_dB (SNRs [id_SNR ], float ( code_rate ) , self .Es )
302311 bit_send = 0
303312 bit_err = 0
304313 while bit_send < send_max and bit_err < err_min :
@@ -310,7 +319,7 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
310319 # Deals with MIMO channel
311320 if isinstance (self .channel , MIMOFlatChannel ):
312321 nb_symb_vector = len (channel_output )
313- received_msg = np .empty (int (math .ceil (len (msg ) / self .rate )), dtype = np .int8 )
322+ received_msg = np .empty (int (math .ceil (len (msg ) / float ( self .rate ) )), dtype = np .int8 )
314323 for i in range (nb_symb_vector ):
315324 received_msg [receive_size * i :receive_size * (i + 1 )] = \
316325 self .receive (channel_output [i ], self .channel .channel_gains [i ],
0 commit comments