模拟退火选项
此示例显示如何使用 Global Optimization Toolbox 中的 simulannealbnd
创建和管理模拟退火函数 optimoptions
的选项。
优化问题设置
simulannealbnd
使用模拟退火寻找函数的最小值。在这个例子中,我们使用 simulannealbnd
来最小化目标函数 dejong5fcn
。运行此示例时,此函数可用。dejong5fcn
是两个变量的实值函数,具有许多局部极小值,因此很难优化。在 x =(-32,-32)
处只有一个全局最小值,其中 f(x) = 0.998
。为了定义我们的问题,我们必须定义目标函数、起点、以及每个 -64 <= x(i) <= 64
的范围 x(i)
指定的边界。
ObjectiveFunction = @dejong5fcn; startingPoint = [-30 0]; lb = [-64 -64]; ub = [64 64];
运行此示例时可用的函数 plotobjective
在范围 -64 <= x1 <= 64
, -64 <= x2 <= 64
上绘制目标函数。
plotobjective(ObjectiveFunction,[-64 64; -64 64]); view(-15,150);
现在,我们可以运行 simulannealbnd
求解器来最小化我们的目标函数。
rng default % For reproducibility [x,fval,exitFlag,output] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The number of iterations was : %d\n', output.iterations);
The number of iterations was : 1095
fprintf('The number of function evaluations was : %d\n', output.funccount);
The number of function evaluations was : 1104
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 2.98211
请注意,当您运行此示例时,您的结果可能与上面显示的结果不同,因为模拟退火算法使用随机数来生成点。
添加可视化
simulannealbnd
可以通过“选项”参量接受一个或多个绘图函数。此功能对于在运行时可视化求解器的性能很有用。使用 optimoptions
选择绘图函数。该工具箱包含一组可供选择的绘图函数,或者您可以提供自己的自定义绘图函数。
要选择多个绘图函数,请通过 PlotFcn
函数设置 optimoptions
选项。对于此示例,我们选择 saplotbestf
,它绘制每次迭代的最佳函数值;saplottemperature
,它显示每次迭代中每个维度的当前温度;saplotf
,它显示当前函数值(请记住当前值不一定是最佳值);以及 saplotstopping
,它绘制每十次迭代满足的停止条件的百分比。
options = optimoptions(@simulannealbnd, ... 'PlotFcn',{@saplotbestf,@saplottemperature,@saplotf,@saplotstopping});
运行求解器。
simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
指定温度选项
模拟退火中使用的温度参数控制整体搜索结果。每个维度的温度用于限制该维度的搜索范围。该工具箱允许您指定初始温度以及在解过程中更新温度的方法。两个与温度相关的选项是 InitialTemperature
和 TemperatureFcn
。
指定初始温度
每个维度的默认初始温度设置为 100。如果您希望初始温度在不同维度上有所不同,那么您必须指定温度向量。当问题在每个维度上的缩放不同的时候,这可能是必要的。例如,
options = optimoptions(@simulannealbnd,'InitialTemperature',[300 50]);
InitialTemperature
可以设置为长度小于变量数量(维度)的向量;求解器通过取初始温度向量的最后一个元素将向量扩展为剩余维度。这里我们希望初始温度在所有维度上都相同,因此我们只需要指定单一温度。
options.InitialTemperature = 100;
指定温度函数
simulannealbnd
使用的默认温度函数称为 temperatureexp
。在 temperatureexp 调度中,任何给定步骤的温度都是前一步温度的 0.95 倍。这会导致温度一开始缓慢下降,但最终比其他方案更快地冷却。如果需要另一种方案,例如玻尔兹曼计划或“快速”计划退火,则可以分别使用 temperatureboltz
或 temperaturefast
。为了选择快速温度计划,我们可以更新之前创建的选项,直接更改 TemperatureFcn
。
options.TemperatureFcn = @temperaturefast;
指定再退火
再退火是退火过程的一部分。在接受了一定数量的新点之后,温度会升高到更高的值,希望重新开始搜索并摆脱局部极小值。过早进行重新退火可能无助于求解器识别最小值,因此相对较高的间隔是一个不错的选择。可以使用 ReannealInterval
选项设置重新退火发生的间隔。在这里,我们将默认的重新退火间隔减少到 50,因为该函数在许多区域似乎是平坦的,并且求解器可能会迅速卡住。
options.ReannealInterval = 50;
现在我们已经设置了新的温度选项,我们再次运行求解器。
[x,fval,exitFlag,output] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The number of iterations was : %d\n', output.iterations);
The number of iterations was : 1306
fprintf('The number of function evaluations was : %d\n', output.funccount);
The number of function evaluations was : 1321
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 16.4409
复现结果
simulannealbnd
是一种非确定性算法。这意味着在不改变任何设置的情况下多次运行求解器可能会产生不同的结果。这是因为 simulannealbnd
在生成后续点以及确定是否接受新点时利用了 MATLAB® 随机数生成器。每次生成随机数时,随机数生成器的状态都会发生变化。
为了看到这一点,两次运行 simulannealbnd
求解器得出以下结果:
[x,fval] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 1.99203
以及
[x,fval] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 10.7632
在前两次运行中,simulannealbnd
给出了不同的结果。
如果我们使用 simulannealbnd
返回的信息在求解器运行之间重置随机数生成器的状态,我们就可以重现我们的结果。simulannealbnd
返回在输出参量中调用 simulannealbnd
时随机数生成器的状态。此信息可用于重置状态。在这里,我们使用此输出信息重置运行之间的状态,以便接下来两次运行的结果相同。
[x,fval,exitFlag,output] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 20.1535
我们重置随机数生成器的状态。
strm = RandStream.getGlobalStream; strm.State = output.rngstate.State;
现在,让我们再次运行 simulannealbnd
。
[x,fval] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 20.1535
修改停止标准
simulannealbnd
使用六种不同的标准来确定何时停止求解器。simulannealbnd
在超过最大迭代次数或函数求值时停止;默认情况下,最大迭代次数设置为 Inf,最大函数计算次数为 3000*numberOfVariables
。simulannealbnd
跟踪 MaxStallIterations
迭代的函数值的平均变化。如果平均变化小于函数容差 FunctionTolerance
,则算法将停止。当目标函数值达到 ObjectiveLimit
时,求解器也会停止。最后,求解器将在运行 MaxTime
秒后停止。这里我们将 FunctionTolerance
设置为 1e-5。
options.FunctionTolerance = 1e-5;
运行 simulannealbnd
求解器。
[x,fval,exitFlag,output] = simulannealbnd(ObjectiveFunction,startingPoint,lb,ub,options);
simulannealbnd stopped because the change in best function value is less than options.FunctionTolerance.
fprintf('The number of iterations was : %d\n', output.iterations);
The number of iterations was : 1843
fprintf('The number of function evaluations was : %d\n', output.funccount);
The number of function evaluations was : 1864
fprintf('The best function value found was : %g\n', fval);
The best function value found was : 6.90334