Many changes here and there. I lost track... :-(
Current work is on MLSE and SD Decoding etc. MLSE is currently not 100% working, the scalings are maybe off?!
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
function [ach_inf_rate] = calc_air(test_signal,reference_signal,options)
|
||||
% Calculation of AIR acc. to J. Kozesnik, „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5.
|
||||
% „Numerically Computing Achievable Rates of Memoryless Channels“, Francisco Javier Garcıa-Gomez, doi: 10.1007/978-94-009-9857-5.
|
||||
% Implementation is not accessible, I mailed TUM to get the code...
|
||||
|
||||
arguments(Input)
|
||||
@@ -26,7 +26,7 @@ end
|
||||
% TRIM
|
||||
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
|
||||
|
||||
% CALC EVM
|
||||
% CALC AIR
|
||||
%%% new implementation of AIR
|
||||
constellation = unique(reference_signal);
|
||||
reference_idx = arrayfun(@(x) find(constellation == x, 1), reference_signal);
|
||||
|
||||
94
Functions/Metrics/calc_gmi_bitwise.m
Normal file
94
Functions/Metrics/calc_gmi_bitwise.m
Normal file
@@ -0,0 +1,94 @@
|
||||
function [GMI,NGMI] = calc_gmi_bitwise(test_signal,reference_signal,options)
|
||||
% https://cioffi-group.stanford.edu/doc/book/AppendixG.pdf
|
||||
|
||||
arguments(Input)
|
||||
test_signal;
|
||||
reference_signal;
|
||||
options.skip_front = 0;
|
||||
options.skip_end = 0;
|
||||
options.returnErrorLocation = 0;
|
||||
end
|
||||
|
||||
options.skip_end = abs(options.skip_end);
|
||||
options.skip_front = abs(options.skip_front);
|
||||
|
||||
assert((options.skip_end+options.skip_front)<length(test_signal),"You can not skip more bits than overall length of data! Set skip_front or skip_end to lower value or check data_in");
|
||||
|
||||
if isa(reference_signal,'Signal')
|
||||
reference_signal = reference_signal.signal;
|
||||
end
|
||||
|
||||
if isa(test_signal,'Signal')
|
||||
test_signal = test_signal.signal;
|
||||
end
|
||||
|
||||
% TRIM
|
||||
[test_signal,reference_signal]=trimseq(test_signal,reference_signal,options.skip_front,options.skip_end);
|
||||
|
||||
% CALC AIR
|
||||
%%% new implementation of AIR
|
||||
% Precompute
|
||||
N = length(test_signal);
|
||||
M = numel(unique(reference_signal));
|
||||
nBits = log2(M);
|
||||
levels = PAMmapper(M,0).levels / PAMmapper(M,0).scaling;
|
||||
grayBits= PAMmapper(M,0).showBitMapping;
|
||||
priors = ones(1,M)/M;
|
||||
|
||||
noise = test_signal-reference_signal;
|
||||
sigma2 = var(noise);
|
||||
|
||||
% Allocate
|
||||
LLR = zeros(N, nBits);
|
||||
rxBits = zeros(N, nBits);
|
||||
|
||||
for n = 1:N
|
||||
y = test_signal(n);
|
||||
ll_table= -((y - levels).^2)/(2*sigma2) + log(priors); % M×1
|
||||
|
||||
% Per‐bit LLR
|
||||
for b = 1:nBits
|
||||
idx0 = grayBits(:,b)==0;
|
||||
idx1 = grayBits(:,b)==1;
|
||||
L0 = logsumexp(ll_table(idx0));
|
||||
L1 = logsumexp(ll_table(idx1));
|
||||
LLR(n,b) = L1 - L0;
|
||||
end
|
||||
end
|
||||
|
||||
tx_bits = PAMmapper(M,0,"eth_style",0).demap(reference_signal);
|
||||
|
||||
% Compute GMI (bit‐wise MI averaged over all symbols)
|
||||
MI_bits = zeros(1,nBits);
|
||||
for b = 1:nBits
|
||||
r0 = LLR(tx_bits(:,b)==0,b);
|
||||
r1 = LLR(tx_bits(:,b)==1,b);
|
||||
I0 = mean( log2(1 + exp(r0)) );
|
||||
I1 = mean( log2(1 + exp( -r1)) );
|
||||
MI_bits(b) = 1 - 0.5*(I0 + I1);
|
||||
end
|
||||
|
||||
GMI = sum(MI_bits); % in bits per symbol
|
||||
NGMI = GMI / nBits; % normalized per bit
|
||||
|
||||
% Auxiliary nested helper for numerically stable log-sum-exp
|
||||
function s = logsumexp(a)
|
||||
% LOGSUMEXP Compute log(sum(exp(a))) in a numerically stable way
|
||||
m = max(a);
|
||||
s = m + log(sum(exp(a - m)));
|
||||
end
|
||||
|
||||
|
||||
function [data_,reference_]=trimseq(data,reference,skipstart,skip_end)
|
||||
|
||||
data_ = data(skipstart+1:end-skip_end,:);
|
||||
|
||||
delta_bits = length(reference) - length(data);
|
||||
|
||||
skip_end = delta_bits + skip_end;
|
||||
|
||||
reference_ = reference(skipstart+1:end-skip_end,:);
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
function [GMI,NGMI] = calc_ngmi(test_signal,reference_signal,options)
|
||||
% Silas implementation of (N)GMI calculation according to: J. Cho, L. Schmalen, und P. J. Winzer,
|
||||
% Silas implementation of (N)GMI calculation according to: J. Cho, L. Schmalen, und P. J. Winzer,
|
||||
% „Normalized Generalized Mutual Information as a Forward Error Correction Threshold for Probabilistically Shaped QAM“,
|
||||
% in 2017 European Conference on Optical Communication (ECOC), Sep. 2017, doi: 10.1109/ECOC.2017.8345872.
|
||||
|
||||
@@ -38,7 +38,7 @@ end
|
||||
|
||||
assert(length(test_signal) == length(reference_signal),"Sequence length does not match");
|
||||
|
||||
%%% implemented according to [1] J. Cho, L. Schmalen, und P. J. Winzer,
|
||||
%%% implemented according to [1] J. Cho, L. Schmalen, und P. J. Winzer,
|
||||
% „Normalized Generalized Mutual Information as a Forward Error Correction Threshold for Probabilistically Shaped QAM“,
|
||||
% in 2017 European Conference on Optical Communication (ECOC), Sep. 2017, S. 1–3. doi: 10.1109/ECOC.2017.8345872.
|
||||
|
||||
@@ -62,7 +62,7 @@ end
|
||||
m = log2(M); %bits per symbol
|
||||
|
||||
entries = sum(~isnan(received_sd),2)';
|
||||
P_X = entries./N;
|
||||
P_X = ones(1,M)/M;%entries./N;
|
||||
|
||||
% Parameters
|
||||
symbols = constellation'; % PAM-4 symbols
|
||||
@@ -75,18 +75,20 @@ end
|
||||
% Entropy term
|
||||
H_X = -sum(P_X .* log2(P_X)); % Entropy of input distribution
|
||||
|
||||
% GMI computation
|
||||
noise_impact_term = 0;
|
||||
for k = 1:N
|
||||
y_k = test_signal(k); % Current received sample
|
||||
[~, closest_symbol_idx] = min(abs(symbols - y_k)); % Closest symbol index
|
||||
closest_symbol = symbols(closest_symbol_idx); % Closest symbol
|
||||
tx_bits = PAMmapper(M,0,"eth_style",0).demap(reference_signal);
|
||||
|
||||
for i = 1:m
|
||||
% GMI computation
|
||||
bit_llr_sum = 0;
|
||||
for k = 1:N %loop over signal
|
||||
y_k = test_signal(k); % Current received sample
|
||||
% [~, closest_symbol_idx] = min(abs(symbols - y_k)); % Closest symbol index
|
||||
|
||||
for i = 1:m %loop over bit position
|
||||
% Extract i-th bit for each symbol
|
||||
bit_mask = gray_bits(:, i); % Binary column for i-th bit of all symbols
|
||||
|
||||
matching_symbols = symbols(bit_mask == gray_bits(closest_symbol_idx, i));
|
||||
|
||||
% matching_symbols = symbols(bit_mask == gray_bits(closest_symbol_idx, i)); %old, based on decision that mihht be wrong
|
||||
matching_symbols = symbols(bit_mask == tx_bits(k,i)); %new, based on tx bits
|
||||
|
||||
% Numerator: Sum over x in x_{b_{k, i}}
|
||||
numerator = sum(q_Y_given_X(y_k, matching_symbols) .* P_X(ismember(symbols, matching_symbols)));
|
||||
@@ -95,15 +97,15 @@ end
|
||||
denominator = sum(q_Y_given_X(y_k, symbols) .* P_X);
|
||||
|
||||
% Logarithmic contribution
|
||||
noise_impact_term = noise_impact_term + log2(numerator / denominator);
|
||||
bit_llr_sum = bit_llr_sum + log2(numerator / denominator);
|
||||
end
|
||||
end
|
||||
|
||||
% Normalize the noise impact term by N
|
||||
noise_impact_term = noise_impact_term / N;
|
||||
bit_llr_sum = bit_llr_sum / N;
|
||||
|
||||
% GMI
|
||||
GMI = H_X + noise_impact_term;
|
||||
GMI = H_X + bit_llr_sum;
|
||||
NGMI = GMI / m;
|
||||
|
||||
end
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
function [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||
% CALC_SNR Calculates overall SNR and level-wise SNR for a PAM-M constellation.
|
||||
%
|
||||
% [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||
%
|
||||
% Inputs:
|
||||
% tx_signal - Vector of transmitted signal values.
|
||||
% eq_noise - Vector of corresponding noise samples.
|
||||
%
|
||||
% Outputs:
|
||||
% snr_all - Overall SNR computed using all signal values.
|
||||
% snr_per_level - A vector where each element is the SNR computed
|
||||
% for a unique amplitude level in tx_signal.
|
||||
%
|
||||
% The function first computes the overall SNR using the full signal vectors.
|
||||
% Then it uses the unique levels in tx_signal to calculate the SNR for
|
||||
% the symbols corresponding to each level separately.
|
||||
|
||||
% CALC_SNR Calculates overall SNR and level-wise SNR for a PAM-M constellation.
|
||||
%
|
||||
% [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||
%
|
||||
% Inputs:
|
||||
% tx_signal - Vector of transmitted signal values.
|
||||
% eq_noise - Vector of corresponding noise samples.
|
||||
%
|
||||
% Outputs:
|
||||
% snr_all - Overall SNR computed using all signal values.
|
||||
% snr_per_level - A vector where each element is the SNR computed
|
||||
% for a unique amplitude level in tx_signal.
|
||||
%
|
||||
% The function first computes the overall SNR using the full signal vectors.
|
||||
% Then it uses the unique levels in tx_signal to calculate the SNR for
|
||||
% the symbols corresponding to each level separately.
|
||||
|
||||
if isa(tx_signal,'Signal')
|
||||
tx_signal = tx_signal.signal;
|
||||
end
|
||||
|
||||
if isa(eq_noise,'Signal')
|
||||
eq_noise = eq_noise.signal;
|
||||
end
|
||||
|
||||
% Calculate overall SNR using the complete signals
|
||||
snr_all = snr(tx_signal, eq_noise);
|
||||
|
||||
|
||||
% Get the unique amplitude levels in the transmitted signal
|
||||
levels = unique(tx_signal);
|
||||
|
||||
@@ -27,10 +35,10 @@ function [snr_all, snr_per_level] = calc_snr(tx_signal, eq_noise)
|
||||
for i = 1:length(levels)
|
||||
% Find indices where tx_signal equals the current level
|
||||
idx = (tx_signal == levels(i));
|
||||
|
||||
|
||||
% Compute the SNR for these indices
|
||||
snr_per_level(i) = snr(tx_signal(idx), eq_noise(idx));
|
||||
|
||||
|
||||
histogram(eq_noise(idx));
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user