最优化理论的经典算法
模拟退火法、神经网络、遗传算法是数学建模中常用的启发式算法,这里整合一下模版,并进行一些拓展,方便直接使用
原文:http://blog.csdn.net/qq_34861102/article/details/77806124
一些拓展:
基于模拟退火的遗传算法:
http://blog.csdn.net/qq_34861102/article/details/77899555
模拟退火法
- 伪代码
/* * J(y):在状态y时的评价函数值 * Y(i):表示当前状态 * Y(i+1):表示新的状态 * r: 用于控制降温的快慢 * T: 系统的温度,系统初始应该要处于一个高温的状态 * T_min :温度的下限,若温度T达到T_min,则停止搜索 */
while( T > T_min )
{dE = J( Y(i+1) ) - J( Y(i) ) ; if ( dE >=0 ) //表达移动后得到更优解,则总是接受移动Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动else{
// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也if ( exp( dE/T ) > random( 0 , 1 ) )Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动}T = r * T ; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快/** 若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值*/i ++ ;
}
实际例子
求解下列非线性规划最优解
min f(x) = x(1)^2 + x(2)^2 + 8;s.t.x(1)^2 - x(2) >= 0;-x(1) - x(2)^2 + 2 = 0;x(1),x(2) >=0
实现代码
%生成初始解 x2=1; x1=2-x2^2; tempx1 = x1; bestx1 = x1; tempx2 = x2; bestx2 = x2; tempans = inf; bestans = inf; figure rand('state',sum(clock)); %初始化随机数发生器 t=90; %初始温度 tf=89.9; %结束温度 a = 0.99; %温度下降比例 while t>=tf%(7)结束条件 for r=1:1000 %退火次数 %产生随机扰动(3)新解的产生 x2=x2+rand*0.2; x1=2-x2^2; %检查是否满足约束 if x1^2-x2>=0 && -x1-x2^2+2==0 && x1>=0 &&x2>=0 else x2=rand*2; x1=2-x2^2; continue; end %退火过程 E_new=x1^2+x2^2+8;%(2)目标函数 if E_new<tempans%(5)接受准则 tempans=E_new; tempx1=x1; tempx2=x2; if E_new<bestans %把冷却过程中最好的解保存下来 bestans=E_new; bestx1=x1; bestx2=x2; end else if rand<exp(-(E_new-tempans)/t)%(4)代价函数差 tempans=E_new; tempx1=x1; tempx2=x2; else x2=tempx2; x1=tempx1; end end plot(r,bestans,'.') hold on end t=t*a;%(6)降温 end disp('最优解为:') disp(bestx1) disp(bestx1) disp('目标表达式的最小值等于:') disp(bestans)
神经网络
这里就介绍一下常用的神经网络
BP网络
%输入变量P和目标变量T P = -1:0.1:1; T = [-0.9602 -0.5770 -0.0729 0.3771 0.6405 0.6600 0.4609 0.1336 -0.2013 -0.4344 -0.5000 -0.3930 -0.1647 0.0988 0.3072 0.3960 0.3449 0.1816 -0.0312 -0.2189 -0.3201]; %网络设计 s = 3:8; res = 1:6; for i = 1:6; %net = newff(minmax(P),[s(i),1],{ 'tansig','logsig'},'traingdx'); net = newff(P,T,s(i),{ 'tansig','logsig'},'traingdx'); net.trainParam.epochs = 2000; net.trainParam.goal = 0.001; net = train(net,P,T); y = sim(net,P); error = y - T; %向量每个元素分别平方后求和再开方 res(i) = norm(error) end %这是一个选择最佳隐层神经元个数的方法 %自己选择不同的训练算法 %输入变量P和目标变量T P = -1:0.1:1; T = [-0.9602 -0.5770 -0.0729 0.3771 0.6405 0.6600 0.4609 0.1336 -0.2013 -0.4344 -0.5000 -0.3930 -0.1647 0.0988 0.3072 0.3960 0.3449 0.1816 -0.0312 -0.2189 -0.3201]; net = newff(P,T,8,{ 'tansig','logsig'},'traingdx'); net.trainParam.epochs = 2000; net.trainParam.goal = 0.001; net = train(net,P,T); y = sim(net,P); plot(P,T,'r+'); hold on plot(P,y,'.'); plot(1:21,y-T); %三个图像分开验证
感知器网络
单层感知器网络
%样本输入向量 lP=[-0.4 -0.6 0.7; 0.8 0 0.1]; %目标向量 T=[1 1 0]; %新建一个感知器网络 %newp -- 第一个参数是R组输入向量的最大值和最小值组成 第二个参数是神经元的个数 第三个参数可选,传递函数 第四个参数可选,学习函数 net=newp([-1 1;-1 1],1); %返回画线的句柄,下一次绘制分类线时将旧的删除 handle=plotpc(net.iw{ 1},net.b{ 1}); %设置训练次数最大为200 net.trainParam.epochs = 200; net=train(net,lP,T); %给定的输入向量 Q=[0.6 0.9 -0.1; -0.1 -0.5 0.5]; %网络仿真函数 Y=sim(net,Q); %控制窗口的数量 figure; %绘制分类线 plotpv(Q,Y); handle=plotpc(net.iw{ 1},net.b{ 1},handle) grid
多层感知器网络
net = network %网络的结构属性%定义了网络的输入向量数,设置为自然数,不是输入层的神经元的个数,是输入源的数目 net.numInputs = 1; %定义了网络的层数 net.numLayers = 2; %定义各个网络层是否具有阈值向量,其值为Nl*1布尔型向量(0或1),Nl为网络层数(net.Layers)。 %可以通过访问net.biasConnect{i}的值,查看第i个网络层是否具有阈值向量 net.biasConnect = [1;1]; %定义各网络层是否具有来自个输入向量的连接权,其值为Nl*Ni布尔型向量(0或1),Nl为网络层数(net.numLayers),Ni为网络输入向量数(net.numInputs)。 %可以通过访问net.inputConnect(i,j)的值,来查看第i个网络是否具有来自第j个输入向量的连接权 net.inputConnect = [1;0]; %定义一个网络层是否具有来自另外一个网络层的连接权,其值为Nl*Nl的布尔型向量(0或1),Nl为网络层数(net.numLayers)。 %可以通过访问net.layerConnect(i,j)的值,来查看第i个网络层是否具有来自第j个网络层的连接权。 net.layerConnect = [0 0;1 0]; %定义各网络层是否作为输出层,其值为1*Nl的布尔型向量(0或1),Nl为网络层数(net.numLayers)。 %可以通过访问net.outputConnect(i)的值来查看第i个网络层是否作为输出层。 net.outputConnect = [0 1];%各层的属性 net.inputs{ 1}.range = [0 1;0 1]; net.layers{ 1}.size = 2; net.layers{ 1}.transferFcn = 'hardlim'; net.layers{ 1}.initFcn = 'initnw';net.layers{ 2}.size = 1; net.layers{ 2}.transferFcn = 'hardlim'; net.layers{ 2}.initFcn = 'initnw';%网络的整体属性 net.adaptFcn = 'adaptwb'; net.performFcn = 'mse'; net.trainFcn= 'trainlm'; net.initFcn = 'initlay';%对网络进行初始化 net = init(net); %设置训练样本P和T P = [0 0;0 1;1 0;1 1]'; T = [0 1 1 0]; net.trainParam.epochs = 500; net = train(net,P,T);y = sim(net,P)
线性神经网络
P = [1 1.5 3.0 -1.2]; T = [0.5 1.1 3.0 -1.0]; plot(P,T,'+'); axis([-1.5 3.5 -1.5 3.5]); xlabel('training vector P'); ylabel('target vaector T'); %创建网络并开始训练 net = newlin(minmax(P),1,0,0.01); net = init(net); net.trainParam.epochs = 500; net.trainParam.goal = 0.0001; net = train(net,P,T); y = sim(net,P); plot(P,y); hold on plot(P,T,'r+');%很好逼近了P和T的线性关系
遗传算法
以上面模拟退火中非线性规划最优解的模型为例
主函数
clear firstbestfit = 0; popsize=20; %群体大小 chromlength=1; %字符串长度(个体长度) pc = 0.6; %交叉概率 pm = 0.001; %变异概率 pop = initpop(popsize,chromlength); %随机产生初始群体 for i=1:20000 %20000为迭代次数[objvalue] = calobjvalue(pop); %计算目标函数fitvalue = calfitvalue(objvalue); %计算群体中每个个体的适应度[newpop] = selection(pop,fitvalue); %复制[newpop] = crossover(newpop,pc); %交叉[newpop] = mutation(newpop,pm); %变异 pop = newpop; [bestindividual,bestfit]=best(pop,fitvalue); %求出群体中适应度值最大的个体及其适应值%保留最好的个体if bestfit > firstbestfitfirstbestfit = bestfit;aa = bestindividual;zz = 1/bestfit + 8;end end
initpop
初始函数对于初始化而言,尽量要选择解质量较好的初始化群体
function pop=initpop(popsize,chromlength) pop = zeros(popsize,chromlength+1); for i = 1:popsizepop(i,1) = rand;pop(i,2) = 2-pop(i,1)^2; end end
calobjvalue
计算目标函数根据自己实际例子中定义目标函数
function [objvalue]=calobjvalue(pop) objvalue = zeros(size(pop,1),1); for i = 1:size(pop,1)x1 = pop(i,2);x2 = pop(i,1); if x1^2-x2>=0 && -x1-x2^2+2==0 && x1>=0 &&x2>=0objvalue(i) = x1^2+x2^2+8;elseobjvalue(i) = 1000; end end
calfitvalue
计算群体中每个个体的适应度对于目标函数可能在不同情况之下和适应度的关系存在其余如反比例的关系
function fitvalue=calfitvalue(objvalue) fitvalue = zeros(size(objvalue,1),1); for i = 1:size(objvalue,1)fitvalue(i) = 1/(objvalue(i)-8); end end
selection
复制过程染色体复制的过程
function [newpop]=selection(pop,fitvalue) totalfit=sum(fitvalue); %求适应值之和 fitvalue=fitvalue/totalfit; %单个个体被选择的概率 fitvalue=cumsum(fitvalue); %如 fitvalue=[1 2 3 4],则 cumsum(fitvalue)=[1 3 6 10] [px,py]=size(pop); ms=sort(rand(px,1)); %从小到大排列 fitin=1; newin=1; while newin<=px if(ms(newin))<fitvalue(fitin) newpop(newin,:)=pop(fitin,:); newin=newin+1; else fitin=fitin+1; end end
crossover
交叉过程染色体交叉的过程
%交叉 function [newpop]=crossover(pop,pc) [px,py]=size(pop); newpop=ones(size(pop)); for i=1:2:px-1 if(rand<pc) cpoint=round(rand*py); newpop(i,:)=[pop(i,1:cpoint),pop(i+1,cpoint+1:py)]; newpop(i+1,:)=[pop(i+1,1:cpoint),pop(i,cpoint+1:py)]; else newpop(i,:)=pop(i); newpop(i+1,:)=pop(i+1); end end
mutation
变异过程染色体变异的过程
%变异 function [newpop1]=mutation(pop,pm) [px,py]=size(pop); for i=1:px if(rand<pm)newpop1(i,1)=sqrt(2) - pop(i,1);newpop1(i,2)=2-newpop1(i,1)^2; elsenewpop1(i,:)=pop(i,:); end end
best
寻找群体中最优个体公告牌用于保存迭代过程中的最优解
%求出群体中适应值最大的值 function [bestindividual,bestfit]=best(pop,fitvalue) [px,py]=size(pop); bestindividual=pop(1,:); bestfit=fitvalue(1); for i=2:px if fitvalue(i)>bestfit bestindividual=pop(i,:); bestfit=fitvalue(i); end end