Don't count decoding failures as bit errors

This commit is contained in:
Andreas Tsouchlos 2022-11-24 12:40:49 +01:00
parent 47482b55e4
commit 68751c50cd

View File

@ -67,16 +67,18 @@ class Simulator:
# Simulation state
self._current_decoder_index = 0
self._current_SNRs_index = 0
self._curr_decoder_index = 0
self._curr_SNRs_index = 0
self._curr_num_frame_errors = 0
self._curr_num_bit_errors = 0
self._curr_num_iterations = 0
self._curr_num_dec_fails = 0
# Results & Miscellaneous
self._BERs = [[]]
self._BERs = [np.zeros(len(SNRs)) for i in range(len(decoders))]
self._dec_fails = [np.zeros(len(SNRs)) for i in range(len(decoders))]
self._create_pbars()
@ -90,7 +92,7 @@ class Simulator:
bar_format="{l_bar}{bar}| {n_fmt}/{"
"total_fmt}")
decoder = self._decoders[self._current_decoder_index]
decoder = self._decoders[self._curr_decoder_index]
self._decoder_pbar = tqdm(total=len(self._SNRs),
desc=f"Calculating"
f"g BERs"
@ -126,8 +128,8 @@ class Simulator:
self._create_pbars()
self._overall_pbar.update(self._current_decoder_index)
self._decoder_pbar.update(self._current_SNRs_index)
self._overall_pbar.update(self._curr_decoder_index)
self._decoder_pbar.update(self._curr_SNRs_index)
self._snr_pbar.update(self._curr_num_frame_errors)
self._overall_pbar.refresh()
@ -139,13 +141,18 @@ class Simulator:
:return: Number of bit errors that occurred
"""
SNR = self._SNRs[self._current_SNRs_index]
decoder = self._decoders[self._current_decoder_index]
SNR = self._SNRs[self._curr_SNRs_index]
decoder = self._decoders[self._curr_decoder_index]
y = noise.add_awgn(self._x_bpsk, SNR, self._n, self._k)
x_hat = decoder.decode(y)
return count_bit_errors(self._x, x_hat)
# Handle decoding failure
if x_hat is not None:
return count_bit_errors(self._x, x_hat)
else:
self._curr_num_dec_fails += 1
return 0
def _update_statistics(self, bit_errors: int) -> None:
"""Update the statistics of the simulator.
@ -164,36 +171,42 @@ class Simulator:
def _advance_state(self) -> None:
"""Advance the state of the simulator.
This function also appends a new BER value to the self._BERs array
if the number of target frame errors has been reached
This function also handles setting the result arrays and progress bars.
"""
if (self._curr_num_frame_errors >= self._target_frame_errors) or (
self._curr_num_iterations > self._max_num_iterations):
self._BERs[self._current_decoder_index] \
.append(self._curr_num_bit_errors / (
self._curr_num_iterations * self._n))
# Adjust the number of iterations to ignore decoding failures
adj_num_iterations = self._curr_num_iterations - \
self._curr_num_dec_fails
self._BERs[self._curr_decoder_index][self._curr_SNRs_index] \
= self._curr_num_bit_errors / (
adj_num_iterations * self._n)
self._dec_fails[self._curr_decoder_index][self._curr_SNRs_index] \
= self._curr_num_dec_fails
self._curr_num_frame_errors = 0
self._curr_num_bit_errors = 0
self._curr_num_iterations = 0
self._curr_num_dec_fails = 0
if self._current_SNRs_index < len(self._SNRs) - 1:
self._current_SNRs_index += 1
if self._curr_SNRs_index < len(self._SNRs) - 1:
self._curr_SNRs_index += 1
self._snr_pbar.reset()
self._snr_pbar.set_description(
f"Simulating for SNR = "
f"{self._SNRs[self._current_SNRs_index]} dB")
f"{self._SNRs[self._curr_SNRs_index]} dB")
self._decoder_pbar.update(1)
else:
if self._current_decoder_index < len(self._decoders) - 1:
self._current_decoder_index += 1
self._current_SNRs_index = 0
self._BERs.append([])
if self._curr_decoder_index < len(self._decoders) - 1:
self._curr_decoder_index += 1
self._curr_SNRs_index = 0
self._decoder_pbar.reset()
decoder = self._decoders[self._current_decoder_index]
decoder = self._decoders[self._curr_decoder_index]
self._decoder_pbar.set_description(
f"Calculating BERs for {decoder.__class__.__name__}")
self._overall_pbar.update(1)
@ -228,22 +241,15 @@ class Simulator:
been calculated are set to 0.
:return: pandas Dataframe with the columns ["SNR", "BER_1", "BER_2",
...]
..., "DecFails_1", "DecFails_2", ...]
"""
data = {"SNR": np.array(self._SNRs)}
# If the BERs of a decoder have not been calculated for all SNRs,
# fill the rest up with zeros to match the length of the 'SNRs' array
for i, decoder_BER_list in enumerate(self._BERs):
padded = np.pad(decoder_BER_list,
(0, len(self._SNRs) - len(decoder_BER_list)))
data[f"BER_{i}"] = padded
for i, decoder_BERs in enumerate(self._BERs):
data[f"BER_{i}"] = decoder_BERs
# If the BERs have not been calculated for all decoders, fill up the
# BERs list
# with zero-vectors to match the length of the 'decoders' list
for i in range(len(self._decoders), len(self._BERs)):
data[f"BER_{i}"] = np.zeros(len(self._SNRs))
for i, decoder_dec_fails in enumerate(self._dec_fails):
data[f"DecFails_{i}"] = decoder_dec_fails
return pd.DataFrame(data)