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