如何在中定义不连续边界SciPy.optimize.minimize公司

2024-04-30 05:23:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我在用scipy.optimize.minimize.最小化“SLSQP”方法,根据文件:

bounds : sequence, optional

Bounds for variables (only for L-BFGS-B, TNC and SLSQP). (min, max) pairs for >each element in x, defining the bounds on that parameter. Use None for one of min >or max when there is no bound in that direction.

我想知道,对于变量x(0,15)&;(30,50);(x在0到15之间,在30到50之间)是否可以定义一个不连续的边界

或者有其他更好的方法来实现这个目标吗?在

提前谢谢你们!在


Tags: 文件方法inforthatscipyminoptional
2条回答

x is between 0 and 15 and between 30 and 50

这将使模型不可行。没有这样的x。你可能是说:

x在0和15之间在30和50之间

这是非凸的,因此标准局部解算器对此有困难。它通常使用额外的二进制变量建模:

30 δ ≤ x ≤ 15(1-δ) + 50 δ  
δ ∈ {0,1}

当然,这假设您可以处理二进制变量(SLSQP不能)。具有二元变量和非线性约束(或目标函数)的模型称为MINLP模型(混合整数非线性规划)。这类模型的求解器是现成的。在

其他一些可行的方法:

  • 把问题解决两次。一次使用0 ≤ x ≤ 15,一次使用30 ≤ x ≤ 50。然后选择最好的解决方案。在
  • 使用scipy.optimize.basinhopping全局解算器帮助您摆脱局部最优。这不是一个严格的算法(没有保证),但它可以帮助。在

一些通常不起作用的方法:

  • 使用连续变量δ ∈ [0,1]并添加约束δ(1-δ)=0,而不是二进制变量δ ∈ {0,1}。通常这会让你陷入困境。在
  • 另一个答案是多项式方法:这也是非凸的,不太适合SLSQP。你会陷入局部最优。在
  • 如果x ∈ [15,30],则向目标添加惩罚。局部解算器也不适用。在

下面是一个实现basinhopping方法的尝试described by Erwin Kalvelagen。在

首先,构造一个根在0、15、30和50的多项式 在所需区域为正:

In [123]: x = np.linspace(-1, 51, 100)

In [124]: plt.plot(x,-(x-0)*(x-15)*(x-30)*(x-50))
Out[124]: [<matplotlib.lines.Line2D at 0x7fa01d65b748>]

In [125]: plt.axhline(color='red')
Out[145]: <matplotlib.lines.Line2D at 0x7fa01d6620b8>

In [146]: plt.show()

enter image description here

现在可以使用该多项式作为约束:

^{pr2}$

收益率

 message: 'Optimization terminated successfully.'
    nfev: 13
     nit: 4
    njev: 4
  status: 0
 success: True
       x: array([15.])
                    message: ['requested number of basinhopping iterations completed successfully']
      minimization_failures: 0
                       nfev: 178
                        nit: 10
                       njev: 56
                          x: array([15.])

注意,最初的猜测是在40处,但是{}设法在x = 15处找到另一个非连续区间的最小值。 使用与两个间隔之间的距离顺序相同的步长对于让basinhopping有机会从两个间隔进行采样非常重要。在

如果没有basinhopping,optimize.minimize使用带有非凸约束的SLSQP可能无法从所有允许的区间进行采样。例如

import scipy.optimize as optimize

cons = ({'type': 'ineq', 'fun': lambda x: -(x-0)*(x-15)*(x-30)*(x-50)}, )

def f(x):
    return (x-20)**2

res = optimize.minimize(
    f, [40], method='SLSQP', constraints=cons)
print(res.x)
# [30.]

res = optimize.minimize(
    f, [5], method='SLSQP', constraints=cons)
print(res.x)
# [15.]

显示您必须运行optimize.minimize两次,并在每个间隔内进行猜测 为了找到真正的最小值。在

相关问题 更多 >