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_decoder.hh"
#include "polar_encoder.hh"
#include "polar_freezer.hh"
#include "polar_sequence.hh"
bool get_bit(const uint32_t *bits, int idx)
@ -27,8 +26,8 @@ int main()
{
const int M = 20;
const int N = 1 << M;
const bool systematic = true;
#if 1
const bool systematic = false;
#if 0
typedef int8_t code_type;
double SCALE = 2;
#else
@ -44,19 +43,13 @@ int main()
auto codeword = 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;
double design_SNR = 10 * std::log10(-std::log(erasure_probability));
std::cerr << "design SNR: " << design_SNR << std::endl;
double better_SNR = design_SNR + 0.5;//1.59175;
std::cerr << "better SNR: " << better_SNR << std::endl;
double probability = std::exp(-pow(10.0, better_SNR / 10));
if (1) {
auto freeze = new CODE::PolarCodeConst0<M>;
std::cerr << "sizeof(PolarCodeConst0<M>) = " << sizeof(CODE::PolarCodeConst0<M>) << std::endl;
(*freeze)(frozen, M, K, probability);
delete freeze;
} else {
auto sequence = new int[N];
auto construct = new CODE::PolarSeqConst0<M>;
std::cerr << "sizeof(PolarSeqConst0<M>) = " << sizeof(CODE::PolarSeqConst0<M>) << std::endl;
@ -66,7 +59,19 @@ int main()
frozen[i] = 0;
for (int i = 0; i < N - K; ++i)
frozen[sequence[i]/32] |= 1 << (sequence[i]%32);
delete[] sequence;
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 {
for (int i = 0; i < K; ++i)
segment_mapping[i] = std::min(i / (K / segments), segments - 1);
}
std::cerr << "Polar(" << N << ", " << K << ")" << std::endl;
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;
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];
double low_SNR = std::floor(design_SNR-3);
double high_SNR = std::ceil(design_SNR+5);
double min_SNR = high_SNR, max_mbs = 0;
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 high_SNR = std::ceil(design_SNR+.5);
for (double SNR = low_SNR; SNR <= high_SNR; SNR += 0.1) {
//double mean_signal = 0;
double sigma_signal = 1;
double mean_noise = 0;
@ -91,13 +91,9 @@ int main()
typedef std::normal_distribution<double> normal;
auto awgn = std::bind(normal(mean_noise, sigma_noise), generator(rd()));
int64_t awgn_errors = 0;
int64_t quantization_erasures = 0;
int64_t uncorrected_errors = 0;
int64_t ambiguity_erasures = 0;
double avg_mbs = 0;
int64_t segment_errors[segments] = { 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)
message[i] = 1 - 2 * data();
@ -112,9 +108,6 @@ int main()
encode(codeword, message, frozen, M);
}
for (int i = 0; i < N; ++i)
orig[i] = codeword[i];
for (int i = 0; i < N; ++i)
symb[i] = codeword[i];
@ -128,15 +121,7 @@ int main()
for (int i = 0; i < N; ++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);
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) {
CODE::PolarEncoder<code_type> encode;
@ -146,46 +131,16 @@ int main()
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)
uncorrected_errors += decoded[i] * message[i] <= 0;
for (int i = 0; i < K; ++i)
ambiguity_erasures += !decoded[i];
segment_errors[(int)segment_mapping[i]] += decoded[i] * message[i] <= 0;
}
for (int i = 0; i < segments - 1; ++i)
segment_errors[i + 1] += segment_errors[i];
avg_mbs /= loops;
max_mbs = std::max(max_mbs, avg_mbs);
double bit_error_rate = (double)uncorrected_errors / (double)(K * loops);
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::cout << SNR;
for (int i = 0; i < segments; ++i)
std::cout << " " << double(segments * segment_errors[i]) / double(K * loops * (i + 1));
std::cout << 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;
}