主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

GlobalSearch 和 MultiStart 的输出函数

什么是输出函数?

输出函数允许您检查优化中的中间结果。此外,它们还允许您以编程方式停止求解器。

输出函数有两种类型,就像输出结构体有两种类型一样:

  • 每次局部求解器运行后,全局输出函数都会运行。它们也会在全局求解器启动和结束时运行。

  • 局部输出函数在局部求解器每次迭代后运行。请参阅 Optimization Toolbox 的输出函数

要使用全局输出函数:

  • 使用 OutputFcn 中描述的语法编写输出函数。

  • GlobalSearchMultiStart 求解器的 OutputFcn 属性设置为输出函数的函数句柄。您可以通过将 OutputFcn 属性设置为函数句柄的元胞数组使用多个输出函数。

内置的 @savelocalsolutions 输出函数将所有局部解保存到基础工作区中的 localSolTable 变量中。该输出函数保存了不可行局部解以及可行的局部解;runsolutions 输出仅返回具有正退出标志的局部解。

收集所有局部解

此示例显示如何将 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 的容差范围内。

要使用嵌套函数而不是持久变量来存储局部结果,请参阅 嵌套输出函数的示例

  1. 使用 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
  2. StopAfterFive.m 保存为 MATLAB® 路径下文件夹中的文件。

  3. 编写目标函数并创建优化问题结构体,如寻找全局或多个局部最小值所示。

    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
  4. sawtoothxy.m 保存为 MATLAB 路径下文件夹中的文件。

  5. 在命令行中,创建问题结构体:

    problem = createOptimProblem('fmincon',...
        'objective',@(x)sawtoothxy(x(1),x(2)),...
        'x0',[100,-50],'options',...
        optimoptions(@fmincon,'Algorithm','sqp'));
  6. 创建一个以 @StopAfterFive 为输出函数的 GlobalSearch 对象,并将迭代显示属性设置为 'iter'

    gs = GlobalSearch('OutputFcn',@StopAfterFive,'Display','iter');
  7. (可选)为了获得与此示例相同的答案,请设置默认随机数流。

    rng default
  8. 运行问题。

    [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 的信息,请参阅 并行计算

另请参阅

主题