Compare commits

...

1 commit

Author SHA1 Message Date
Ahmet Inan
ed4fe54ee9 experimenting with ordered reliability message bits
wanted to see if this can be exploited for graceful degradation but the
effect is minimal. order of reliability does not matter, but order of
decoding of message bits gives a very marginal effect.
This means that the probability of an errornous decode of a message bit
at the beginning is less likely than at the end, as a single error will
produce a cascade effect that breaks all later decoded bits.
2023-07-07 15:12:29 +02:00

View file

@ -15,7 +15,6 @@ Copyright 2020 Ahmet Inan <inan@aicodix.de>
#include "polar_helper.hh" #include "polar_helper.hh"
#include "polar_decoder.hh" #include "polar_decoder.hh"
#include "polar_encoder.hh" #include "polar_encoder.hh"
#include "polar_freezer.hh"
#include "polar_sequence.hh" #include "polar_sequence.hh"
bool get_bit(const uint32_t *bits, int idx) bool get_bit(const uint32_t *bits, int idx)
@ -27,8 +26,8 @@ int main()
{ {
const int M = 20; const int M = 20;
const int N = 1 << M; const int N = 1 << M;
const bool systematic = true; const bool systematic = false;
#if 1 #if 0
typedef int8_t code_type; typedef int8_t code_type;
double SCALE = 2; double SCALE = 2;
#else #else
@ -44,29 +43,35 @@ int main()
auto codeword = new code_type[N]; auto codeword = new code_type[N];
auto temp = new code_type[N]; auto temp = new code_type[N];
double erasure_probability = 1. / 3.; double erasure_probability = 1. / 2.;
int K = (1 - erasure_probability) * N; int K = (1 - erasure_probability) * N;
double design_SNR = 10 * std::log10(-std::log(erasure_probability)); double design_SNR = 10 * std::log10(-std::log(erasure_probability));
std::cerr << "design SNR: " << design_SNR << std::endl; std::cerr << "design SNR: " << design_SNR << std::endl;
double better_SNR = design_SNR + 0.5;//1.59175; double better_SNR = design_SNR + 0.5;//1.59175;
std::cerr << "better SNR: " << better_SNR << std::endl; std::cerr << "better SNR: " << better_SNR << std::endl;
double probability = std::exp(-pow(10.0, better_SNR / 10)); double probability = std::exp(-pow(10.0, better_SNR / 10));
if (1) { auto sequence = new int[N];
auto freeze = new CODE::PolarCodeConst0<M>; auto construct = new CODE::PolarSeqConst0<M>;
std::cerr << "sizeof(PolarCodeConst0<M>) = " << sizeof(CODE::PolarCodeConst0<M>) << std::endl; std::cerr << "sizeof(PolarSeqConst0<M>) = " << sizeof(CODE::PolarSeqConst0<M>) << std::endl;
(*freeze)(frozen, M, K, probability); (*construct)(sequence, M, probability);
delete freeze; delete construct;
for (int i = 0; i < N / 32; ++i)
frozen[i] = 0;
for (int i = 0; i < N - K; ++i)
frozen[sequence[i]/32] |= 1 << (sequence[i]%32);
const int segments = 4;
auto segment_mapping = new char[N];
for (int i = 0; i < N; ++i)
segment_mapping[i] = -1;
if (0) {
for (int i = 0; i < K; ++i)
segment_mapping[sequence[N-1-i]] = std::min(i / (K / segments), segments - 1);
for (int i = 0, j = 0; i < N; ++i)
if (segment_mapping[i] >= 0)
segment_mapping[j++] = segment_mapping[i];
} else { } else {
auto sequence = new int[N]; for (int i = 0; i < K; ++i)
auto construct = new CODE::PolarSeqConst0<M>; segment_mapping[i] = std::min(i / (K / segments), segments - 1);
std::cerr << "sizeof(PolarSeqConst0<M>) = " << sizeof(CODE::PolarSeqConst0<M>) << std::endl;
(*construct)(sequence, M, probability);
delete construct;
for (int i = 0; i < N / 32; ++i)
frozen[i] = 0;
for (int i = 0; i < N - K; ++i)
frozen[sequence[i]/32] |= 1 << (sequence[i]%32);
delete[] sequence;
} }
std::cerr << "Polar(" << N << ", " << K << ")" << std::endl; std::cerr << "Polar(" << N << ", " << K << ")" << std::endl;
auto message = new code_type[K]; auto message = new code_type[K];
@ -74,15 +79,10 @@ int main()
std::cerr << "sizeof(PolarDecoder<code_type, M>) = " << sizeof(CODE::PolarDecoder<code_type, M>) << std::endl; std::cerr << "sizeof(PolarDecoder<code_type, M>) = " << sizeof(CODE::PolarDecoder<code_type, M>) << std::endl;
auto decode = new CODE::PolarDecoder<code_type, M>; auto decode = new CODE::PolarDecoder<code_type, M>;
auto orig = new code_type[N];
auto noisy = new code_type[N];
auto symb = new double[N]; auto symb = new double[N];
double low_SNR = std::floor(design_SNR-3); double low_SNR = std::floor(design_SNR-3);
double high_SNR = std::ceil(design_SNR+5); double high_SNR = std::ceil(design_SNR+.5);
double min_SNR = high_SNR, max_mbs = 0; for (double SNR = low_SNR; SNR <= high_SNR; SNR += 0.1) {
int count = 0;
std::cerr << "SNR BER Mbit/s Eb/N0" << std::endl;
for (double SNR = low_SNR; count <= 3 && SNR <= high_SNR; SNR += 0.1, ++count) {
//double mean_signal = 0; //double mean_signal = 0;
double sigma_signal = 1; double sigma_signal = 1;
double mean_noise = 0; double mean_noise = 0;
@ -91,13 +91,9 @@ int main()
typedef std::normal_distribution<double> normal; typedef std::normal_distribution<double> normal;
auto awgn = std::bind(normal(mean_noise, sigma_noise), generator(rd())); auto awgn = std::bind(normal(mean_noise, sigma_noise), generator(rd()));
int64_t awgn_errors = 0; int64_t segment_errors[segments] = { 0 };
int64_t quantization_erasures = 0;
int64_t uncorrected_errors = 0;
int64_t ambiguity_erasures = 0;
double avg_mbs = 0;
int64_t loops = 0; int64_t loops = 0;
while (uncorrected_errors < 1000 && ++loops < 100) { while (segment_errors[0] < 100000 && ++loops < 10000) {
for (int i = 0; i < K; ++i) for (int i = 0; i < K; ++i)
message[i] = 1 - 2 * data(); message[i] = 1 - 2 * data();
@ -112,9 +108,6 @@ int main()
encode(codeword, message, frozen, M); encode(codeword, message, frozen, M);
} }
for (int i = 0; i < N; ++i)
orig[i] = codeword[i];
for (int i = 0; i < N; ++i) for (int i = 0; i < N; ++i)
symb[i] = codeword[i]; symb[i] = codeword[i];
@ -128,15 +121,7 @@ int main()
for (int i = 0; i < N; ++i) for (int i = 0; i < N; ++i)
codeword[i] = CODE::PolarHelper<code_type>::quant(fact * symb[i]); codeword[i] = CODE::PolarHelper<code_type>::quant(fact * symb[i]);
for (int i = 0; i < N; ++i)
noisy[i] = codeword[i];
auto start = std::chrono::system_clock::now();
(*decode)(decoded, codeword, frozen, M); (*decode)(decoded, codeword, frozen, M);
auto end = std::chrono::system_clock::now();
auto usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
double mbs = (double)K / usec.count();
avg_mbs += mbs;
if (systematic) { if (systematic) {
CODE::PolarEncoder<code_type> encode; CODE::PolarEncoder<code_type> encode;
@ -146,46 +131,16 @@ int main()
decoded[j++] = temp[i]; decoded[j++] = temp[i];
} }
for (int i = 0; i < N; ++i)
awgn_errors += noisy[i] * (orig[i] < 0);
for (int i = 0; i < N; ++i)
quantization_erasures += !noisy[i];
for (int i = 0; i < K; ++i) for (int i = 0; i < K; ++i)
uncorrected_errors += decoded[i] * message[i] <= 0; segment_errors[(int)segment_mapping[i]] += decoded[i] * message[i] <= 0;
for (int i = 0; i < K; ++i)
ambiguity_erasures += !decoded[i];
} }
for (int i = 0; i < segments - 1; ++i)
segment_errors[i + 1] += segment_errors[i];
avg_mbs /= loops; std::cout << SNR;
for (int i = 0; i < segments; ++i)
max_mbs = std::max(max_mbs, avg_mbs); std::cout << " " << double(segments * segment_errors[i]) / double(K * loops * (i + 1));
double bit_error_rate = (double)uncorrected_errors / (double)(K * loops); std::cout << std::endl;
if (!uncorrected_errors)
min_SNR = std::min(min_SNR, SNR);
else
count = 0;
int MOD_BITS = 1; // BPSK
double code_rate = (double)K / (double)N;
double spectral_efficiency = code_rate * MOD_BITS;
double EbN0 = 10 * std::log10(sigma_signal * sigma_signal / (spectral_efficiency * 2 * sigma_noise * sigma_noise));
if (0) {
std::cerr << SNR << " Es/N0 => AWGN with standard deviation of " << sigma_noise << " and mean " << mean_noise << std::endl;
std::cerr << EbN0 << " Eb/N0, using spectral efficiency of " << spectral_efficiency << " from " << code_rate << " code rate and " << MOD_BITS << " bits per symbol." << std::endl;
std::cerr << awgn_errors << " errors caused by AWGN." << std::endl;
std::cerr << quantization_erasures << " erasures caused by quantization." << std::endl;
std::cerr << uncorrected_errors << " errors uncorrected." << std::endl;
std::cerr << ambiguity_erasures << " ambiguity erasures." << std::endl;
std::cerr << bit_error_rate << " bit error rate." << std::endl;
std::cerr << avg_mbs << " megabit per second." << std::endl;
} else {
std::cout << SNR << " " << bit_error_rate << " " << avg_mbs << " " << EbN0 << std::endl;
}
} }
std::cerr << "QEF at: " << min_SNR << " SNR, speed: " << max_mbs << " Mb/s." << std::endl;
double QEF_SNR = design_SNR + 0.2;
assert(min_SNR < QEF_SNR);
std::cerr << "Polar regression test passed!" << std::endl;
return 0; return 0;
} }