Add some older Theory projects from the past years

This commit is contained in:
2026-03-25 09:45:42 +01:00
parent 5b90bc11a0
commit b4e735148e
17 changed files with 514 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
w0 = [1290:2:1290+15*2]';
w0 = [1290:2:1290+15*2]';
w0 = [ 1302 1304 1306 1308]';
%w0 = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]';
m = 0.5*(numel(w0)^3 - numel(w0)^2);
a = [1,1,1]';
w = w0;
for o = 2:3
p = nchoosek(w,3);
q = [];
parfor i = 1:size(p,1)
q_ = perms(p(i,:));
q = [q;q_];
end
p = q;
%p = unique(q,"rows");
w_ = p(:,1) + p(:,2) - p(:,3);
a_ = ones(size(w_)).* 1/o;
w = [w ; w_];
a = [a ; a_];
% w = unique(w);
% a = unique(a);
m(end+1) = 0.5*(numel(w)^3 - numel(w)^2);
end
figure(11)
hold on
lambda = min(w):max(w);
gen = sum(lambda == w,1);
gen(gen==0) = NaN;
stem(lambda,gen,"filled",'LineWidth',1,'Marker','o','MarkerSize',2,'LineStyle',':')
initial = sum(lambda == w0,1);
initial(initial==0) = NaN;
stem(lambda,initial,"filled",'LineWidth',1.5,'MarkerSize',5,'Marker','^');
xlabel('Wavelength');
ylabel('number of FWM products');
grid minor
legend('Generated Products', 'Initial Channel Position')
AxesMain = gca;
fig = gcf;
fontsize(AxesMain,8,"points")
fig.Units = "centimeters";
fig.Position = [2 2 8.5 7];

View File

@@ -0,0 +1,43 @@
%% Laser Offset Statistics
figure
for i = 1
res = 1.7e6;
n_chann = 16;
df_T_exact = (-n_chann/2+0.5:n_chann/2).* 200e9;
for key = 1:100
laser_frequency_imperfection(key,:) = res .* round(randn(1,n_chann)*i*100);
df_T(key,:) = df_T_exact + laser_frequency_imperfection(key,:);
end
hold on
histogram(laser_frequency_imperfection.*1e-6,100,"Normalization","probability","EdgeColor","none","FaceAlpha",0.3,'DisplayName',['Std. Dev.: ',num2str(mean(std(laser_frequency_imperfection))*1e-6),' MHz']);
xlabel('Laser Frequency Offset in MHz');
ylabel('Probability');
title(['Laser deviations from exact grid.'])
end
%% ZDW Statistics
for k = 1:1000
% Set parameters
meanUniformMin = 1309;
meanUniformMax = 1315;
meanValue = 1310;
sigma = 2;
% Seed the random number generator (assuming Mersenne Twister)
rng(k);
% Generate normally distributed random numbers
randomNumbers(k,:) = normrnd(meanValue, sigma, [n_chann, 1]).';
end
figure;
histogram(randomNumbers,100,"Normalization","probability","EdgeColor","none");
xlabel('ZDW in nm');
ylabel('Probability');

View File

