我正在尝试使用shgo算法运行模拟(黑箱问题)并最大化模拟的输出参数。目标函数运行并评估仿真。有5个变量作为输入。我需要定义边界和约束,这需要限制模拟的几何形状。因为这是一个有很多变量的问题,我需要一个全局优化器,它接受边界和约束。因此,shgo似乎非常合适。然而,我正在努力使优化器算法接受我的边界和约束并收敛。
这是我的优化代码:
bnds = [(50*1e-9,500*1e-9), (50*1e-9,500*1e-9), (1,20), (20*1e-9,80*1e-9), (250*1e-9,800*1e-9)]
def constraint1(x):
return x[4]-50*1e-9-2*x[0] # x[4]<=2*x[0]-50nm(threshold)
def constraint2(x):
return x[1]-x[3]-20*1e-9 # x[1]-x[3]>=20nm(threshold)
def constraint3(x):
return x[0]-(x[1]/2)*(2.978/x[2])-20*1e-9
cons = ({'type': 'ineq', 'fun': constraint1},
{'type': 'ineq', 'fun': constraint2},
{'type': 'ineq', 'fun': constraint3})
minimizer_kwargs = {'method':'COBYLA',
'bounds': bnds,
'constraints':cons}
opts = {'disp':True}
res_shgo = shgo(objective,
bounds=bnds,
constraints=cons,
sampling_method='sobol',
minimizer_kwargs=minimizer_kwargs,
options=opts)
全局算法运行33轮以完成评估并启动最小化池:
Evaluations completed.
Search for minimiser pool
--- Starting minimization at [3.3828125e-07 4.6484375e-07 1.1984375e+01 6.7812500e-08 7.5703125e-07]...
现在,在最小化池中使用COBYLA算法进行最小化。然而,在几轮之后,它超出了结果的边界,即输入参数导致我的模拟崩溃。
我还尝试了最小化池的'L-BFGS-B'算法。
minimizer_kwargs = {'method':'L-BFGS-B'}
算法收敛于以下语句:
lres = fun: -20.247226776119533
hess_inv: <5x5 LbfgsInvHessProduct with dtype=float64>
jac: array([ 1.70730429e+09, 1.22968297e+09, 0.00000000e+00, -1.82566323e+09,
1.83071706e+09])
message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
nfev: 6
nit: 0
njev: 1
status: 0
success: True
x: array([2.43359375e-07, 2.99609375e-07, 1.48046875e+01, 7.01562500e-08,
6.23828125e-07])
Minimiser pool = SHGO.X_min = []
Successfully completed construction of complex.
结果不是全局最小值。
如何使用COBYLA使shgo成功终止?
我认为中间(不可行的)解决方案可能不服从边界。(其他NLP求解器实际上从来不会在没有边界的情况下调用函数求值;这是一个更好的方法。这意味着我们可以使用边界来防止错误的计算。)如果您有这些越界函数求值,您可以尝试以下两种方法:
- 在调用模拟器之前将变量投影到它们的边界上。
- 如果不遵守边界,立即返回一个大值,甚至不调用模拟器。
感谢您的评论。
我在目标函数中添加了这几行代码,以避免调用模拟器。
def objective(x):
global iteration
if all(lower_bound <= variable <= upper_bound for variable, (lower_bound, upper_bound) in zip(x, bnds)):
target_value = run_simulation(x)
else:
target_value = ?
return target_value
我不确定在else-命令中传递给优化算法的值,这不会干扰优化器的结果。"np。Nan '或'0'不能工作。
Ok…我解决了这个问题。
问题在于边界的值非常接近于零(10^-9)。因此,我删除了10^-9,并简单地将其添加到脚本的其他地方。
然而,现在下一个问题又出现了:
该算法在开始局部最小化之前进行8-10次迭代的粗略全局。我发现这还不够,因为有5个输入参数。此外,局部最小化例程在20多次迭代中保持在同一位置"挖掘",每次只调整输入参数小于0,5。
我的目标是增加全局迭代的次数,以更好地覆盖参数范围,从而减少局部迭代的次数,在局部迭代中,输出只发生很小的、因此可以忽略的变化。否则,增加局部最小化轮的步长。
我尝试了shgo算法的不同输入变量,如'n', 'iters', 'maxfev', 'maxev'和'f_tol'。没有一个显示出期望的结果。