Scipy优化中的SLSQP忽略了约束条件。

3
我希望使用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有什么问题? - sascha
就你的最终目标而言,0.1*x[1]*x[1] 的最小值也是该函数平方根的最小值。你真幸运! - Bill Bell
感谢大家的评论!@BillBell,这只是我正在处理的一个多元问题的虚拟简化 - 在那种情况下,不幸运气不是一个选项。 - Milán Janosov
@sascha,我的问题是我想执行一些操作(例如#return sqrt(0.1*x[0]*x[1])),这可能会在某些条件下导致数学错误。我希望使用约束来在优化过程中忽略这些情况,但显然,条件只适用于最终解决方案?我该如何解决这个问题? - Milán Janosov
我只是在讽刺。只要平方根将整个被优化的函数包围起来,就可以省略它了。结果将是相同的。而且你不需要投入任何约束条件来试图将函数限制在平方根的定义域内。 - Bill Bell
1个回答

3

在一般情况下,我们不知道您的整个任务,未能在所有步骤中强制执行约束条件(正如我们观察到的那样)!没有改变优化器,我们没有太多办法。即使找到一个合适的优化器可能也不容易。

对于你的情况,如果你的变量是非负的,这个方法就可以解决问题了!如果您在其他任务中可以使用这个方法,我们不知道。

现在有两种非负性的方法:

  • 不等式
  • 边界

使用边界时,会使用显式处理(就我所知),在优化过程中不会违反限制条件。

举个例子:

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.])

非常感谢您的回复 - 知道约束条件不是在所有步骤中都被执行是非常有用的。我也考虑过边界,但我也找不到解决方法。目标函数中我必须取平方根(以及对数)的术语是一个由6个变量组成的复杂非线性函数。根据scipy文档,边界只适用于我们正在优化的变量。我想到了一些类似于在f中捕获MathError异常并在返回之前跳过的方法,但这似乎很肤浅。 - Milán Janosov
@MilánJanosov 当然可以使用try catch来捕获这些异常,并输出一些值作为代理。但这需要对平滑性做出一定的假设,不过值得一试。 - sascha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接