主要内容

优化工具箱™教程

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

本教程示例包括以下任务:

  • 最小化目标函数

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

  • 带约束条件的目标函数最小化

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

无约束优化的例子

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

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

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

exp(-x.^2-y.^2)+(x.^2+y.^2)/20;fsurf (f (2, 2),“ShowContours”“上”

图中包含一个坐标轴。坐标轴包含一个函数曲面类型的对象。

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

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

Fun = @(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文件,然后使用嵌套函数。

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

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;

定义参数。

= 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) %% Copyright 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

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

= 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

这两种方法产生相同的答案,所以您可以使用您认为最方便的方法。

约束优化示例:不等式

考虑前面的约束条件问题:

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

x y / 2 + x + 2 2 + y - 2 2 / 2 2

约束集是倾斜椭圆的内部。查看目标函数和倾斜椭圆的轮廓。

exp(-x.^2-y.^2)+(x.^2+y.^2)/20;x = (x,y) x.*y/2+(x+2).^2+(y-2).^2/2-2;Fimplicit (g)轴([-6 0 -1 7])保持fcontour (f)情节(-.9727 .4685,“罗”);传奇(“约束”“f轮廓”“最低”);持有

图中包含一个坐标轴。轴包含隐函数线、函数轮廓线、直线三个对象。这些对象代表约束,f线,最小值。

从图中可以看出,目标函数在椭圆内的最小值出现在椭圆的右下部分附近。在计算绘制的最小值之前,先猜测一下答案。

X0 = [-2 1];

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

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

求解器要求非线性约束函数给出两个输出,一个用于非线性不等式,一个用于非线性等式。要给出两个输出,使用交易函数。

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

调用非线性约束解算器。这个问题没有线性等式、不等式或边界,所以传递[]参数。

[x, fval exitflag,输出]= fmincon (x0有趣, ,[],[],[],[],[],[], gfun选项);
Iter的一阶范数f(x)可行性优化步骤03 2.365241e-01 0.000e+00 1.972e-01 16 1.748504e-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- 01 0.000e+00 1.241e-01 3.103e-01 4 17 -1.584082e-01 0.000e+00 7.934e-02 1.826e-01 6 23-2.255299e-01 0.000e+00 1.955e-02 1.993e-02 7 26 -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 Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.

显示求解器找到的解决方案。

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

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

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

最小化 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
function [f,gf] = onehump(x) % onhump Helper function for Tutorial for the Optimization Toolbox demo % Copyright 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; 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 Helper function for Tutorial for the Optimization Toolbox demo %测查= [];If 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(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.972e-01 12 1.748504e-01 0.000e+00 1.734e-01 2.260e-01 24 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 36 -6.629161e- 01 0.000e+00 1.241e-01 3.103e-01 47 -1.584082e-01 0.000e+00 7.934e-02 1.826e-01 58 -2.349124e-01 0.000e+00 1.912e- 01 1.571e-01 6 9-2.255299e-01 0.000e+00 4.293e-03 3.821e-02 8 11 -2.446931e-01 0.000e+00 8.100e-04 4.035e-03 9 12 -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内点算法选项。StepTolerance = 1平台以及选项。OptimalityTolerance = 1 e-6

覆盖这两个默认终止条件。

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

解算器。

[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter的一阶范数f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.972e-01 12 1.748504e-01 0.000e+00 1.734e-01 2.260e-01 24 -1.570560e-01 0.000e+00 2.608e-01 9.347e-01 36 -6.629161e- 01 0.000e+00 1.241e-01 3.103e-01 47 -1.584082e-01 0.000e+00 7.934e-02 1.826e-01 58 -2.349124e-01 0.000e+00 1.912e- 01 1.571e-01 6 912 - 2.4485e -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.448927e-01 0.000e+00 4.036e-07 8.156e-05 8.230e-07找到满足约束条件的最小值。优化完成是因为目标函数在可行方向上不减小到最优性公差的值内,约束条件满足到约束公差的值内。

为了更准确地看到新公差造成的差异,在溶液中显示更多的小数。

格式

显示求解器找到的解决方案。

x
x =2×1-0.972742227363546 - 0.468569289098342

将这些值与前面示例中的值进行比较。

xold
xold =2×1-0.972742694488360 - 0.468569966693330

确定值的变化。

x - xold
ans =2×110-6×0.467124813385844 - -0.677594988729435

在解处查看函数值。

fval
fval = -0.244893137879894

看看解决方案改进了多少。

fval——minfval
ans = -3.996450220755676 e-07

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

查看函数求值的总数。

output.funcCount
ans = 15

将这个数字与示例中使用用户提供的梯度和默认容差解决的函数求值数进行比较。

Fgradevals
Fgradevals = 14

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

如果你提供一个Hessian和梯度,求解器甚至更准确和高效。

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

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

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

类型hessfordemo
函数H = hessfordemo(x,lambda) % hessfordemo Helper function for Tutorial for the Optimization Toolbox demo %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 + λ .ineqnonlin(1)*hessc;

为了使用Hessian,您需要适当地设置选项。

选择= optimoptions (“fmincon”...“算法”“内点”...“SpecifyConstraintGradient”,真的,...“SpecifyObjectiveGradient”,真的,...“HessianFcn”, @hessfordemo);

公差被设置为默认值,这将导致更少的函数计数。设置在每次迭代时显示结果的选项。

选项。显示=“通路”

解算器。

[x, fval exitflag,输出]= fmincon (x0 @onehump ,[],[],[],[],[],[],...@tiltellipse选项);
Iter的一阶范数f(x)可行性优化步骤01 2.365241e-01 0.000e+00 1.972e-01 13 5.821325e-02 0.000e+00 1.443e-01 8.728e-01 25 -1.218829e-01 0.000e+00 1.007e-01 4.927e-01 36 -1.421167e-01 0.000e+00 8.486e-02 5.165e- 01 4 7 - 2.261616e -01 0.000e+00 1.989e-02 1.667e-01 5 8 -2.433609e-01 0.000e+00 1.537e-03 3.486e-02 6-2.448911e-01 0.000e+00 2.057e-04 2.727e-03 7 10 -2.448911e-01 0.000e+00 2.068e-06 4.191e-04 8 11 -2.448931e-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

相关的话题