主要内容

优化工具箱教程

本教程包括多个示例,展示如何使用两个非线性优化求解器,fminunc而且fmincon,以及如何设置选项。本教程中概述的原则适用于其他非线性求解器,例如fgoalattainfminimaxlsqnonlinlsqcurvefit,fsolve

教程示例涵盖了以下任务:

  • 最小化目标函数

  • 用附加参数最小化相同函数

  • 最小化有约束的目标函数

  • 通过提供梯度或Hessian或改变选项来获得更有效或更准确的解决方案

无约束优化示例

考虑寻找函数的最小值的问题

x 经验值 - x 2 + y 2 + x 2 + y 2 / 2 0

绘制函数图,看它在哪里被最小化。

F = @(x,y) x.*exp(-x.²-y.²)+(x.²+y.²)/20;fsurf (f (2, 2),“ShowContours”“上”

图中包含一个轴对象。axis对象包含一个functionsurface类型的对象。

图中显示最小值在点(-1/2,0)附近。

通常将目标函数定义为MATLAB®文件。在本例中,函数非常简单,可以将其定义为匿名函数。

Fun = @(x) f(x(1),x(2));

设定一个寻找解决方案的起始点。

X0 = [-.5;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文件,然后使用嵌套函数。

考虑前面例子中的目标函数。

f x y x 经验值 - x 2 + y 2 + x 2 + y 2 / 2 0

用(a,b,c)参数化函数,如下所示:

f x y 一个 b c x - 一个 经验值 - x - 一个 2 + y - b 2 + x - 一个 2 + y - b 2 / c

该函数是原始目标函数的移位和缩放版本。

MATLAB文件函数

考虑一个MATLAB文件目标函数bowlpeakfun定义如下。

类型bowlpeakfun
function y = bowlpeakfun(x, a, b, c) %% 2008年版权MathWorks公司y = (x(1)——)。* exp (- ((x(1)——)^ 2 + (x (2) - b) ^ 2)) + ((x(1)——)^ 2 + (x (2) - b) ^ 2) / c;

定义参数。

A = 2;B = 3;C = 10;

为MATLAB文件创建一个匿名函数句柄。

F = @(x)bowlpeakfun(x,a,b,c)
f =Function_handle with value:@ (x) bowlpeakfun (x, a, b, c)

调用fminunc求最小值。

X0 = [-.5;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.外层函数,nestedbowlpeakfminunc然后传递目标函数,nestedfun

定义参数、初始猜测和选项:

A = 2;B = 3;C = 10;X0 = [-.5;0);选项= optimoptions(“fminunc”“算法”“拟牛顿”);

运行优化:

[x,fval] = nestedbowlpeak(a,b,c,x0,options)
找到局部极小值。优化完成,因为梯度的大小小于最优性公差的值。
x =2×11.3639 - 3.0000
Fval = -0.3840

两种方法都会得到相同的答案,所以您可以使用您认为最方便的方法。

约束优化示例:不等式

考虑前面的约束问题:

最小化 x 经验值 - x 2 + y 2 + x 2 + y 2 / 2 0

主题 x y / 2 + x + 2 2 + y - 2 2 / 2 2

约束集是一个倾斜椭圆的内部。查看目标函数与倾斜椭圆一起绘制的等高线。

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轮廓”“最低”);持有

图中包含一个轴对象。axis对象包含3个隐式函数line,函数contour, line类型的对象。这些对象表示约束,f轮廓,最小值。

图中显示,椭圆内目标函数的最低值出现在椭圆的右下部分附近。在计算绘制的最小值之前,先猜测一下解。

X0 = [-2 1];

设置优化选项以使用内点算法,并在每次迭代中显示结果。

选项= optimoptions(“fmincon”“算法”“内点”“显示”“通路”);

求解器要求非线性约束函数给出两个输出,一个是非线性不等式,一个是非线性等式。方法来编写约束以同时给出两个输出交易函数。

Gfun = @(x) deal(g(x(1),x(2)),[]);

调用非线性约束求解器。这个问题没有线性等式或不等式或边界,所以这些参数可以通过[]。

[x, fval exitflag,输出]= fmincon (x0有趣, ,[],[],[],[],[],[], gfun选项);
Iter f -count f(x)可行性优化步骤03 2.365241e-01 0.000e+00 1.734e-01 0.000e+00 1.734e-01 2.260e-01 2 10 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 3 14 -6.629160e-02 0.000e+00 1.934e -02 1.826e-01 5 20 -2.349124e-01 0.000e+00 1.955e-02 1.571e-01 6 23 -2.444225e-01 0.000e+00 4.293e-03 3.821e-02 8 29 -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

查看函数求值的总数。

Fevals = output.funcCount
发烧= 38次

求解时满足不等式约束。

[c, ceq] = gfun(x)
C = -2.4608e-06
Ceq = []

因为c(x)趋近于0,约束条件是活跃,这意味着它会影响解。回想一下无约束解。

uncx
uncx =2×1-0.6691 - 0.0000

回想一下无约束目标函数。

uncf
Uncf = -0.4052

看看约束移动了多少解,增加了多少目标。

fval-uncf
Ans = 0.1603

约束优化示例:用户提供的梯度

通过提供梯度,您可以更有效和准确地解决优化问题。这个例子和前面的例子一样,解决了不平等约束的问题

最小化 x 经验值 - x 2 + y 2 + x 2 + y 2 / 2 0

主题 x y / 2 + x + 2 2 + y - 2 2 / 2 2

提供f(x)的梯度fmincon,将目标函数以MATLAB文件的形式编写。

类型onehump
函数[f,gf] = one驼峰(x) %帮助函数为教程的优化工具箱演示%版权所有2008-2009 the MathWorks, Inc. r = x(1)^2 + x(2)^2;S = exp(-r);F = x(1)*s+r/20;If nargout > 1 gf = [(1-2*x(1)^2)*s+x(1)/10;2 * x (1) * (2) * s + x (2) / 10);结束

约束及其梯度包含在MATLAB文件中tiltellipse

类型tiltellipse
函数[c,ceq,gc,gceq] = tiltellipse(x) % tiltellipse辅助函数用于优化工具箱演示教程%版权所有2008-2009 the MathWorks, Inc. c = x(1)*x(2)/2 + (x(1)+2)^2 + (x(2)-2)^2/2 -2;Ceq = [];如果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 f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.734e-01 0.000e+00 1.734e-01 2.260e-01 24 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 3 36 -6.629161e-02 0.000e+00 7.934e-02 1.826e-01 58 -2.349124e-01 0.000e+00 1.955e-02 1.993e-02 69 -2.444225e-01 0.000e+00 4.293e-03 3.821e- 01 0.000e 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次

约束优化示例:更改默认终止容差

本例继续使用梯度并解决相同的约束问题

最小化 x 经验值 - x 2 + y 2 + x 2 + y 2 / 2 0

主题 x y / 2 + x + 2 2 + y - 2 2 / 2 2

在这种情况下,通过覆盖默认终止条件(选项。StepTolerance而且选项。OptimalityTolerance).的默认值fmincon内点算法是选项。步进公差= 1e-10而且选项。OptimalityTolerance = 1e-6

重写这两个默认终止条件。

选项= optimoptions(选项,...“StepTolerance”1 e15汽油,...“OptimalityTolerance”1 e-8);

调用求解器。

[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter f -count f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.734e-01 0.000e+00 1.734e-01 2.260e-01 24 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 3 36 -6.629161e-02 0.000e+00 7.934e-02 1.826e-01 58 -2.349124e-01 0.000e+00 1.955e-02 1.993e-02 69 -2.444225e-01 0.000e+00 4.293e-03 3.821e- 01 0.000e 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.996450220755676e-07

答案是负的,因为新解更小。

查看函数求值的总数。

output.funcCount
Ans = 15

将此数字与使用用户提供的梯度和默认容差解决的示例中的函数计算数量进行比较。

Fgradevals
Fgradevals = 14

约束优化示例:用户提供的Hessian

如果你提供一个黑森除了梯度,求解器甚至更准确和有效。

fmincon内点算法将一个Hessian矩阵作为一个单独的函数(不属于目标函数)。Hessian函数H(x,)计算拉格朗日函数的Hessian;看到Hessian for fmincon内点算法

求解器计算这些值lambda.ineqnonlin而且lambda.eqlin;你的Hessian函数告诉解算器如何使用这些值。

这个例子有一个不等式约束,所以黑森函数定义为hessfordemo函数。

类型hessfordemo
H = hessfordemo(x,lambda) % hessfordemo用于优化工具箱教程的帮助函数%版权所有2008-2009 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 f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.972e-01 0.000e+00 1.443e-01 8.728e-01 25 -1.218829e-01 0.000e+00 1.486e -02 4.927e-01 36 -1.421167e-01 0.000e+00 1.989e-02 5.167e -02 5 8 -2.433609e-01 0.000e+00 1.537e-03 3.486e-02 6 9 -2.446875e-01 0.000e+00 2.057e-04 4.191e- 01 0.000e+00 2.068e-06 4.191e- 01 0.000e 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

相关的话题