function[shanonCapacity powerAllocated] = ofdmwaterfilling(nSubChannel,totalPower,channelStateInformation,bandwidth,noiseDensity);
%为了使频率选择性信道的容量最大化,注水算法被使用,OFDM调制把总带宽分配成了
%n个子信道,如果正确的循环前缀被添加到每个OFDM模型的末端,那么大部分的子信道
%都能让其经历平衰落。注水算法就实现了把更多的功率分配给有好状态的信道,不给信道状态不好的(有深度衰落)的信道分配功率。
%参数设置
nSubChannel = 16;
totalPower = 1e-5;
channelStateInformation = random('rayleigh',1/0.6552,1,nSubChannel); %瑞利分布是一个均值为0,方差为σ^2的平稳窄带高斯过程
bandwidth = 1e6;
noiseDensity = 1e-11; %噪声密度
subchannelNoise=noiseDensity*bandwidth/nSubChannel;
carrierToNoiseRatio =channelStateInformation.^2/subchannelNoise;
initPowerAllo=(totalPower + sum(1./carrierToNoiseRatio))/nSubChannel-1./carrierToNoiseRatio;
%在这个阶段,公式一的最优化结果就会导致一些子信道被分配了少功率,
%在接下来的阶段,这些信道会被消除,然后继续这种算法,把多余的功率分
%配给其他信道。
while(length(find(initPowerAllo < 0 )) > 0 )
negIndex = initPowerAllo <= 0;
posIndex = find(initPowerAllo > 0);
nSubchannelRem = length(posIndex);
initPowerAllo(negIndex) = 0;
CnrRem = carrierToNoiseRatio(posIndex);
powerAlloTemp = (totalPower + sum(1./CnrRem))/nSubchannelRem - 1./CnrRem;
initPowerAllo(posIndex) = powerAlloTemp;
end
%计算信道容量
powerAllocated = initPowerAllo';
shanonCapacity = bandwidth/nSubChannel*sum(log2(1 + initPowerAllo.*carrierToNoiseRatio));
%绘直方图
f1 = figure(1);
clf;
set(f1,'Color',[1 1 1]);
bar((initPowerAllo +1./carrierToNoiseRatio),1,'r')
hold on;
bar(1./carrierToNoiseRatio,1);
xlabel('subchannel indices');
title('Water filling algorithm')
legend('amount of power allocated to each subchannel', 'Noise to Carrier Ratio')
下面我们举一个实例来应用此算法,首先我们要知道注水算法的初衷:保留正数,负数置零。
下面是主程序:
N=16;
H=100;
L=2000;
ro=80;
p=linspace(100000,100000,N);
q=linspace(100000,100000,N);
x=linspace(0,2000,N);
y=linspace(500,500,N);
rsr=ro./(H^2+x.^2+y.^2);
rrd=ro./(H^2+(L-x).^2+y.^2);
la=linspace(1/16,1/16,N);
u=linspace(0.0001,0.0001,N);
for t=1:1:1000
b=linspace(0,0,N);
for n=1:1:N-1
for i=n+1:1:N
b(n)=b(n)+la(i);
end
end
v=linspace(0,0,N);
for n=2:1:N
for i=n:1:N
v(n)=1-(v(n)+la(i));
end
end
[Ps]=WF1(p,b,rsr);
[Pr]=WF1(q,v,rrd);
[Rr]=WF3(q,v,rrd);
la=la-u.*(sum(log2(1+Ps.*rsr))-sum(Rr));
disp(la)
end
下面是注水子程序:
function[Ps]=WF1(p,b,rsr)
Ps=p.*b-1./(rsr);
while(~isempty(find(Ps<0, 1)))
IndexN= Ps<=0;
IndexP= Ps>0;
Ps(IndexN)=0;
pT=p(IndexP);
bT=b(IndexP);
rsnT=rsr(IndexP);
PsT=pT.*bT-1./(rsnT);
Ps(IndexP)=PsT;
end
end
function[Pr]=WF2(q,v,rrd)
Pr=q.*v-1./(rrd);
while(~isempty(find(Pr<0, 1)))
IndexN= Pr<=0;
IndexP= Pr>0;
Pr(IndexN)=0;
qT=q(IndexP);
vT=v(IndexP);
rrdT=rsn(IndexP);
PrT=qT.*vT-1./(rrdT);
Pr(IndexP)=PrT;
end
function[Rr]=WF3(q,v,rrd)
Rr=log2(q.*v.*rrd);
while(~isempty(find(Rr<0, 1)))
IndexN= Rr<=0;
IndexP= Rr>0;
Rr(IndexN)=0;
qT=q(IndexP);
vT=v(IndexP);
rrdT=rrd(IndexP);
RrT=log2(qT.*vT.*rrdT);
Rr(IndexP)=RrT;
end
end