算法原理:Nelder-Mead法是利用多面体来逐步逼近最佳点x*.设函数变量为n维,则在n维空间里多面体有(n+1)个顶点.设x1,x2,...,xn+1为多面体的顶点,且满足:
f(x1)<=f(x2)<=...<=f(xn+1)
Nelder-Mead法试着将多面体中最差的顶点xn+1(也就是函数的最大点)以新的最佳点替代,来更新多面体,使之逼近最佳解.更新的设定方式有四种,分别是:反射,扩展,外收缩,内收缩.如果这四种方法都不适用,则进行变小步骤.
算法实现:
在matlab中编程实现Nelder-Mead算法为:Opt-Nelder.
功能:Nelder-Mead算法求无约束最优化解.
调用格式:[xo,fo]=Opt_Nelder(f,x0,TolX,TolFun,MaxIter).
其中,f为函数名;
x0为搜索初值;
TolX为最优值点间的误差阈值;
TolFun为函数的误差阈值;
xo为最优化点值;
fo为函数在点xo处的函数值;
算法程序分Nelder0.m和Opt-Nelder.m其中子程序Nelder0.m用于二维空间上的多边形最优化逼近.对于大于2维的情形,可以通过若干次二维迭代计算求出最优值.Opt-Nelder.m可求解若干维变量的最优化问题.
(1)Nelder0.m
- function [xo,fo]=Nelder0(f,abc,fabc,TolX,TolFun,k)
- %二维空间中的多边形逼近
- % f:函数名
- % abc:二维空间三个顶点值
- % fabc:三个顶点处的函数值
- % TolX:最优点的误差阈值
- % TolFun:最优点处的函数值的误差阈值
- % k:最大迭代次数
- %%%%确定三个顶点a,b,c并且按其函数值从小到大排列
- [fabc,I]=sort(fabc);%将二维空间中的多边形三个顶点的函数值按从小到大排列
- a=abc(I(1),:);
- b=abc(I(2),:);
- c=abc(I(3),:);
- fa=fabc(1);
- fb=fabc(2);
- fc=fabc(3);
- %%%%判断三点或三点函数值的距离是否小于给定阈值.若小于阈值则停止循环,得最优解x0=a
- fba=fb-fa;
- fcb=fc-fb;
- if k<=0 | abs(fba)+abs(fcb)<TolFun | abs(b-a)+abs(c-b)<TolX
- xo=a;
- fo=fa;
- else
- m=(a+b)/2;
- e=3*m-2*c; %扩展
- fe=feval(f,e);
- if fe<fb
- c=e;
- fc=fe;
- else
- r=(m+e)/2; %反射
- fr=feval(f,r);
- if fr<fc
- c=r;
- fc=fr;
- end
- if fr>=fb
- s=(c+m)/2; %内收缩
- fs=feval(f,s);
- if fs<fc
- c=s;
- fc=fs;
- else
- b=m;
- c=(a+c)/2; %变小
- fb=feval(f,b);
- fc=feval(f,c);
- end
- end
- end
- [xo,fo]=Nelder0(f,[a;b;c],[fa,fb,fc],TolX,TolFun,k-1);
- end
复制代码
(2)Opt_Nelder.m
- function [xo,fo]=Opt_Nelder(f,x0,TolX,TolFun,MaxIter)
- %Nelder-Mead法用于多维变量的最优化问题,维数>=2
- % f:函数名
- % abc:二维空间三个顶点值
- % fabc:三个顶点处的函数值
- % TolX:最优点的误差阈值
- % TolFun:最优点处的函数值的误差阈值
- % MaxIter:最大迭代次数
- N=length(x0);
- if N==1 %一维情况,用二次逼近计算
- [xo,fo]=Opt_Quadratic(f,x0,TolX,TolFun,MaxIter);
- return
- end
- S=eye(N);
- for i=1:N %自变量维数大于2时,重复计算每个子平面的情况
- i1=i+1;
- if i1>N
- i1=1;
- end
- abc=[x0;x0+S(i,:);x0+S(i1,:)]; %每一个定向子平面
- fabc=[feval(f,abc(1,:));feval(f,abc(2,:));feval(f,abc(3,:))];
- [x0,fo]=Nelder0(f,abc,fabc,TolX,TolFun,MaxIter);
- if N<3 %二维情况不需重复
- break;
- end
- end
- xo=x0;
- 检验:
- f=inline('x(1)*(x(1)-5-x(2))+x(2)*(x(2)-4)','x');
- x0=[0 4];
- TolX=1e-4;
- TolFun=1e-9;
- MaxIter=100;
- [xN,fN]=Opt_Nelder(f,x0,TolX,TolFun,MaxIter)
复制代码- xN =
- 4.6667 4.3333
- fN =
- -20.3333
复制代码 |