From fffb15595b7f33195f71a536d7cc93f47551e660 Mon Sep 17 00:00:00 2001 From: Andreas Tsouchlos Date: Wed, 7 May 2025 16:01:11 +0200 Subject: [PATCH] Simulate multiple SNRs --- python/examples/simulate_error_rate.py | 39 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/python/examples/simulate_error_rate.py b/python/examples/simulate_error_rate.py index 52ed0e1..e64a8a8 100644 --- a/python/examples/simulate_error_rate.py +++ b/python/examples/simulate_error_rate.py @@ -4,6 +4,7 @@ import galois import argparse from dataclasses import dataclass from tqdm import tqdm +import pandas as pd # autopep8: off import sys @@ -47,7 +48,7 @@ def decode(tracker, y, H, args: SimulationArgs) -> np.ndarray: return x_hat -def simulate_error_rates_for_SNR(H, Eb_N0, args: SimulationArgs) -> typing.Tuple[np.ndarray, np.ndarray, np.ndarray]: +def simulate_error_rates_for_SNR(H, Eb_N0, args: SimulationArgs) -> typing.Tuple[float, float, float, int]: GF = galois.GF(2) H_GF = GF(H) G = H_GF.null_space() @@ -84,14 +85,29 @@ def simulate_error_rates_for_SNR(H, Eb_N0, args: SimulationArgs) -> typing.Tuple num_frames += 1 - if frame_errors > args.target_frame_errors: + if frame_errors >= args.target_frame_errors: break BER = bit_errors / (num_frames * n) FER = frame_errors / num_frames DFR = decoding_failures / num_frames - return FER, BER, DFR + return FER, BER, DFR, frame_errors + + +def simulate_error_rates(H, Eb_N0_list, args: SimulationArgs) -> typing.Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + FERs = [] + BERs = [] + DFRs = [] + frame_errors_list = [] + for SNR in Eb_N0_list: + FER, BER, DFR, num_frames = simulate_error_rates_for_SNR(H, SNR, args) + FERs.append(FER) + BERs.append(BER) + DFRs.append(DFR) + frame_errors_list.append(num_frames) + + return np.array(FERs), np.array(BERs), np.array(DFRs), np.array(frame_errors_list) def main(): @@ -101,9 +117,10 @@ def main(): parser.add_argument("-c", "--code", type=str, required=True, help="Path to the alist file containing the parity check matrix of the code") - # TODO: Extend this script to multiple SRNs - parser.add_argument("--snr", type=float, required=True, - help="Eb/N0 to use for this simulation") + parser.add_argument("--snr", type=float, required=True, nargs=3, + metavar=('start', 'stop', 'step'), + help="SNRs to simulate (Eb/N0) in dB") + parser.add_argument("--max-frames", type=int, default=int(1e6), help="Maximum number of frames to simulate") parser.add_argument("--target-frame-errors", type=int, default=200, @@ -139,12 +156,12 @@ def main(): max_frames=args.max_frames, target_frame_errors=args.target_frame_errors) - FER, BER, DFR = simulate_error_rates_for_SNR(H, args.snr, simulation_args) - - print(f"FER: {FER}") - print(f"DFR: {DFR}") - print(f"BER: {BER}") + SNRs = np.arange(args.snr[0], args.snr[1], args.snr[2]) + FERs, BERs, DFRs, frame_errors_list = simulate_error_rates( + H, SNRs, simulation_args) + df = pd.DataFrame({"SNR": SNRs, "FER": FERs, "BER": BERs, "DFR": DFRs, "frame_errors": frame_errors_list}) + print(df) if __name__ == "__main__": main()