【问题标题】:Scipy optimization with SLSQP disregards constraints使用 SLSQP 进行 Scipy 优化忽略约束
【发布时间】:2017-12-06 20:12:30
【问题描述】:

我想使用 scipy 添加 x[0] - x[1] > 0 的约束来优化以下公式。在目标函数中打印此表达式时,它也会给出负值,而优化成功终止。最终目标是最小化由于数学错误而失败的 sqrt(0.1*x[0]*x[1]) 。

import numpy as np
from scipy.optimize import minimize


def f(x):

    print x[0] - x[1]
    #return sqrt(0.1*x[0]*x[1])
    return 0.1*x[0]*x[1]

def ineq_constraint(x):

    return x[0] - x[1]


con = {'type': 'ineq', 'fun': ineq_constraint}
x0 = [1, 1]
res = minimize(f, x0, method='SLSQP', constraints=con)

print res

还有输出:

0.0
0.0
1.49011611938e-08
-1.49011611938e-08
0.0
0.0
1.49011611938e-08
-1.49011611938e-08
0.0
0.0
1.49011611938e-08
-1.49011611938e-08
4.65661176285e-10
4.65661176285e-10
1.53668223701e-08
-1.44355000176e-08
     fun: 1.7509862319755833e-18
     jac: array([  3.95812066e-10,   4.42378184e-10,   0.00000000e+00])
 message: 'Optimization terminated successfully.'
    nfev: 16
     nit: 4
    njev: 4
  status: 0
 success: True
       x: array([  4.42378184e-09,   3.95812066e-09])

【问题讨论】:

  • 在您的解决方案x[0] - x[1] >= 0 中,有什么问题?
  • 就您的最终目标而言,最小值 0.1*x[1]*x[1] 也是此函数平方根的最小值。你走运了!
  • 感谢大家的cmets! @BillBell,这是我正在研究的多变量问题的虚拟简化 - 在这种情况下,不幸的是,运气不是一种选择。
  • @sascha,我的问题是我想做一些操作(例如 #return sqrt(0.1*x[0]*x[1]) 中的 sqrt,这可能会在某些情况下导致数学错误条件。我想在优化过程中使用约束来忽略这些情况,但显然,条件只适用于最终解决方案?我该如何解决?
  • 我是在讽刺。只需省略平方根,只要它包含正在优化的整个函数即可。结果将是相同的。而且您不需要任何约束,以尝试将函数保持在平方根的域内。

标签: python optimization scipy constraints


【解决方案1】:

在一般情况下,我们不了解您的整个任务,并非在所有步骤中都强制执行约束(如观察到的那样)!不改变优化器没有什么可做的。甚至找到合适的优化器也可能并不容易。

对于您的情况,如果您的变量为非负数,它会起作用!如果您可以在其他任务中使用它,我们不知道。

现在有两种非否定性方法:

  • 不等式
  • 界限

使用边界,使用显式处理(据我所知)并且在优化期间不会违反这些。

例子:

import numpy as np
from scipy.optimize import minimize
from math import sqrt

def f(x):
    print(x)
    return sqrt(0.1*x[0]*x[1])

def ineq_constraint(x):
    return x[0] - x[1]

con = {'type': 'ineq', 'fun': ineq_constraint}

x0 = [1, 1]
res = minimize(f, x0, method='SLSQP', constraints=con, bounds=[(0, None) for i in range(len(x0))])
print(res)

输出:

[1. 1.]
[1. 1.]
[1.00000001 1.        ]
[1.         1.00000001]
[0.84188612 0.84188612]
[0.84188612 0.84188612]
[0.84188613 0.84188612]
[0.84188612 0.84188613]
[0.05131671 0.05131669]
[0.05131671 0.05131669]
[0.05131672 0.05131669]
[0.05131671 0.0513167 ]
[0. 0.]
[0. 0.]
[1.49011612e-08 0.00000000e+00]
[0.00000000e+00 1.49011612e-08]
     fun: 0.0
     jac: array([0., 0.])
 message: 'Optimization terminated successfully.'
    nfev: 16
     nit: 4
    njev: 4
  status: 0
 success: True
       x: array([0., 0.])

【讨论】:

  • 非常感谢您的回复 - 了解并非在所有步骤中都强制执行约束是非常有用的。我也考虑过界限,但我也找不到出路。我必须在目标函数中使用 sqrt(以及 log)的术语是 6 个变量的复杂非线性函数。根据 scipy 文档,界限仅适用于我们正在优化的变量。我想到了一些方法,比如在 f 中的 MathError 情况下捕获异常并在返回之前通过,但这似乎很肤浅。
  • @MilánJanosov 当然,您可以尝试捕获这些并输出一些值作为代理。但这需要在一定程度上考虑平滑假设。但值得一试。
猜你喜欢
  • 2016-02-04
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 2015-06-09
  • 1970-01-01
  • 2014-07-13
  • 2022-09-17
相关资源
最近更新 更多