@@ -0,0 +1,65 @@
%%FWM analysis from "Analytical Calculation of the Number of
%%Four-Wave-Mixing Products in Optical Multichannel Communication Systems"
N_ = [4,8,16];
df_hz = 400e9;
center_nm = 1310;
figure()
for i = 1:length(N_)
vec = (2*N_(i)-1:-1:2-N_(i)) -(N_(i)/2+0.5);
channelplan_hz = nm2hz(center_nm) + (vec * df_hz) ;
channelplan_nm = hz2nm(channelplan_hz);
[Mndg,Mdg] = getProducts(N_(i));
total(i) = sum(Mndg) + sum(Mdg);
subplot(1,length(N_),i)
xline(calcWavelengthPlan(N_(i), df_hz, center_nm));
hold on
stem(channelplan_nm,(Mndg+Mdg),'filled','LineWidth',1,'Marker','o','MarkerSize',2)
stem(channelplan_nm,(Mdg),'filled','LineWidth',1,'Marker','none');
ylim([0,100])
xlim([1260, 1365]);
grid off
xlabel('O-band wavelength region in nm');
ylabel('Number of FWM products');
title([num2str(N_(i)),' ch.'])
end
function [Mndg,Mdg] = getProducts(N)
s = abs(2-N-1) ;
for n = 2-N:2*N-1
if n<-N
Mdg(n+s) = 0;
elseif (-N <= n)&&(n <= 0)
Mdg(n+s) = N - ceil((N-n)/2);
elseif (1 <= n)&&(n <= N)
Mdg(n+s) = N - 1 - floor(n/2) - ceil((N-n)/2);
elseif (N < n)&&(n <= 2*N)
Mdg(n+s) = N - floor(n/2);
elseif n > 2*N
Mdg(n+s) = 0;
end
if n<-N
Mndg(n+s) = 0;
elseif (-N <= n)&&(n < 1)
Mndg(n+s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
elseif (1 <= n)&&(n <= N)
Mndg(n+s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
elseif (N < n)&&(n <= 2*N)
Mndg(n+s) = floor(N^2 + n^2 /4 - N*n);
elseif n > 2*N
Mndg(n+s) = 0;
end
end
end

View File

@@ -0,0 +1,23 @@
function [eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm)
% FWM efficiency including phase mismatch and attenuation.
% alphaDbPerKm is the power attenuation in dB/km, Lkm is the fiber length in km.
deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds);
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
Lm = Lkm .* 1e3;
denominator = alphaNpPerM.^2 + deltaBeta.^2;
term1 = alphaNpPerM.^2 ./ denominator;
loss_term = 1 - exp(-alphaNpPerM .* Lm);
if abs(alphaNpPerM) < eps
term2 = 4 .* sin(deltaBeta .* Lm ./ 2).^2 ./ max((alphaNpPerM .* Lm).^2, eps);
else
term2 = 1 + 4 .* exp(-alphaNpPerM .* Lm) .* sin(deltaBeta .* Lm ./ 2).^2 ./ (loss_term.^2);
end
eta = term1 .* term2;
end

View File

@@ -0,0 +1,48 @@
function [P_fwm, eta, deltaBeta, Leff] = calcFwmPower( ...
f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm, ...
P_i, P_j, P_k, gammaWInvKmInv, degeneracyFactor)
% Calculate FWM power for a fiber with attenuation and phase mismatch.
%
% Inputs:
% f_i, f_j, f_k, f_0 : frequencies in Hz
% Ds : dispersion slope in ps / (nm^2 km)
% alphaDbPerKm : attenuation in dB/km
% Lkm : fiber length in km
% P_i, P_j, P_k : launch powers in W
% gammaWInvKmInv : nonlinear coefficient in 1/(W km)
% degeneracyFactor : typically 3 for degenerate FWM, 6 for non-degenerate
if nargin < 8 || isempty(P_i)
P_i = 1;
end
if nargin < 9 || isempty(P_j)
P_j = P_i;
end
if nargin < 10 || isempty(P_k)
P_k = 1;
end
if nargin < 11 || isempty(gammaWInvKmInv)
gammaWInvKmInv = 1;
end
if nargin < 12 || isempty(degeneracyFactor)
degeneracyFactor = 1;
end
[eta, deltaBeta] = calcFwmEfficiency(f_i, f_j, f_k, f_0, Ds, alphaDbPerKm, Lkm);
alphaNpPerM = alphaDbPerKm .* log(10) ./ 10 ./ 1e3;
Lm = Lkm .* 1e3;
gammaWInvMInv = gammaWInvKmInv ./ 1e3;
if abs(alphaNpPerM) < eps
Leff = Lm;
else
Leff = (1 - exp(-alphaNpPerM .* Lm)) ./ alphaNpPerM;
end
P_fwm = degeneracyFactor .* eta .* ...
(gammaWInvMInv .* Leff).^2 .* ...
P_i .* P_j .* P_k .* ...
exp(-alphaNpPerM .* Lm);
end

View File

@@ -0,0 +1,20 @@
function deltaBeta = calcPhaseMatching(f_i, f_j, f_k, f_0, Ds)
% Approximate phase mismatch for degenerate FWM close to the ZDW.
% Inputs are frequencies in Hz.
% f_i, f_j : pump frequencies (equal in the degenerate case)
% f_k : signal frequency
% f_0 : zero-dispersion frequency
% Ds : dispersion slope in ps / (nm^2 km)
c = physconst('LightSpeed');
pump_frequency = 0.5 .* (f_i + f_j);
lambda_zdw_m = c ./ f_0;
dispersion_slope_si = Ds .* 1e3;
deltaBeta = -(2 .* pi .* lambda_zdw_m.^4 ./ c.^2) .* ...
dispersion_slope_si .* ...
(pump_frequency - f_0) .* ...
(pump_frequency - f_k).^2;
end

View File

@@ -0,0 +1,104 @@
clear;
clc;
% Sweep the degenerate pump frequency around its nominal wavelength.
pump_detuning_hz = (-800:0.01:800) .* 1e9;
% Degenerate FWM setup: two pump photons at f_p and one signal at f_s
% generate an idler at f_i = 2*f_p - f_s.
pump_wavelength_nm = 1310;
signal_wavelength_nm = 1308;
zdw_wavelength_nm = 1310;
f_pump_nominal = wavelength2frequency(pump_wavelength_nm, 'nm');
f_signal_scalar = wavelength2frequency(signal_wavelength_nm, 'nm');
f_zdw_scalar = wavelength2frequency(zdw_wavelength_nm, 'nm');
f_pump = f_pump_nominal + pump_detuning_hz;
f_signal = f_signal_scalar .* ones(size(f_pump));
f_zdw = f_zdw_scalar .* ones(size(f_pump));
f_idler = 2 .* f_pump - f_signal;
% Fiber parameters
dispersion_slope_ps_nm2_km = 0.07;
attenuation_db_per_km = 0.21;
fiber_length_km = 10;
% Launch powers and nonlinear coefficient
pump_power_dbm = 10;
signal_power_dbm = 10;
pump_power_w = dbm2watt(pump_power_dbm);
signal_power_w = dbm2watt(signal_power_dbm);
gamma_w_inv_km_inv = 1.3;
degeneracy_factor = 3;
[P_fwm, eta, delta_beta, L_eff_m] = calcFwmPower( ...
f_pump, f_pump, f_signal, f_zdw, ...
dispersion_slope_ps_nm2_km, attenuation_db_per_km, fiber_length_km, ...
pump_power_w, pump_power_w, signal_power_w, ...
gamma_w_inv_km_inv, degeneracy_factor);
f_pump_thz = f_pump .* 1e-12;
f_zdw_thz = f_zdw_scalar .* 1e-12;
f_signal_thz = f_signal_scalar .* 1e-12;
idler_power_dbm = 10 .* log10(max(P_fwm, realmin) ./ 1e-3);
figure;
tiledlayout(2,1);
ax1 = nexttile;
plot(ax1, f_pump_thz, eta, 'LineWidth', 2);
hold(ax1, 'on');
xline(ax1, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
xline(ax1, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
ylabel(ax1, 'FWM efficiency');
grid(ax1, 'on');
title(ax1, 'FWM Efficiency and Idler Power versus Pump Frequency');
ax2 = nexttile;
plot(ax2, f_pump_thz, idler_power_dbm, 'LineWidth', 2);
hold(ax2, 'on');
xline(ax2, f_zdw_thz, '--r', 'ZDW', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'bottom');
xline(ax2, f_signal_thz, '--k', 'Signal', 'LineWidth', 1.2, ...
'LabelOrientation', 'horizontal', 'LabelVerticalAlignment', 'middle');
xlabel(ax2, 'Pump frequency (THz)');
ylabel(ax2, 'FWM idler power (dBm)');
grid(ax2, 'on');
fprintf('Pump wavelength : %.3f nm -> %.6f THz\n', ...
pump_wavelength_nm, f_pump_nominal .* 1e-12);
fprintf('Signal wavelength : %.3f nm -> %.6f THz\n', ...
signal_wavelength_nm, f_signal_scalar .* 1e-12);
fprintf('ZDW wavelength : %.3f nm -> %.6f THz\n', ...
zdw_wavelength_nm, f_zdw_scalar .* 1e-12);
fprintf('Pump launch power : %.2f dBm -> %.4g W\n', ...
pump_power_dbm, pump_power_w);
fprintf('Signal launch power : %.2f dBm -> %.4g W\n', ...
signal_power_dbm, signal_power_w);
fprintf('Peak FWM efficiency : %.4g\n', max(eta));
fprintf('Peak FWM idler power : %.4g W (%.2f dBm)\n', ...
max(P_fwm), 10 .* log10(max(P_fwm) ./ 1e-3));
fprintf('Effective fiber length : %.4f km\n', L_eff_m ./ 1e3);
fprintf('Idler wavelength range : %.3f nm to %.3f nm\n', ...
min(frequency2wavelength(f_idler, 'nm')), max(frequency2wavelength(f_idler, 'nm')));
fprintf('Max |delta beta| : %.4g 1/m\n', max(abs(delta_beta)));
function wavelength = frequency2wavelength(frequency, outputUnit)
c = physconst('LightSpeed');
wavelength = c ./ frequency;
switch lower(outputUnit)
case 'm'
case 'nm'
wavelength = wavelength .* 1e9;
otherwise
error('Unsupported output unit "%s". Use "m" or "nm".', outputUnit);
end
end
function power_w = dbm2watt(power_dbm)
power_w = 1e-3 .* 10.^(power_dbm ./ 10);
end

View File

@@ -0,0 +1,124 @@
%% Validate the analytical FWM product count against a brute-force reference
% The paper counts channel combinations, not only unique output frequencies:
% non-degenerate: i < j, k ~= i, k ~= j, n = i + j - k
% degenerate: i == j, k ~= i, n = 2*i - k
clear;
clc;
N_values = [4, 8, 16];
plot_N = 8;
fprintf('Validating analytical FWM product count from Goebel and Hanik (2008)\n');
for idxN = 1:numel(N_values)
N = N_values(idxN);
fprintf('\nN = %d\n', N);
[Mndg_ana, Mdg_ana] = getProducts(N);
[Mndg_brute, Mdg_brute, n_values] = getProductsBruteForce(N);
diff_ndg = Mndg_ana - Mndg_brute;
diff_dg = Mdg_ana - Mdg_brute;
fprintf(' Analytical total : %d\n', sum(Mndg_ana) + sum(Mdg_ana));
fprintf(' Brute-force total : %d\n', sum(Mndg_brute) + sum(Mdg_brute));
if all(diff_ndg == 0) && all(diff_dg == 0)
fprintf(' Match : yes\n');
else
fprintf(' Match : no\n');
fprintf(' Non-degenerate diff: %s\n', mat2str(diff_ndg));
fprintf(' Degenerate diff : %s\n', mat2str(diff_dg));
end
if N == plot_N
plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N);
end
end
function [Mndg, Mdg, n_values] = getProductsBruteForce(N)
n_values = (2 - N):(2*N - 1);
Mndg = zeros(size(n_values));
Mdg = zeros(size(n_values));
for idx = 1:numel(n_values)
n = n_values(idx);
% Degenerate products: two identical pumps and one different channel.
for i = 1:N
k = 2*i - n;
if isValidChannel(k, N) && (k ~= i)
Mdg(idx) = Mdg(idx) + 1;
end
end
% Non-degenerate products: unordered pump pair plus one third channel.
for i = 1:N
for j = (i + 1):N
k = i + j - n;
if isValidChannel(k, N) && (k ~= i) && (k ~= j)
Mndg(idx) = Mndg(idx) + 1;
end
end
end
end
end
function tf = isValidChannel(channel_idx, N)
tf = (channel_idx >= 1) && (channel_idx <= N) && (channel_idx == round(channel_idx));
end
function plotComparison(n_values, Mndg_ana, Mdg_ana, Mndg_brute, Mdg_brute, N)
figure;
subplot(1,2,1);
stem(n_values, Mndg_ana + Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
hold on;
stem(n_values, Mdg_ana, 'filled', 'LineWidth', 1, 'Marker', 'none');
title(['Analytical (N=', num2str(N), ')']);
xlabel('Product index n');
ylabel('Number of FWM products');
legend('Total', 'Degenerate');
grid on;
subplot(1,2,2);
stem(n_values, Mndg_brute + Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'o', 'MarkerSize', 2);
hold on;
stem(n_values, Mdg_brute, 'filled', 'LineWidth', 1, 'Marker', 'none');
title(['Brute force (N=', num2str(N), ')']);
xlabel('Product index n');
ylabel('Number of FWM products');
legend('Total', 'Degenerate');
grid on;
end
function [Mndg, Mdg] = getProducts(N)
s = abs(2 - N - 1);
for n = 2 - N:2*N - 1
if n < -N
Mdg(n + s) = 0;
elseif (-N <= n) && (n <= 0)
Mdg(n + s) = N - ceil((N - n)/2);
elseif (1 <= n) && (n <= N)
Mdg(n + s) = N - 1 - floor(n/2) - ceil((N - n)/2);
elseif (N < n) && (n <= 2*N)
Mdg(n + s) = N - floor(n/2);
elseif n > 2*N
Mdg(n + s) = 0;
end
if n < -N
Mndg(n + s) = 0;
elseif (-N <= n) && (n < 1)
Mndg(n + s) = ceil((N^2 + n^2 - 2*N - 2*n + 2*N*n)/4);
elseif (1 <= n) && (n <= N)
Mndg(n + s) = ceil(((N^2 - 6*N - 2*n^2 + 2*n + 4)/4) + floor((N*n)/2));
elseif (N < n) && (n <= 2*N)
Mndg(n + s) = floor(N^2 + n^2/4 - N*n);
elseif n > 2*N
Mndg(n + s) = 0;
end
end
end

View File

@@ -0,0 +1,18 @@
function frequency = wavelength2frequency(wavelength, inputUnit)
% Convert wavelength to optical frequency.
% Supported units: m, nm.
c = physconst('LightSpeed');
switch lower(inputUnit)
case 'm'
wavelength_m = wavelength;
case 'nm'
wavelength_m = wavelength .* 1e-9;
otherwise
error('Unsupported input unit "%s". Use "m" or "nm".', inputUnit);
end
frequency = c ./ wavelength_m;
end

View File

@@ -0,0 +1,25 @@
Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
Institute for Communications Engineering (LNT)
Technical University of Munich, Germany
www.lnt.ei.tum.de
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,24 @@
## MI-CG: Numerically Computing Achievable Rates of Memoryless Channels
This repository provides a MATLAB function mi_cg.m to numerically compute achievable rates for memoryless channels. The function uses a conditionally-Gaussian (CG) channel model to obtain a lower bound on the achievable rate of the true channel. The method is well-known, and it is explained in [this short document](https://mediatum.ub.tum.de/node?id=1533663). Two example scripts that compute several achievable rate curves are also provided.
### Citation
This software and the accompanying document are meant as a tutorial to get started with mutual information as a numerical figure of merit for a communications channel. The software is provided under the open-source [MIT license](https://opensource.org/licenses/MIT). If you use the software in your academic work, please cite the accompanying [document](https://mediatum.ub.tum.de/node?id=1533663) as follows:
> F. J. Garcia-Gomez, “Numerically computing achievable rates of memoryless channels,” TUM University Library, 2019. [Online]. Available: https://mediatum.ub.tum.de/node?id=1533663
The corresponding BibTeX entry is
```
@article{garcia2019numerically,
author = "Francisco Javier Garcia-Gomez",
title = "Numerically Computing Achievable Rates of Memoryless Channels",
year = "2019",
journal="TUM University Library",
url={https://mediatum.ub.tum.de/node?id=1533663}
}
```
### Acknowledgment
This work was supported by the German Research Foundation (DFG) under Grant KR 3517/8-2.

View File

@@ -0,0 +1,156 @@
function air = air(x,r,idx_tx,Px,M_training)
MAX_MEMORY = 200e6; % maximum allowed size for a matrix
if nargin == 3
Px = [];
M_training = [];
end
if nargin == 4
M_training = [];
end
% if input is complex, separate into real and imaginary parts
if any(imag(x(:))~=0) || any(imag(r(:))~=0)
x = [real(x); imag(x)];
r = [real(r); imag(r)];
end
D = size(x, 1); % D = 2 if complex x
N = size(x, 2); % number of constellation points
M = size(r, 2); % number of samples
% set default training set size
if isempty(M_training)
M_training = ceil(0.3*M);
end
M_testing = M - M_training;
% Training: estimate parameters of the conditionally Gaussian model
% sort according to transmit index
[idx_tx_training, idx_sort] = sort(idx_tx(1:M_training));
r_training = r(:, idx_sort);
i_bounds = zeros(1, N+1);
% compute conditional means and covariance matrices
C_n = zeros(D, D, N);
det_n = zeros(1, N);
for n=1:N
% find how many times x(:, n) was transmitted and update i_bounds
N_current_x = find(idx_tx_training((i_bounds(n)+1):end)==n, 1, 'last');
if isempty(N_current_x), N_current_x=0; end
i_bounds(n+1) = i_bounds(n) + N_current_x;
if N_current_x > 0
% Compute mu_n=E[Y|X=x_n] according to Eq. (14) and store it in
% x(:, n) to save space
x(:, n) = sum(r_training(:, (i_bounds(n)+1):i_bounds(n+1)), 2)/(i_bounds(n+1)-i_bounds(n));
% compute C_n=cov[Y|X=x_n] according to Eq. (15)
r_meanfree = r_training(:, (i_bounds(n)+1):i_bounds(n+1)) - x(:, n);
C_n(:, :, n) = (r_meanfree*r_meanfree')/(i_bounds(n+1)-i_bounds(n));
% store also the determinant of C(:, :, n)
det_n(n) = det(C_n(:, :, n));
% if the determinant is 0, or if the matrix is badly conditioned,
% regularize by adding a small identity matrix. Note that we do
% need the check for 0 determinant, in case a cloud has exactly 0
% variance according to the training set
if det_n(n)==0 || cond(C_n(:, :, n))>1e16
C_n(:, :, n) = C_n(:, :, n) + 5 * eps * eye(D);
det_n(n) = (5*eps)^D;
end
end
end
% uniform input pmf Px if not provided
if isempty(Px)
Px = repmat(1/N, [1, N]);
end
% extract testing set and sort it according to transmit index
[idx_tx_testing, idx_sort] = sort(idx_tx((M_training+1):M));
r_testing = r(:, M_training+idx_sort);
% computation of h(Y|X)
h_Y_X = 0;
i_bounds_testing = zeros(1, N+1);
% loop over constellation points to compute h(Y|X)
for n = 1:N
% find how many times x(:, n) was transmitted and update
% i_bounds_testing
N_current_x = find(idx_tx_testing((i_bounds_testing(n)+1):end)==n, 1, 'last');
if isempty(N_current_x), N_current_x=0; end
i_bounds_testing(n+1) = i_bounds_testing(n) + N_current_x;
% add the corresponding contribution to the mutual information (two
% first lines of Eq. (17)). This, together with
% D/2*log2(2*pi) after the end of the loop, gives h(Y|X)
h_Y_X = h_Y_X + N_current_x * log2(det_n(n))/2+...
sum(sum(conj(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)).*(C_n(:, :, n)\(r_testing(:, (i_bounds_testing(n)+1):i_bounds_testing(n+1))-x(:, n)))))/2/log(2);
end
h_Y_X = D/2*log2(2*pi) + h_Y_X/M_testing;
% When computing log(py), we might run out of memory. If necessary, we
% doe the computation in blocks
logpy = zeros(1, M_testing);
BLOCK_SIZE = floor(MAX_MEMORY/N);
N_blocks = ceil(M_testing/BLOCK_SIZE);
% loop over blocks of symbols. This loop can be replaced by parfor to allow
% parallel computation
for i_block = 1:N_blocks
logpy_cur = zeros(1, M_testing);
% beginning of block
i_start = (i_block-1) * BLOCK_SIZE + 1;
% end of block
i_end = min(M_testing, i_block*BLOCK_SIZE);
% block size
current_block_size = i_end-i_start+1;
% compute exponents of third line of (17)
exponents = zeros(N, current_block_size);
for n = 1:N
exponents(n, :) = -log(det_n(n))/2-real(sum(conj(r_testing(:, i_start:i_end)-x(:, n)).*(C_n(:, :, n)\(r_testing(:, i_start:i_end)-x(:, n))), 1))/2;
%sum über 2 einträge von r
end
% compute third line of Eq. (17). Use a custom function
% that computes log(sum(exp(x))) avoiding overflow errors
logpy_cur(i_start:i_end) = math_logsumexp(log(Px(:))+exponents, 1);
logpy = logpy + logpy_cur;
end
% output entropy h(Y)
h_Y = D/2*log2(2*pi) - mean(logpy)/log(2);%log basis change
% compute mutual information
air = h_Y - h_Y_X;
end
function [y] = math_logsumexp(x, dim)
%[y] = math_logsumexp(x, dim)
% Computes log(sum(exp(x), dim)), avoiding overflow errors when one of the
% x is large.
if nargin<2 || isempty(dim)
m = max(x);
y = m + log(sum(exp(x-m)));
else
m = max(x, [], dim);
y = m + log(sum(exp(x-m), dim));
end
end

View File

@@ -0,0 +1,124 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two complex sequences. This file simulates a
% one-dimensional complex AWGN channel with 16-QAM constellation for
% different SNRs, and then plots the achievable rate, which is equal to two
% times the 4-PAM curve of Fig. 1 of [1].
%
% Note that using mi_cg with complex sequences assumes that the channel
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
% received clouds are circular). This is not the case in a channel with
% phase noise: see example_it_mi_cg.m for an example of how to deal with
% non-circularly-symmetric channels.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
% close all;
%%% Simulation parameters
M_QAM=16; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
X=[real(X); imag(X)]; % separate real and imaginary parts
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));%+1i*randn([1, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(1);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn = s+w;
%%%%%%%%%%%%
clf
hold on
xlim([-20, 20]);
ylim([-20, 20]);
%received signal
scatter(r_awgn(1,:),r_awgn(2,:),1,"red",'.');
%tx signal constellation
scatter(s(1,:),s(2,:),4,"black",'o','filled');
%uni power transmit constallation
scatter(X(1,:),X(2,:),5,'blue','o','filled');
drawnow
pause(0.1)
%%%%%%%%%%%%
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
I_shannon=log2(1+SNR_values);
figure(2);
hold on
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,140 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%% example_mi_cg_real_2D_awgn_vs_phasenoise %%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two sequences. This file simulates a two-dimensional
% AWGN channel with 4-PAM constellation (or, equivalently, a complex AWGN
% channel with 16-QAM constellation) for different SNRs, and then plots
% the achievable rate, reproducing the 4-PAM curve of Fig. 1 of [1]. Note
% that this curve can also be reproduced by simulating a 1-dimensional
% channel with 4-PAM: this file is an example of how to deal with multiple
% dimensions.
%
% This file also simulates a complex phase-noise channel:
% r=s.*exp(1i*theta)+w
% where w is complex AWGN and theta is i.i.d. real Gaussian. As q(Y|X) for
% this channel is not circularly-symmetric, this complex channel needs to
% be separated into two real dimensions to compute the mutual information.
% The resulting achievable rate is, as expected, below the rate for the
% AWGN channel.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% [2]
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
close all;
%%% Simulation parameters
D=1; % number of complex dimensions
M_QAM=16; % QAM size
var_w=1; % noise variance
E_theta=0.2; % phase offset for the phase noise channel
var_theta=0.05; % phase noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
X=[real(X); imag(X)]; % separate real and imaginary parts
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM^D, [1, N]);
%%% AWGN noise (real and imaginary parts)
w=sqrt(var_w/2)*randn([2*D, N]);
%%% phase noise
theta=E_theta+sqrt(var_theta)*randn([D, N]);
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
MI_phasenoise=zeros(1, n_SNR);
fig = figure(1);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn=s+w;
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx)/D;
% The following also works but is slower
% MI_awgn(i_SNR)=air(s, r_awgn)/D;
% Phase-noise channel
s_complex=s(1:2:end, :)+1i*s(2:2:end, :); % transform to complex
r_phasenoise_complex=s_complex.*exp(1i*theta); % phase noise and AWGN
r_phasenoise=zeros(2*D, N); % transform to real
r_phasenoise(1:2:end, :)=real(r_phasenoise_complex);
r_phasenoise(2:2:end, :)=imag(r_phasenoise_complex);
r_phasenoise=r_phasenoise+w; % add AWGN
clf
fig = scatter(r_phasenoise(1,:),r_phasenoise(2,:),1,'.');
xlim([-20, 20]);
ylim([-20, 20]);
drawnow
pause(0.1)
% Compute MI
MI_phasenoise(i_SNR)=air(X, r_phasenoise, idx_tx)/D;
% The following also works but is slower
% MI_phasenoise(i_SNR)=air(s, r_phasenoise)/D;
end
% Shannon capacity of the AWGN channel
I_shannon=log2(1+SNR_values);
figure;
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', '16-QAM, AWGN');
plot(SNR_dB_values, MI_phasenoise, '-.', 'DisplayName', ['16-QAM, Phase noise, \sigma_\Theta^2=' num2str(var_theta)]);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of 16-QAM in AWGN and in a phase noise channel with \theta~N(' num2str(E_theta) ', ' num2str(var_theta) ')']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,164 @@
colored_noise = true;
I_shannon=[];
for cmplx = [0,1]
cnt = 1;
for M_PAM = [4,8,16]
complex_constellation = cmplx;
%%% Simulation parameters
% M_PAM=2; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):1:35; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M=sqrt(M_PAM); % number of points per real dimension
if complex_constellation
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
else
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
end
X_ = X_ ./ rms(unique(X_));
X_=[real(X_); imag(X_)];
%%%%%%%%%%%%
figure(10);
clf
hold on
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
%%%%%%%%%%%%
%%% Uniformly choose transmit indices
idx_tx=randi(M_PAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(2);
if colored_noise
for i_SNR = 1:n_SNR
% Transmitted signal for the given indices
signal = X_(:, idx_tx);
% Generate white Gaussian noise of the same size as the signal
noise_white = randn(size(signal));
% Define the filter coefficient for colored noise (adjust as needed)
a = 0; % A higher value gives more correlation
% Filter the white noise to create colored noise.
% Here we filter each row (dimension) independently.
noise_colored = zeros(size(signal));
noise_colored(1,:) = filter(1, [1, -a], noise_white(1,:));
noise_colored(2,:) = filter(1, [1, -a], noise_white(2,:));
% Compute signal and unscaled noise power for proper scaling.
signal_power = mean(abs(signal(:)).^2);
noise_power = mean(abs(noise_colored(:)).^2);
% Convert desired SNR from dB to linear scale.
SNR_linear = 10^(SNR_dB_values(i_SNR)/10);
% Scale the colored noise so that signal_power / noise_power equals SNR_linear.
scaling_factor = sqrt(signal_power / (SNR_linear * noise_power));
noise_colored_scaled = scaling_factor * noise_colored;
% Received signal is the sum of the signal and the scaled colored noise.
r_colored = signal + noise_colored_scaled;
% For SNR measurement, compute the noise actually added.
measured_noise = r_colored - signal;
snr_meas_(i_SNR) = snr(signal(1,:) + 1i*signal(2,:), ...
measured_noise(1,:) + 1i*measured_noise(2,:));
% Plotting the transmitted and received signal
clf;
hold on;
xlim([-4, 4]);
ylim([-4, 4]);
scatter(signal(1,:), signal(2,:), 3, "black", 'o', 'DisplayName','Tx Constellation');
scatter(r_colored(1,:), r_colored(2,:), 1, "red", 'x', 'DisplayName', 'Colored Noise Mapping');
drawnow;
% Compute Mutual Information (or any other metric) with the new channel
MI_awgn_(i_SNR) = air(X_, r_colored, idx_tx);
end
else
for i_SNR=1:n_SNR
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
% r_awgn_ = s_ + w;
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
%%%%%%%%%%%%
clf
hold on
xlim([-4, 4]);
ylim([-4, 4]);
%received signal
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
drawnow
%%%%%%%%%%%%
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
end
figure(3);
hold on
if isempty(I_shannon)
I_shannon=log2(1+db2pow(snr_meas_));
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
end
cols = [ 0.9047 0.1918 0.1988
0.2941 0.5447 0.7494
0.3718 0.7176 0.3612
1.0000 0.5482 0.1000
0.8650 0.8110 0.4330
0.6859 0.4035 0.2412];
if complex_constellation
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
else
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
end
hold off;
ylim([0,8]);
xlim([min(SNR_dB_values) max(SNR_dB_values)])
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
cnt = cnt+1;
end
end

View File

@@ -0,0 +1,104 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright (c) 2019 Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
% Institute for Communications Engineering (LNT)
% Technical University of Munich, Germany
% www.lnt.ei.tum.de
%
% All rights reserved.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Permission is hereby granted, free of charge, to any person obtaining a
% copy of this software and associated documentation files (the
% "Software"), to deal in the Software without restriction, including
% without limitation the rights to use, copy, modify, merge, publish,
% distribute, sublicense, and/or sell copies of the Software, and to permit
% persons to whom the Software is furnished to do so, subject to the
% following conditions:
%
% The above copyright notice and this permission notice shall be included
% in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
% OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
% NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
% DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
% OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
% USE OR OTHER DEALINGS IN THE SOFTWARE.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% example_mi_cg_complex_16qam.m %%%%%%%%%%%%%%%%%%%%%%
%
% Example usage of the function mi_cg to numerically compute mutual
% information between two complex sequences. This file simulates a
% one-dimensional complex AWGN channel with 16-QAM constellation for
% different SNRs, and then plots the achievable rate, which is equal to two
% times the 4-PAM curve of Fig. 1 of [1].
%
% Note that using mi_cg with complex sequences assumes that the channel
% model q(Y|X) is circularly symmetric for a given X=x (i.e., that the
% received clouds are circular). This is not the case in a channel with
% phase noise: see example_it_mi_cg.m for an example of how to deal with
% non-circularly-symmetric channels.
%
% [1] G. David Forney and Gottfried Ungerboeck, "Modulation and Coding for
% Linear Gaussian Channels", IEEE Trans. Inf. Theory vol. 44, no. 6, pp.
% 2384-2415, October 1998
%
% Technische Universitaet Muenchen - Lehrstuhl fuer Nachrichtentechnik
% Date: 12.12.2019
% Author: Francisco Javier Garcia-Gomez <javier.garcia@tum.de>
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear;
close all;
%%% Simulation parameters
M_QAM=16; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):2:25; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M_PAM=sqrt(M_QAM); % number of points per real dimension
X_1d=-(M_PAM-1)+2*(0:(M_PAM-1)); % generate PAM
X=X_1d+1i*X_1d.'; % transform to QAM
X=X(:).'*sqrt(3/2/(M_QAM-1)); % set to unit power
%%% Uniformly choose transmit indices
idx_tx=randi(M_QAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w/2)*(randn([1, N])+1i*randn([1, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
for i_SNR=1:n_SNR
% transmitted points
s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
% AWGN channel
r_awgn = s+w;
% Compute MI
MI_awgn(i_SNR)=air(X, r_awgn, idx_tx);
% The following also works but is slower: MI_awgn(i_SNR)=air(s, r_awgn);
end
I_shannon=log2(1+SNR_values);
figure;
plot(SNR_dB_values, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)');
hold on;
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', [num2str(M_QAM) '-QAM, AWGN']);
hold off;
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_QAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');

View File

@@ -0,0 +1,135 @@
clear;
I_shannon=[];
for cmplx = [1,0]
cnt = 1;
for M_PAM = [2,4,8,16]
% close all;
usegarcia = 0;
complex_constellation = cmplx;
%%% Simulation parameters
% M_PAM=2; % QAM size
var_w=1; % noise variance
SNR_dB_values=(-5):1:35; % SNR values in dB
N=8000; % number of Monte-Carlo points
%%% Derived parameters
n_SNR=length(SNR_dB_values);
SNR_values=10.^(SNR_dB_values/10);
%%% Generation of QAM constellation with power 1
M=sqrt(M_PAM); % number of points per real dimension
if complex_constellation
X_ = qammod(0:M_PAM-1,M_PAM,"gray");
else
X_ = pammod(0:M_PAM-1,M_PAM,0,'gray');
end
X_ = X_ ./ rms(unique(X_));
X_=[real(X_); imag(X_)];
%%%%%%%%%%%%
figure(10);
clf
hold on
scatter(X_(1,:),X_(2,:),15,'red','x','DisplayName','Matlab');
%%%%%%%%%%%%
%%% Uniformly choose transmit indices
idx_tx=randi(M_PAM, [1, N]);
%%% AWGN noise
w=sqrt(var_w)*(randn([2, N]));
%%% Loop over the SNR values
MI_awgn=zeros(1, n_SNR);
fig = figure(2);
for i_SNR=1:n_SNR
if usegarcia
%scale transmitted points acc. to SNR condition (this is not correct I think, the papaer also show diff results)
% s=sqrt(SNR_values(i_SNR)*var_w)*X(:, idx_tx);
%scale nosie acc. to snr condition
noise_power = mean(abs(X_(1, idx_tx)+1i*X_(2, idx_tx)).^2) / SNR_values(i_SNR); % Noise power
w_ = sqrt(noise_power) .* w / sqrt(2);
% AWGN channel
r_awgn = X(:, idx_tx)+w_;
% snr_meas(i_SNR) = snr(s(1,:)+1i*s(2,:),w(1,:)+1i*w(2,:));
snr_meas(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx),w_(1,:)+1i*w_(2,:));
end
s_ = sqrt(SNR_values(i_SNR)*var_w) * X_(:, idx_tx);
% r_awgn_ = s_ + w;
if cmplx
r_awgn_ = awgn(X_(:, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(:,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx)+1i*X_(2, idx_tx) , w_awgn_matlab(1,:)+1i*w_awgn_matlab(2,:));
else
r_awgn_ = awgn(X_(1, idx_tx),SNR_dB_values(i_SNR),"measured",10);
w_awgn_matlab = r_awgn_ - X_(1,idx_tx);
snr_meas_(i_SNR) = snr(X_(1, idx_tx) , w_awgn_matlab(1,:));
end
%%%%%%%%%%%%
clf
hold on
xlim([-4, 4]);
ylim([-4, 4]);
%received signal
scatter(X_(1, idx_tx),X_(2, idx_tx),3,"black",'o','DisplayName','Tx Constellation');
if cmplx
scatter(r_awgn_(1,:),r_awgn_(2,:),1,"red",'x','DisplayName','Matlab Mapping');
else
scatter(r_awgn_,zeros(size(r_awgn_)),1,"red",'x','DisplayName','Matlab Mapping');
end
drawnow
MI_awgn_(i_SNR)=air(X_, r_awgn_, idx_tx);
% The following also works but is slower
% MI_awgn(i_SNR)=mi_cg(s, r_awgn);
end
figure(4);
hold on
if isempty(I_shannon)
I_shannon=log2(1+db2pow(snr_meas_));
plot(snr_meas_, I_shannon, '-', 'DisplayName', 'log_2 (1+SNR)','Color','black');
end
if usegarcia
plot(SNR_dB_values, MI_awgn, '--', 'DisplayName', ['GARCIA ',num2str(M_PAM) '-QAM, AWGN']);
end
cols = linspecer(6);
if complex_constellation
plot(snr_meas_, MI_awgn_, ':', 'DisplayName', ['',num2str(M_PAM) '-QAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
else
plot(snr_meas_, MI_awgn_, '-', 'DisplayName', ['',num2str(M_PAM) '-PAM, AWGN'],'LineWidth',1,'Color',cols(cnt,:));
end
hold off;
ylim([0,8]);
xlim([min(SNR_dB_values) max(SNR_dB_values)])
xlabel('SNR (dB)'); ylabel('Achievable rate (bits/complex dimension)');
title(['Achievable rate of ' num2str(M_PAM) '-QAM in AWGN']);
legend('Location', 'NorthWest');
yline(log2(M_PAM),'LineStyle',':','HandleVisibility','off','Color','black');
autoArrangeFigures;
cnt = cnt+1;
end
end