【问题标题】:Scipy minimize constraint: One of two values needs to be zeroScipy最小化约束:两个值之一需要为零
【发布时间】:2020-06-30 17:29:34
【问题描述】:

我想最小化以下功能:

def objective(B, P, O):
    return - (sum([(p * o - 1) * b for p, o, b in zip(P, O, B)]) /\
    math.sqrt(sum([(1-p) * p * b**2 * o**2 for p, o, b in zip(P, O, B)])))

sol = minimize(objective, x0=bets, args=(P,O,), method='SLSQP', bounds=bnds, constraints=constr)

我想将以下约束添加到B = [1,2,3,4,5,6,....](B 始终具有偶数长度):

对于列表 (1,2), (3,4), (5,6)... (b1,b2) 中的每一对,在优化结束时,这两个值中的一个应该变为 0。 所以从逻辑的角度来看:b1 + b2 = b1 xor b1 + b2 = b2

如果我把它写成一个约束,它看起来像这样:

def constb(B):
    for i in range(0, len(B), 2):
        b1, b2 = B[i:i+2]
        if b1 == 0.0:
            return b2 + b1 - b2
        elif b2 == 0.0:
            return b1 + b2 - b1
        else: 
            return 42 

约束如下所示:

constr = [{'type': 'ineq', 'fun': lambda x: sum(x) - 100},
          {'type': 'eq', 'fun': constb}]

但它不起作用,因为我的配对最后看起来像这样(我的边界是每个值的 (0,20)):

20.0 20.0
20.0 20.0
20.0 20.0
20.0 20.0
20.0 20.0

看起来算法在约束中默认为else 语句。我尝试将 B 初始化为 0,但随后出现 MathError,因为不能除以 0。

有没有办法实现这个?

【问题讨论】:

    标签: python python-3.x scipy scipy-optimize-minimize


    【解决方案1】:

    没有。这一般是不可能的。

    答: 这些约束就像析取或基数约束一样,是导致优化问题 NP-hard 的典型事物。

    乙: scipy.minimize 中的求解器基于一些强有力的假设,并通过设计提供多项式时间的局部最优值。您忽略的核心假设是:

    • 约束 + 目标是两次可微的
      • 简单的规则:如果你在你的 obj/constraints 中使用 if-else 的东西,它可能不会有两倍的差异!

    A 和 B 结合起来应该清楚地表明你有点迷失了。

    另请参阅斯坦福Convex-Cardinality Problems 上的相关介绍,其中概述了问题。 (请记住,这个主题更笼统,并且仅与您的问题相关;对于您的示例,关于问题的析取观点更加专业!)

    要么放弃精确性/追求近似值,然后像机器学习和 co 中那样做那些 l1-norm 技巧(请参阅lasso-optimization)。这对调整 = 超参数选择很重要(并且在 scipy 中实现也很烦人 -> 记住 => 两次差异 => 你不能使用 np.linalg.norm(x, 1) 但需要重新制定,这也使问题变得更加复杂对于 scipy 中的求解器)

    或者你放弃多项式时间算法并去混合整数数学优化。这不是 scipy 的一部分。

    然后,候选方法是:

    • 混合整数规划(线性)
      • 例如CoinOR Cbc
    • 各种凸整数规划
      • QP、SOCP、SDP 等。
    • 一般非线性混合整数规划
      • 例如CoinOR Bonmin(本地)/ Couenne(全球)

    我懒得分析你的目标,但似乎前者不在讨论范围内,因为你有非线性部分(平方根)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-03
      • 2016-05-27
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      相关资源
      最近更新 更多