传递额外参数
额外参数、固定变量或数据
有时目标函数或约束函数除了自变量之外还有参数。额外的参数可以是数据,也可以表示在优化过程中不变的变量。传递这些参数有三种方法:
全局变量比较麻烦,因为它们不允许在函数间重用名称。最好使用另外两种方法。
通常,对于基于问题的优化,您可以以自然的方式传递额外的参数。请参阅在基于问题的方法中传递额外的参数。
例如,假设您要对最小化以下函数
(1) |
其中,a、b 和 c 使用不同值。求解器接受仅依赖于单个变量(本例中为 x)的目标函数。以下各节显示如何提供附加参数 a、b 和 c。这些解是参数值为 a = 4、b = 2.1 和 c = 4 时,使用 fminunc
求得的在 x0 = [0.5 0.5] 附近的解。
匿名函数
要使用匿名函数传递参数,请执行以下操作:
编写包含以下代码的文件:
function y = parameterfun(x,a,b,c) y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ... (-c + c*x(2)^2)*x(2)^2;
通过在 MATLAB® 提示符下输入以下命令,为参数赋值并定义匿名函数的函数句柄
f
:a = 4; b = 2.1; c = 4; % Assign parameter values x0 = [0.5,0.5]; f = @(x)parameterfun(x,a,b,c);
使用匿名函数调用求解器
fminunc
:在命令行窗口中显示以下输出:[x,fval] = fminunc(f,x0)
Local minimum found. Optimization completed because the size of the gradient is less than the default value of the function tolerance. x = -0.0898 0.7127 fval = -1.0316
注意
匿名函数中传递的参数是那些在匿名函数创建时存在的参数。例如
a = 4; b = 2.1; c = 4; f = @(x)parameterfun(x,a,b,c)
假设您随后将 a
更改为 3,然后运行
[x,fval] = fminunc(f,x0)
您会得到与之前相同的答案,因为 parameterfun
使用的是 a = 4
,这是 f
创建时的值。
要更改传递给函数的参数,请重新输入匿名函数来进行更新:
a = 3; f = @(x)parameterfun(x,a,b,c)
您可以创建包含多个参量的匿名函数。例如,要使用 lsqcurvefit
,请首先创建一个接受两个输入参量 x
和 xdata
的函数:
fh = @(x,xdata)(sin(x).*xdata +(x.^2).*cos(xdata)); x = pi; xdata = pi*[4;2;3]; fh(x, xdata)
ans = 9.8696 9.8696 -9.8696
lsqcurvefit
:% Assume ydata exists
x = lsqcurvefit(fh,x,xdata,ydata)
嵌套函数
要通过嵌套函数传递公式 1 的参数,请编写一个文件,该文件
接受
a
、b
、c
和x0
作为输入包含目标函数作为嵌套函数
调用
fminunc
以下是此示例的函数文件的代码:
function [x,fval] = runnested(a,b,c,x0) [x,fval] = fminunc(@nestedfun,x0); % Nested function that computes the objective function function y = nestedfun(x) y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) +... (-c + c*x(2)^2)*x(2)^2; end end
nestedfun
,它可以访问变量 a
、b
和 c
。要运行优化,请输入:
a = 4; b = 2.1; c = 4;% Assign parameter values
x0 = [0.5,0.5];
[x,fval] = runnested(a,b,c,x0)
全局变量
全局变量可能会比较麻烦,因此最好避免使用它们。而且,全局变量在并行计算中会失败。请参阅Factors That Affect Results。
要使用全局变量,请在工作区和使用变量的函数中声明变量是全局的。
编写函数文件:
function y = globalfun(x) global a b c y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ... (-c + c*x(2)^2)*x(2)^2;
在您的 MATLAB 工作区中,定义变量并运行
fminunc
:global a b c; a = 4; b = 2.1; c = 4; % Assign parameter values x0 = [0.5,0.5]; [x,fval] = fminunc(@globalfun,x0)
输出与在匿名函数中相同。