优化工具箱教程
本教程包括多个示例,演示如何使用两个非线性优化求解器,fminunc
而且fmincon
,以及如何设置选项。本教程中概述的原则适用于其他非线性求解器,例如fgoalattain
,fminimax
,lsqnonlin
,lsqcurvefit
,fsolve
.
教程示例涵盖了以下任务:
最小化目标函数
用附加参数最小化相同的函数
带约束的目标函数最小化
通过提供梯度或Hessian,或通过改变选项,获得更有效或更准确的解决方案
无约束优化的例子
考虑寻找函数的最小值的问题
画出函数图,看看它在哪里最小化。
F = @(x,y) x.*exp(-x.²-y.²)+(x.²+y.²)/20;fsurf (f (2, 2),“ShowContours”,“上”)
图显示最小值在点(-1/2,0)附近。
通常你将目标函数定义为MATLAB®文件。在本例中,函数非常简单,可以将其定义为匿名函数。
乐趣= @(x) f(x(1),x(2));
为寻找解设定一个初始点。
x0 =[闲置;0);
设置优化选项以使用fminunc
默认的“拟牛顿”
算法。这一步确保本教程在每个MATLAB版本中都能正常工作。
选择= optimoptions (“fminunc”,“算法”,“拟牛顿”);
在求解器执行计算时查看迭代。
选项。显示=“通路”;
调用fminunc
,一个无约束非线性最小化器。
[x, fval, exitflag, output] = fminunc(fun,x0,options);
一阶迭代函数计数f(x)步长最优性03 -0.3769 0.339 1 6 -0.379694 1 0.286 2 9 -0.405023 1 0.0284 3 12 -0.405233 1 0.00386 4 15 -0.405237 1 3.17e-05 5 18 -0.405237 1 3.35e-08发现局部最小值。由于梯度的大小小于最优公差值,因此优化已完成。
显示解算器找到的解。
uncx = x
uncx =2×1-0.6691 - 0.0000
查看解处的函数值。
uncf = fval
uncf = -0.4052
这些示例使用函数计算的次数作为效率的度量。查看函数求值的总数。
output.funcCount
ans = 18
附加参数的无约束优化实例
接下来,首先通过使用MATLAB文件,然后通过使用嵌套函数,将额外的参数作为附加参数传递给目标函数。
考虑前面例子中的目标函数。
用(a,b,c)将函数参数化如下:
这个函数是原始目标函数的平移和缩放版本。
MATLAB文件函数
考虑一个MATLAB文件目标函数命名为bowlpeakfun
定义如下。
类型bowlpeakfun
在TUTDEMO中传递参数的目标函数。% 2008年版权MathWorks公司y = (x(1)——)。* exp (- ((x(1)——)^ 2 + (x (2) - b) ^ 2)) + ((x(1)——)^ 2 + (x (2) - b) ^ 2) / c;
定义参数。
= 2;b = 3;c = 10;
创建MATLAB文件的匿名函数句柄。
f = @ (x) bowlpeakfun (x, a, b, c)
f =function_handle与价值:@ (x) bowlpeakfun (x, a, b, c)
调用fminunc
求最小值。
x0 =[闲置;0);选择= optimoptions (“fminunc”,“算法”,“拟牛顿”);[x, fval] = fminunc(f,x0,options)
局部最小值。由于梯度的大小小于最优公差值,因此优化已完成。
x =2×11.3639 - 3.0000
fval = -0.3840
嵌套函数
考虑到nestedbowlpeak
函数,该函数将目标作为嵌套函数实现。
类型nestedbowlpeak
function [x,fval] = nestedbowlpeak(a,b,c,x0,options) % nestedbowlpeak TUTDEMO中参数传递的嵌套函数。版权所有2008 The MathWorks, Inc. [x,fval] = fminunc(@nestedfun,x0,options);函数y = nestedfun (x) y = (x(1)——)。* exp (- ((x(1)——)^ 2 + (x (2) - b) ^ 2)) + ((x(1)——)^ 2 + (x (2) - b) ^ 2) / c;结束结束
参数(a,b,c)对于嵌套的目标函数是可见的nestedfun
.外部函数,nestedbowlpeak
称fminunc
传递目标函数,nestedfun
.
定义参数、初始猜测和选项:
= 2;b = 3;c = 10;x0 =[闲置;0);选择= optimoptions (“fminunc”,“算法”,“拟牛顿”);
运行优化:
[x, fval] = nestedbowlpeak (a, b, c, x0,选项)
局部最小值。由于梯度的大小小于最优公差值,因此优化已完成。
x =2×11.3639 - 3.0000
fval = -0.3840
两种方法都会得到相同的答案,所以您可以使用您认为最方便的方法。
约束优化例子:不等式
考虑前面带约束的问题:
约束集是一个倾斜椭圆的内部。查看目标函数与倾斜椭圆一起绘制的等高线。
F = @(x,y) x.*exp(-x.²-y.²)+(x.²+y.²)/20;G = @(x,y) x.*y/2+(x+2).^2+(y-2).^2/2-2;Fimplicit (g)轴([-6 0 -1 7])保持在fcontour (f)情节(-.9727 .4685,“罗”);传奇(“约束”,“f轮廓”,“最低”);持有从
从图中可以看出,椭圆内目标函数的最小值出现在椭圆的右下部分附近。在计算绘图的最小值之前,先猜测一下解。
X0 = [-2 1];
设置优化选项以使用内点算法,并在每次迭代时显示结果。
选择= optimoptions (“fmincon”,“算法”,“内点”,“显示”,“通路”);
求解器要求非线性约束函数给出两个输出,一个是非线性不等式,一个是非线性等式。要给出两个输出,可以使用交易
函数。
Gfun = @(x) deal(g(x(1),x(2)),[]);
调用非线性约束求解器。该问题没有线性等式或不等式或边界,因此使用[]作为这些参数。
[x, fval exitflag,输出]= fmincon (x0有趣, ,[],[],[],[],[],[], gfun选项);
Iter f -count一阶Norm f(x)可行性优化步骤03 2.365241e-01 0.000e+00 1.9752 -01 16 1.748504e-01 0.000e+00 1.734e-01 0.000e+00 2.608e-01 9.347e-01 3 14 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 0.000e+00 1.934e -02 3.103e-01 4 17 -1.584082e-01 0.000e+00 1.912e-02 1.826e-01 5 20 -2.349124e-01 0.000e+00 1.912e-02 1.571e-01 6 23 -2.444225e-01 0.000e+00 1.955e-02 1.993e-02 826 -2.446931e-01 0.000e+00 8.100e-04 4.035e-03 9 32-2.446933e-01 0.000e+00 1.999e-04 8.126e-04 10 35 -2.448531e-01 0.000e+00 4.004e-05 3.289e-04 11 38 -2.448927e-01 0.000e+00 4.036e-07 8.156e-05发现满足约束的局部极小值。由于目标函数在可行方向上不减少,优化完成,在最优性公差的值内,约束满足在约束公差的值内。
显示解算器找到的解。
x
x =1×2-0.9727 - 0.4686
查看解处的函数值。
fval
fval = -0.2449
查看函数求值的总数。
函数宏指令= output.funcCount
函数宏指令= 38
在解处满足不等式约束。
[c, ceq] = gfun(x)
c = -2.4608 e-06
测查= []
因为c(x)接近于0,约束条件是活跃,这意味着它会影响解。回想一下无约束解。
uncx
uncx =2×1-0.6691 - 0.0000
回想一下无约束目标函数。
uncf
uncf = -0.4052
看看约束使解移动了多少,增加了多少目标。
fval-uncf
ans = 0.1603
约束优化例子:用户提供的梯度
通过提供梯度,可以更有效、更准确地解决优化问题。这个例子和前面的例子一样,解决了不等式约束问题
提供f(x)到的梯度fmincon
,以MATLAB文件的形式写出目标函数。
类型onehump
函数[f,gf] = one驼峰(x) % one驼峰优化工具箱演示教程的辅助函数%版权所有the MathWorks, Inc. r = x(1)^2 + x(2)^2;s = exp (- r);f = x (1) * s + r / 20;如果nargout > 1 gf = [(1-2*x(1)^2)*s+x(1)/10;2 * x (1) * (2) * s + x (2) / 10);结束
该约束及其梯度包含在MATLAB文件中tiltellipse
.
类型tiltellipse
function [c,ceq,gc,gceq] = tiltellipse(x) % tiltellipse优化工具箱演示教程的辅助函数%版权所有the MathWorks, Inc. c = x(1)*x(2)/2 + (x(1)+2)^2 + (x(2)-2;测查= [];如果nargout > 2 gc = [x(2)/2+2*(x(1)+2);(1) / 2 + x (2) 2);gceq = [];结束
为寻找解设定一个初始点。
x0 = [2;1];
设置优化选项以使用与上一个示例相同的算法,以便进行比较。
选择= optimoptions (“fmincon”,“算法”,“内点”);
设置选项以在目标函数和约束函数中使用梯度信息。注意:这些选项必须打开,否则渐变信息将被忽略。
选择= optimoptions(选项,...“SpecifyObjectiveGradient”,真的,...“SpecifyConstraintGradient”,真正的);
因为fmincon
不需要用有限差分估计梯度,求解器应该有更少的函数计数。设置在每次迭代中显示结果的选项。
选项。显示=“通路”;
解算器。
[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter f -count一阶Norm f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.734e-01 2.260e-01 0.000e+00 1.734e-01 0.000e+00 2.608e-01 9.347e-01 0.000e+00 1.608e -01 9.347e-01 0.000e+00 1.934e -01 0.000e+00 1.934e -02 1.103e -01 58 -2.349124e-01 0.000e+00 1.912e-02 1.571e-01 69 -2.444225e-01 0.000e+00 1.955e-02 1.993e-02 8 11 -2.446931e-01 0.000e+00 8.100e-04 4.035e-03 912-2.446933e-01 0.000e+00 1.999e-04 8.126e-04 10 13 -2.448531e-01 0.000e+00 4.004e-05 3.289e-04 11 14 -2.448927e-01 0.000e+00 4.036e-07 8.156e-05发现满足约束的局部极小值。由于目标函数在可行方向上不减少,优化完成,在最优性公差的值内,约束满足在约束公差的值内。
fmincon
在前面的例子中估计了梯度,所以这个例子中的迭代是相似的。
显示解算器找到的解。
xold = x
xold =2×1-0.9727 - 0.4686
查看解处的函数值。
minfval = fval
minfval = -0.2449
查看函数求值的总数。
Fgradevals = output.funcCount
Fgradevals = 14
将这个数字与没有梯度的函数求值的数量进行比较。
函数宏指令
函数宏指令= 38
约束优化示例:更改默认终止公差
本例继续使用梯度并解决相同的约束问题
.
在这种情况下,您可以通过覆盖默认终止条件(选项。StepTolerance
而且选项。OptimalityTolerance
).的默认值fmincon
内点算法选项。StepTolerance = 1平台以及
而且选项。OptimalityTolerance = 1 e-6
.
覆盖这两个默认终止条件。
选择= optimoptions(选项,...“StepTolerance”1 e15汽油,...“OptimalityTolerance”1 e-8);
解算器。
[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter f -count一阶Norm f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.734e-01 2.260e-01 0.000e+00 1.734e-01 0.000e+00 2.608e-01 9.347e-01 0.000e+00 1.608e -01 9.347e-01 0.000e+00 1.934e -01 0.000e+00 1.934e -02 1.103e -01 58 -2.349124e-01 0.000e+00 1.912e-02 1.571e-01 69 -2.444225e-01 0.000e+00 1.955e-02 1.993e-02 8 11 -2.446931e-01 0.000e+00 8.100e-04 4.035e-03 912-2.446933e-01 0.000e+00 1.999e-04 8.126e-04 10 13 -2.448531e-01 0.000e+00 4.004e-05 3.289e-04 11 14 -2.448927e-01 0.000e+00 4.036e-07 8.156e-05 12 15 -2.448931e-01 0.000e+00 4.000e-09 8.230e-07发现满足约束的局部极小值。由于目标函数在可行方向上不减少,优化完成,在最优性公差的值内,约束满足在约束公差的值内。
为了更准确地看到新公差造成的差异,在溶液中显示更多小数。
格式长
显示解算器找到的解。
x
x =2×1-0.972742227363546 - 0.468569289098342
将这些值与前面示例中的值进行比较。
xold
xold =2×1-0.972742694488360 - 0.468569966693330
确定值的变化。
x - xold
ans =2×1106×0.467124813385844 - -0.677594988729435
查看解处的函数值。
fval
fval = -0.244893137879894
看看解决方案改进了多少。
fval——minfval
ans = -3.996450220755676 e-07
答案是负的,因为新的解变小了。
查看函数求值的总数。
output.funcCount
ans = 15
将这个数字与使用用户提供的梯度和默认公差解决的示例中的函数求值的数量进行比较。
Fgradevals
Fgradevals = 14
受限优化示例:用户提供的Hessian
如果你提供一个黑森除了梯度,求解甚至更准确和有效。
的fmincon
内点算法将一个Hessian矩阵作为一个单独的函数(不是目标函数的一部分)。Hessian函数H(x,)求拉格朗日的Hessian;看到Hessian for fmincon内点算法.
求解器计算这些值lambda.ineqnonlin
而且lambda.eqlin
;你的Hessian函数告诉求解者如何使用这些值。
这个例子有一个不等式约束,所以Hessian被定义为hessfordemo
函数。
类型hessfordemo
the MathWorks, Inc. s = exp(-(x(1)^2+x(2)^2));H = (2 * x (1) * (2 * x (1) ^ 2 - 3) * s + 1/10, 2 * x (2) * (2 * x(1) ^ 2 - 1) *年代;2 * x (2) * (2 * x (1) ^ 2 - 1) * s, 2 * x (1) * (2 * x (2) ^ 2 - 1) * s + 1/10);hessc = (2 1/2; 1/2, 1);H = H + lambda.ineqnonlin(1)*hessc;
为了使用Hessian,您需要适当地设置选项。
选择= optimoptions (“fmincon”,...“算法”,“内点”,...“SpecifyConstraintGradient”,真的,...“SpecifyObjectiveGradient”,真的,...“HessianFcn”, @hessfordemo);
公差设置为默认值,这将导致更少的函数计数。设置在每次迭代中显示结果的选项。
选项。显示=“通路”;
解算器。
[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter f -count一阶Norm f(x)可行性最优步骤01 2.365241e-01 0.000e+00 1.9752 e-01 8.728e-01 0.000e+00 1.443e-01 8.728e-01 0.000e+00 1.446e -01 4.927e-01 36 - 1.4211616e -01 0.000e+00 1.486e -02 5.165e- 01 0.000e+00 1.989e-02 1.667e- 02 48 - 2.4436875e -01 0.000e+00 1.1537e -03 3.486e-02 6 9 - 2.448975e -01 0.000e+00 2.057e-04 2.727e-03 8 11 -2.448911e-01 0.000e+00 2.001e-08 4.218e-06本地找到满足约束条件的最小值。由于目标函数在可行方向上不减少,优化完成,在最优性公差的值内,约束满足在约束公差的值内。
结果显示迭代次数更少且不同。
显示解算器找到的解。
x
x =2×1-0.972742246093537 - 0.468569316215571
查看解处的函数值。
fval
fval = -0.244893121872758
查看函数求值的总数。
output.funcCount
ans = 11
将这个数字与仅使用梯度计算求解的示例中的函数计算的数量进行比较,并使用相同的默认公差。
Fgradevals
Fgradevals = 14