国赛第四次培训总结
这题是一个光伏角的优化问题, 模型问题不再赘述, 我是负责算法部分, 所以在这里重述一下算法的思路.
题目
太阳能是一种清洁能源,它的应用正在世界范围内快速地增长。目前建设一个太阳能发电系统成本较高,从我国现阶段的太阳能发电成本来看,其花费在太阳电池组件的费用大约为60%左右。为了更好地利用太阳能电池板发电,从安装的角度来看,也有可以挖掘的潜力。
涉及到的几何参数
- 太阳能电池板的倾角(Module tilt):太阳能电池板平面与水平面的夹角
- 太阳能电池板的方位角(Module azimuth):此角度为太阳能电池板的法线在水平面上的投影与正南方向的夹角。并按如下方法规定角度:如果一个太阳能电池板朝向正南,那么它的方位角为零度; 如果一个太阳能电池板朝向正东,那么它的方位角为-90度; 如果一个太阳能电池板朝向正西,那么它的方位角为+90度。
- 太阳高度角:对于地球表面上的某个点,太阳高度角是指太阳光的入射方向和地平面之间的夹角。
- 太阳方位角:在地球表面某点,建立以球面外法线方向为z轴正方向,以向东方向为x轴,向北方向为y轴的坐标系。太阳在这个坐标系中,北偏东的角度为方位角。
- 经度、纬度、海拔高度
latitude: in degrees, north of equator is positive
longitude :in degrees, positive for east of Greenwich
altitude: in meters ,above mean sea level
具体背景
一般情况下,电池板朝向正南(即=0°)时,太阳电池发电量最大。在偏离正南(北半球)30°度时,发电量将减少约10%~15%;在偏离正南(北半球)60°时,发电量将减少约20%~30%。但是,在晴朗的夏天,太阳辐射能量的最大时刻是在中午稍后,因此电池板方阵的方位稍微向西偏一些时,在午后时刻可获得最大的发电功率。 一年中的最佳倾角与当地的地理纬度有关,当纬度较高时,相应的倾角也大。因此,为了更加有效地利用太阳能,铺设安装时,选取太阳电池板的方位角与倾角是一个十分重要的问题。
太阳能电池板平面所能获得的太阳光强与倾角和方位角等参数有关,直接影响电池板的产能。现有一实际工况,见如下俯视图(图1),其中标示数据为几何尺寸 (长度、高度【单位:米】和角度(单位:度))
一般实际工况中,太阳能电池板是以一定倾角和方位角安装在屋顶上,前排电池板不可避免的会对后排电池板造成遮蔽【注:如果太阳电池不能被日光直接照射,那么只有散射光用来发电,此时的发电量比无阴影的要减少约10%~20%】,因此,在太阳能电池板大小一定的情况下,为了尽可能多的获得太阳的照射而增加产能,安装之前,有必要根据房屋的情况对太阳能电池板的安装间距D、倾角和方位角等参数进行设计。请解决如下问题【注:对于需要使用,而未给定的参数,可以按实际情况,自行合理设定; 参数具体含义可以查阅文献】
(1) 请以屋顶的几何参数和太阳能电池板各几何参数【,因为可以拼接,其中可以任意】,并假设太阳高度角和太阳方位角。以此时刻点参数的具体值,请设计安装间距D、倾角和方位角等参数,使之获得最大瞬时光照面积。
(2) 太阳的高度角随时间和空间变化,如果以某一天为例,以武汉某地【longitude = 114.3556,latitude =30.5286,altitude = 183m】为对象,设计安装间距D、倾角和方位角等参数,使获得最大日产能【附件数据文件data1给出如下系列数据:时间点,高度角和方位角等离散数据】。
(3) 如果在一个月的时间里考虑,设计安装间距D、倾角和方位角等参数,使获得最大月产能【附件数据文件data2: 年、 月、 日、时、分、高度角和方位角等离散数据】。
(4) 如果将散射光也考虑在内,对问题(3)进行讨论。
为了方便工程施工人员铺设安装太阳能电池板,请设计一个应用程序(图形用户界面),为在任一地点铺设安装提供参数支持(此时可以使用附件中提供的MATLAB程序:sun_position.m)。
第一题是个固定解, 不再赘述,
第二题
由于所给的数据中太阳的方向角与高度角均为离散的值, 因此在求解该模型时无法直接给出解析的解, 因此选用数值解法. 而本题由于数据量较大, 所以采用遗传算法与粒子群算法相结合的方法搜索最优解.利用遗传算法各染色体互相共享信息的特点,使得整个种群逼近parato前沿.利用粒子群算法粒子会记忆保存邻域内最好解的特点, 使种群加快收敛.
GA_PSO算法步骤也不赘述了, 程序如下
clear
lenchrom=2; %字符串长度(个体长度),染色体编码长度
pc=0.7; %设置交叉概率,本例中交叉概率是定值,若想设置变化的交叉概率可用表达式表示,或从写一个交叉概率函数,例如用神经网络训练得到的值作为交叉概率
pm=0.3; %设置变异概率,同理也可设置为变化的
h = waitbar(0, 'couting...');
data = xlsread('/Users/xuguodong/Desktop/4/4/data1.xlsx');
tilt = 5.71;
height = 1.8;
%粒子群算法中的两个参数
c1 = 0.5;
c2 = 0.5;
maxgen=80; % 进化次数
popsize=50; %种群规模
%粒子更新速度
Vmax=1;
Vmin=-1;
% 变量取值范围
bound=[2 60;0 80]; %变量范围
% 优化粒子数目
par_num=2;
%% 产生初始粒子和速度
for i=1:popsize
%随机产生一个种群
pop(i,1)=bound(1,1)+rand*(bound(1,2)-bound(1,1));%初始种群
pop(i,2)= 80 .* rand;
V(i,:)=rand(1,par_num); %初始化速度
%计算适应度
fitness(i)=fun(pop(i,:), data, tilt); %染色体的适应度
end
%找最好的染色体
[bestfitness bestindex]=min(fitness);
zbest=pop(bestindex,:); %全局最佳
gbest=pop; %个体最佳
fitnessgbest=fitness; %个体最佳适应度值
fitnesszbest=bestfitness; %全局最佳适应度值
%% 迭代寻优
for i=1:maxgen
for j=1:popsize
%速度更新 PSO选择更新
V(j,:) = V(j,:) + c1*rand*(gbest(j,:) - pop(j,:)) + c2*rand*(zbest - pop(j,:));
V(j,find(V(j,:)>Vmax))=Vmax;
V(j,find(V(j,:)<Vmin))=Vmin;
%种群更新 PSO选择更新
pop(j,:)=pop(j,:)+0.5*V(j,:);
pop(j,find(pop(j,1)>80))=80;
pop(j,find(pop(j,1)<0))=0;
pop(j,find(pop(j,2)>20))=20;
pop(j,find(pop(j,2)<0))=0;
GApop=Cross(pc,lenchrom,pop,popsize,bound);
% 变异操作 GA变异
GApop=Mutation(pm,lenchrom,GApop,popsize,[i maxgen],bound);
pop=GApop; % GA pop --> PSO pop
fitness(j)=fun(pop(j,:),data,tilt);
%个体最优更新
if fitness(j) < fitnessgbest(j)
gbest(j,:) = pop(j,:);
fitnessgbest(j) = fitness(j);
end
%群体最优更新
if fitness(j) < fitnesszbest
zbest = pop(j,:);
fitnesszbest = fitness(j);
end
end
yy(i)=fitnesszbest;
waitbar(i/maxgen);
end
%% 结果
disp '*************result****************'
betaj = zbest(1)
rj = zbest(2)-40
a = mean(data(:,1));
D = height*sin((a+betaj)*pi/180)/sin((a+betaj+tilt)*pi/180)
close(h);
plot(yy,'linewidth',2);
grid on
title(['适应度曲线 ' '终止代数=' num2str(maxgen)]);
xlabel('进化代数');ylabel('适应度');
其中子函数包括fun.m, Cross.m, Mutation.m,
test.m,
fun.m如下
function y = fun(x,data,tilt)
if(size(data,2) > 4)
A1 = data(:,7);
alpha = data(:,6);
y = 0;
for i=1:size(A1,1)
y=y+alpha(i,1)*sin((alpha(i,1)+x(1)+tilt)*2*pi/360)*cos((A1(i,1)+140+x(2))*2*pi/360);
end
y = -y;
elseif size(data,2) == 3
A1 = data(:,3);
alpha = data(:,2);
y = 0;
for i=1:size(A1,1)
y=y+alpha(i,1)*sin((alpha(i,1)+x(1)+tilt)*2*pi/360)*cos((A1(i,1)+140+x(2))*2*pi/360);
end
y = -y;
else
A1 = data(:,2);
alpha = data(:,1);
y = 0;
for i=1:size(A1,1)
y=y+alpha(i,1)*sin((alpha(i,1)+x(1)+tilt)*2*pi/360)*cos((A1(i,1)+140+x(2))*2*pi/360)+0.4*alpha(i,1)*(1+cos((x(1)+tilt)*2*pi/360))/2+0.2*alpha(i,1)*(1-cos((x(1)+tilt)*2*pi/360))/2;
end
y = -y;
end
end
Cross.m如下
function ret=Cross(pcross,lenchrom,chrom,sizepop,bound)
%本函数完成交叉操作
% pcorss input : 交叉概率
% lenchrom input : 染色体的长度
% chrom input : 染色体群
% sizepop input : 种群规模
% ret output : 交叉后的染色体
for i=1:sizepop
% 随机选择两个染色体进行交叉
pick=rand(1,2);
while prod(pick)==0
pick=rand(1,2);
end
index=ceil(pick.*sizepop);
% 交叉概率决定是否进行交叉
pick=rand;
while pick==0
pick=rand;
end
if pick>pcross
continue;
end
flag=0;
while flag==0
% 随机选择交叉位置
pick=rand;
while pick==0
pick=rand;
end
pos=ceil(pick.*sum(lenchrom)); %随机选择进行交叉的位置,即选择第几个变量进行交叉,注意:两个染色体交叉的位置相同
pick=rand; %交叉开始
v1=chrom(index(1),pos);
v2=chrom(index(2),pos);
chrom(index(1),pos)=pick*v2+(1-pick)*v1;
chrom(index(2),pos)=pick*v1+(1-pick)*v2; %交叉结束
flag1=test(lenchrom,bound,chrom(index(1),:)); %检验染色体1的可行性
flag2=test(lenchrom,bound,chrom(index(2),:)); %检验染色体2的可行性
if flag1*flag2==0
flag=0;
else flag=1;
end %如果两个染色体不是都可行,则重新交叉
end
end
ret=chrom;
Mutation.m如下
function ret=Mutation(pmutation,lenchrom,chrom,sizepop,pop,bound)
% 本函数完成变异操作
% pcorss input : 变异概率
% lenchrom input : 染色体长度
% chrom input : 染色体群
% sizepop input : 种群规模
% pop input : 当前种群的进化代数和最大的进化代数信息
% ret output : 变异后的染色体
for i=1:sizepop
% 随机选择一个染色体进行变异
pick=rand;
while pick==0
pick=rand;
end
index=ceil(pick*sizepop);
% 变异概率决定该轮循环是否进行变异
pick=rand;
if pick>pmutation
continue;
end
flag=0;
while flag==0
% 变异位置
pick=rand;
while pick==0
pick=rand;
end
pos=ceil(pick*sum(lenchrom)); %随机选择了染色体变异的位置,即选择了第pos个变量进行变异
v=chrom(i,pos);
v1=v-bound(pos,1);
v2=bound(pos,2)-v;
pick=rand; %变异开始
if pick>0.5
delta=v2*(1-pick^((1-pop(1)/pop(2))^2));
chrom(i,pos)=v+delta;
else
delta=v1*(1-pick^((1-pop(1)/pop(2))^2));
chrom(i,pos)=v-delta;
end %变异结束
flag=test(lenchrom,bound,chrom(i,:)); %检验染色体的可行性
end
end
ret=chrom;
test.m如下
function flag=test(lenchrom,bound,code)
% lenchrom input : 染色体长度
% bound input : 变量的取值范围
% code output: 染色体的编码值
flag=1;
[n,m]=size(code);
for i=1:n
if code(i)<bound(i,1) || code(i)>bound(i,2)
flag=0;
end
end
第三题
题目要求如果在一个月的时间里考虑, 设计安装间距D、倾角和方位角等参数,使获得最大月产能, 其模型与第二题一致, 不同的是数据的不同, 为3255组一个月内不同的时间点的太阳方向角及高度角数据, 因此求解过程也与第二问类似, 仍然选用第二题的GA-PSO算法对第三题进行求解. 算法的迭代次数为100次, 种群规模pop-size为50, 交叉概率pc为0.7, 变异概率pm为0.3, 程序的迭代过程如下图所示
所得结果为 倾角19.0518度(百分制单位), 方向角1.2331度, 间距1.6824米.
代码如下
clear
lenchrom=2; %字符串长度(个体长度),染色体编码长度
pc=0.7; %设置交叉概率,本例中交叉概率是定值,若想设置变化的交叉概率可用表达式表示,或从写一个交叉概率函数,例如用神经网络训练得到的值作为交叉概率
pm=0.3; %设置变异概率,同理也可设置为变化的
data = xlsread('/Users/xuguodong/Desktop/4/4/data2.xlsx');
tilt = 5.71;
height = 1.8;
%粒子群算法中的两个参数
c1 = 0.5;
c2 = 0.5;
maxgen=80; % 进化次数
popsize=50; %种群规模
%粒子更新速度
Vmax=1;
Vmin=-1;
% 变量取值范围
bound=[2 60;0 80]; %变量范围
% 优化粒子数目
par_num=2;
h = waitbar(0, 'couting...');
%% 产生初始粒子和速度
for i=1:popsize
%随机产生一个种群
pop(i,1)=bound(1,1)+rand*(bound(1,2)-bound(1,1));%初始种群
pop(i,2)= 80 .* rand;
V(i,:)=rand(1,par_num); %初始化速度
%计算适应度
fitness(i)=fun(pop(i,:), data, tilt); %染色体的适应度
end
%找最好的染色体
[bestfitness bestindex]=min(fitness);
zbest=pop(bestindex,:); %全局最佳
gbest=pop; %个体最佳
fitnessgbest=fitness; %个体最佳适应度值
fitnesszbest=bestfitness; %全局最佳适应度值
%% 迭代寻优
for i=1:maxgen
for j=1:popsize
%速度更新 PSO选择更新
V(j,:) = V(j,:) + c1*rand*(gbest(j,:) - pop(j,:)) + c2*rand*(zbest - pop(j,:));
V(j,find(V(j,:)>Vmax))=Vmax;
V(j,find(V(j,:)<Vmin))=Vmin;
%种群更新 PSO选择更新
pop(j,:)=pop(j,:)+0.5*V(j,:);
pop(j,find(pop(j,1)>80))=80;
pop(j,find(pop(j,1)<0))=0;
pop(j,find(pop(j,2)>20))=20;
pop(j,find(pop(j,2)<0))=0;
GApop=Cross(pc,lenchrom,pop,popsize,bound);
% 变异操作 GA变异
GApop=Mutation(pm,lenchrom,GApop,popsize,[i maxgen],bound);
pop=GApop; % GA pop --> PSO pop
fitness(j)=fun(pop(j,:),data,tilt);
%个体最优更新
if fitness(j) < fitnessgbest(j)
gbest(j,:) = pop(j,:);
fitnessgbest(j) = fitness(j);
end
%群体最优更新
if fitness(j) < fitnesszbest
zbest = pop(j,:);
fitnesszbest = fitness(j);
end
end
yy(i)=fitnesszbest;
waitbar(i/maxgen);
end
%% 结果
disp '*************result****************'
betaj = zbest(1)
rj = zbest(2)-40
a = mean(data(:,1));
close(h);
D = height*sin((a+betaj)*pi/180)/sin((a+betaj+tilt)*pi/180)
%%
plot(yy,'linewidth',2);
grid on
title(['适应度曲线 ' '终止代数=' num2str(maxgen)]);
xlabel('进化代数');ylabel('适应度');
第四题
改变的是目标函数的值, 只改变了fun.m, 代码不再贴了, 主要的改变的由于需要做出程序的GUI, 此时优化模型就更加宽泛了. 所以在这里使用了sun_position函数来对输入的经纬度与海拔计算该地2017年一整年的数据, 具体为以分钟为单位的518400组太阳高度角与方向角数据, 并利用该数据为基础结合第四问的模型以及GA-PSO算法来为该
住房进行优化计算.
GUI设计
利用matlab设计的程序gui如下图所示
使用过程如下步骤
- 输入优化所需的参数.
- 点击开始优化就开始优化了.
- 优化结果如下图所示
可以看到优化的最终结果为间距D为1.6724米, 方向角p为38.5359度, 倾角a 为22.9018度
GUI代码
gui的代码由于太冗长, 就不贴上来了, 这里只把GUI的按钮call_back上传, 是程序的核心控制部分, 不得不得说matlab的GUIDE确实好用..
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
location.longitude = str2num(get(handles.edit1,'String'));
location.latitude = str2num(get(handles.edit2,'String'));
location.altitude = str2num(get(handles.edit3,'String'));
toward = str2num(get(handles.edit9,'String'));
tilt = str2num(get(handles.edit6,'String'));
height= str2num(get(handles.edit7,'String'));
[beta, r, D] = loc_pso(location,tilt,height,toward);
set(handles.edit4,'String',num2str(beta));
set(handles.edit5,'String',num2str(r));
set(handles.edit8,'String',num2str(D));
guidata(hObject, handles);
按钮处的代码如上
核心函数loc_pso
具体的, 其中的loc_pso是封装好的核心求解优化函数, 其代码如下.
function [betaj,rj,D] = loc_pso(location,tilt,height, toward)
lenchrom=2; %字符串长度(个体长度),染色体编码长度
pc=0.7; %设置交叉概率,本例中交叉概率是定值,若想设置变化的交叉概率可用表达式表示,或从写一个交叉概率函数,例如用神经网络训练得到的值作为交叉概率
pm=0.3; %设置变异概率,同理也可设置为变化的
nyears = 1;
time.sec = 30;
time.UTC = -7;
i = 1;
h = waitbar(0, 'counting...');
for timeyear = 1:nyears
for timemonth = 1:12,
for timeday = 1:30,
for timehour = 1:24,
for timemin = 1:60,
time.year = timeyear+2016;
time.month = timemonth;
time.day = timeday;
time.hour = timehour;
time.min = timemin;
sun = sun_position(time, location);
data(i,1) = 90-sun.zenith;
data(i,2) = sun.azimuth;
i = i+1;
end
end
end
timemonth
end
waitbar(timeyear/103);
end
size(data)
%粒子群算法中的两个参数
c1 = 0.5;
c2 = 0.5;
maxgen=100; % 进化次数
popsize=50; %种群规模
%粒子更新速度
Vmax=1;
Vmin=-1;
% 变量取值范围
bound=[5 80;0 80]; %变量范围
% 优化粒子数目
par_num=2;
%% 产生初始粒子和速度
for i=1:popsize
%随机产生一个种群
pop(i,1)=bound(1,1)+rand*(bound(1,2)-bound(1,1));%初始种群
pop(i,2)= 80 .* rand;
V(i,:)=rand(1,par_num); %初始化速度
%计算适应度
fitness(i)=fun(pop(i,:), data, tilt); %染色体的适应度
end
%找最好的染色体
[bestfitness bestindex]=min(fitness);
zbest=pop(bestindex,:); %全局最佳
gbest=pop; %个体最佳
fitnessgbest=fitness; %个体最佳适应度值
fitnesszbest=bestfitness;%全局最佳适应度值
%% 迭代寻优
for i=1:maxgen
for j=1:popsize
%速度更新 PSO选择更新
V(j,:) = V(j,:) + c1*rand*(gbest(j,:) - pop(j,:)) + c2*rand*(zbest - pop(j,:));
V(j,find(V(j,:)>Vmax))=Vmax;
V(j,find(V(j,:)<Vmin))=Vmin;
%种群更新 PSO选择更新
pop(j,:)=pop(j,:)+0.5*V(j,:);
pop(j,find(pop(j,1)>80))=80;
pop(j,find(pop(j,1)<0))=0;
pop(j,find(pop(j,2)>20))=20;
pop(j,find(pop(j,2)<0))=0;
GApop=Cross(pc,lenchrom,pop,popsize,bound);
% 变异操作 GA变异
GApop=Mutation(pm,lenchrom,GApop,popsize,[i maxgen],bound);
pop=GApop; % GA pop --> PSO pop
fitness(j)=fun(pop(j,:), data, tilt);
%个体最优更新
if fitness(j) < fitnessgbest(j)
gbest(j,:) = pop(j,:);
fitnessgbest(j) = fitness(j);
end
%群体最优更新
if fitness(j) < fitnesszbest
zbest = pop(j,:);
fitnesszbest = fitness(j);
end
end
yy(i)=fitnesszbest;
waitbar((3+i)/(maxgen+3));
end
%% 结果
betaj = zbest(1);
rj = zbest(2)-40;
a = mean(data(:,1));
D = height*sin((a+betaj)*pi/180)/sin((a+betaj+tilt)*pi/180);
close(h);
end