GlobalSearch 和 MultiStart 的输出函数
什么是输出函数?
输出函数允许您检查优化中的中间结果。此外,它们还允许您以编程方式停止求解器。
输出函数有两种类型,就像输出结构体有两种类型一样:
每次局部求解器运行后,全局输出函数都会运行。它们也会在全局求解器启动和结束时运行。
局部输出函数在局部求解器每次迭代后运行。请参阅 Optimization Toolbox 的输出函数。
要使用全局输出函数:
使用 OutputFcn 中描述的语法编写输出函数。
将
GlobalSearch
或MultiStart
求解器的OutputFcn
属性设置为输出函数的函数句柄。您可以通过将OutputFcn
属性设置为函数句柄的元胞数组使用多个输出函数。
内置的 @savelocalsolutions
输出函数将所有局部解保存到基础工作区中的 localSolTable
变量中。该输出函数保存了不可行局部解以及可行的局部解;run
的 solutions
输出仅返回具有正退出标志的局部解。
收集所有局部解
此示例显示如何将 savelocalsolutions
输出函数与 MultiStart
结合使用来收集运行期间发现的所有局部解。首先指定 savelocalsolutions
作为 MultiStart
的输出函数。
ms = MultiStart(OutputFcn=@savelocalsolutions);
使用 bigtoleft
目标函数和 twocone
非线性约束函数为 MultiStart
创建一个三变量问题,如本例末尾的辅助函数所列。设置每个分量的下界– 1e5
和上界 1e5
。有关该目标函数和非线性约束函数的详细信息,请参阅使用解析黑塞函数的 fmincon 内点算法。
fun = @bigtoleft; lb = -1e5*ones(1,3); ub = -lb;
目标函数和约束函数包含导数信息。设置使用导数的选项。
opts = optimoptions(@fmincon,SpecifyObjectiveGradient=true,...
SpecifyConstraintGradient=true);
将初始点设置为 [–10,–10,–10] 并创建优化问题。
x0 = -10*ones(1,3); prob = createOptimProblem("fmincon",x0=x0,... lb = lb,ub = ub,... objective=fun,nonlcon=@twocone,options=opts);
为了实现可再现性,请设置随机种子。在 35 个起点上运行 MultiStart
。
rng default
[x,fval,eflag,output,solns] = run(ms,prob,35)
MultiStart completed some of the runs from the start points. 11 out of 35 local solver runs converged with a positive local solver exitflag. x = -6.5000 -0.0000 -3.5000 fval = -2.8941e+03 eflag = 2 output = struct with fields: funcCount: 73904 localSolverTotal: 35 localSolverSuccess: 11 localSolverIncomplete: 23 localSolverNoSolution: 1 message: 'MultiStart completed some of the runs from the start points. ↵↵11 out of 35 local solver runs converged with a positive local solver exitflag.' solns = 1×2 GlobalOptimSolution array with properties: X Fval Exitflag Output X0
工作区包含 localSolTable
变量,该变量具有全部 35 个局部解。相比之下,输出结构体显示只有 11 次局部求解器运行成功。
size(localSolTable)
ans = 35 4
要查看输出函数返回的信息类型,请查看 localSolTable
的第一行。
disp(localSolTable(1,:))
X fval exitflag constrviolation ________________________________ _______ ________ _______________ -6.5 2.3432e-07 -3.5 -2894.1 1 0
输出函数返回局部解 X
、其关联的目标函数值 fval
、与该局部求解器运行相对应的退出标志以及约束违反(对于没有约束违反则为 0
)。
辅助函数
以下代码会创建 bigtoleft
辅助函数。
function [f,gradf] = bigtoleft(x) % This is a simple function that grows rapidly negative % as x(1) becomes negative % f = 10*x(:,1).^3+x(:,1).*x(:,2).^2+x(:,3).*(x(:,1).^2+x(:,2).^2); if nargout > 1 gradf=[30*x(1)^2+x(2)^2+2*x(3)*x(1); 2*x(1)*x(2)+2*x(3)*x(2); (x(1)^2+x(2)^2)]; end end
以下代码会创建 twocone
辅助函数。
function [c,ceq,gradc,gradceq] = twocone(x) % This constraint is two cones, z > -10 + r % and z < 3 - r ceq = []; r = sqrt(x(1)^2 + x(2)^2); c = [-10+r-x(3); x(3)-3+r]; if nargout > 2 gradceq = []; gradc = [x(1)/r,x(1)/r; x(2)/r,x(2)/r; -1,1]; end end
自定义 GlobalSearch 输出函数
此输出函数在找到五个具有正退出标志的不同局部极小值后,或找到小于 0.5
的局部最小值后停止 GlobalSearch
。输出函数使用持久局部变量 foundLocal
来存储局部结果。foundLocal
使输出函数能够确定局部解是否与其他解不同,并在 1e-4
的容差范围内。
要使用嵌套函数而不是持久变量来存储局部结果,请参阅 嵌套输出函数的示例。
使用 OutputFcn 中描述的语法编写输出函数。
function stop = StopAfterFive(optimValues, state) persistent foundLocal stop = false; switch state case 'init' foundLocal = []; % initialized as empty case 'iter' newf = optimValues.localsolution.Fval; exitflag = optimValues.localsolution.Exitflag; % Now check if the exit flag is positive and % the new value differs from all others by at least 1e-4 % If so, add the new value to the newf list if exitflag > 0 && all(abs(newf - foundLocal) > 1e-4) foundLocal = [foundLocal;newf]; % Now check if the latest value added to foundLocal % is less than 1/2 % Also check if there are 5 local minima in foundLocal % If so, then stop if foundLocal(end) < 0.5 || length(foundLocal) >= 5 stop = true; end end end
将
StopAfterFive.m
保存为 MATLAB® 路径下文件夹中的文件。编写目标函数并创建优化问题结构体,如寻找全局或多个局部最小值所示。
function f = sawtoothxy(x,y) [t r] = cart2pol(x,y); % change to polar coordinates h = cos(2*t - 1/2)/2 + cos(t) + 2; g = (sin(r) - sin(2*r)/2 + sin(3*r)/3 - sin(4*r)/4 + 4) ... .*r.^2./(r+1); f = g.*h; end
将
sawtoothxy.m
保存为 MATLAB 路径下文件夹中的文件。在命令行中,创建问题结构体:
problem = createOptimProblem('fmincon',... 'objective',@(x)sawtoothxy(x(1),x(2)),... 'x0',[100,-50],'options',... optimoptions(@fmincon,'Algorithm','sqp'));
创建一个以
@StopAfterFive
为输出函数的GlobalSearch
对象,并将迭代显示属性设置为'iter'
。gs = GlobalSearch('OutputFcn',@StopAfterFive,'Display','iter');
(可选)为了获得与此示例相同的答案,请设置默认随机数流。
rng default
运行问题。
[x,fval] = run(gs,problem)
Num Pts Best Current Threshold Local Local Analyzed F-count f(x) Penalty Penalty f(x) exitflag Procedure 0 200 555.5 555.5 0 Initial Point 200 1463 1.547e-15 1.547e-15 1 Stage 1 Local GlobalSearch stopped by the output or plot function. 1 out of 2 local solver runs converged with a positive local solver exit flag. x = 1.0e-07 * 0.0414 0.1298 fval = 1.5467e-15
运行提前停止,因为 GlobalSearch
发现了一个函数值小于 0.5
的点。
无并行输出函数
虽然 MultiStart
可以并行运行,但它不支持全局输出函数和并行绘图函数。此外,虽然 MultiStart
并行运行时局部输出函数和绘图函数在工作进程上运行,但其效果与串行运行不同。本地输出和绘图函数在工作进程上运行时不会创建显示。在工作进程将其结果传递给客户端(MultiStart
并行作业的发起者)之前,您看不到输出和绘图函数的任何其他效果。
有关并行运行 MultiStart
的信息,请参阅 并行计算。