Python 约束非线性优化

标签 python mathematical-optimization cvxpy

python 中约束非线性优化的推荐包是什么?

我要解决的具体问题是:

我有一个未知的X (Nx1),我有M (Nx1) u 向量和M (NxN) s 矩阵。

max [5th percentile of (ui_T*X), i in 1 to M]
st 
0<=X<=1 and
[95th percentile of (X_T*si*X), i in 1 to M]<= constant

当我开始解决这个问题时,我只有一个点估计 us 并且我能够用 cvxpy 解决上面的问题>。

我意识到,我没有对 us 进行一次估计,而是得到了整个值分布,所以我想更改我的目标函数,以便我可以使用整个分布。上面的问题描述是我尝试以有意义的方式包含该信息。

cvxpy 不能用来解决这个问题,我试过 scipy.optimize.anneal,但我似乎无法设置未知值的界限。我也看过 pulp,但它不允许非线性约束。

最佳答案

虽然 scipy.optimize.minimize 中的 SLSQP 算法很好,但它有很多限制。第一个是它是一个 QP 求解器,因此它适用于非常适合二次规划范式的方程。但是如果你有功能限制会发生什么?此外,scipy.optimize.minimize 不是全局优化器,因此您通常需要从非常接近最终结果的地方开始。

有一个受约束的非线性优化包(称为 mystic)几乎与 scipy.optimize 本身一样长 - 我建议它作为处理任何一般约束非线性优化的首选。

例如,如果我理解你的伪代码,你的问题看起来像这样:

import numpy as np

M = 10
N = 3
Q = 10
C = 10

# let's be lazy, and generate s and u randomly...
s = np.random.randint(-Q,Q, size=(M,N,N))
u = np.random.randint(-Q,Q, size=(M,N))

def percentile(p, x):
    x = np.sort(x)
    p = 0.01 * p * len(x)
    if int(p) != p:
        return x[int(np.floor(p))]
    p = int(p)
    return x[p:p+2].mean()

def objective(x, p=5): # inverted objective, to find the max
    return -1*percentile(p, [np.dot(np.atleast_2d(u[i]), x)[0] for i in range(0,M-1)])


def constraint(x, p=95, v=C): # 95%(xTsx) - v <= 0
    x = np.atleast_2d(x)
    return percentile(p, [np.dot(np.dot(x,s[i]),x.T)[0,0] for i in range(0,M-1)]) - v

bounds = [(0,1) for i in range(0,N)]

因此,要在 mystic 中处理您的问题,您只需指定边界和约束。

from mystic.penalty import quadratic_inequality
@quadratic_inequality(constraint, k=1e4)
def penalty(x):
  return 0.0

from mystic.solvers import diffev2
from mystic.monitors import VerboseMonitor
mon = VerboseMonitor(10)

result = diffev2(objective, x0=bounds, penalty=penalty, npop=10, gtol=200, \
                 disp=False, full_output=True, itermon=mon, maxiter=M*N*100)

print result[0]
print result[1]

结果看起来像这样:

Generation 0 has Chi-Squared: -0.434718
Generation 10 has Chi-Squared: -1.733787
Generation 20 has Chi-Squared: -1.859787
Generation 30 has Chi-Squared: -1.860533
Generation 40 has Chi-Squared: -1.860533
Generation 50 has Chi-Squared: -1.860533
Generation 60 has Chi-Squared: -1.860533
Generation 70 has Chi-Squared: -1.860533
Generation 80 has Chi-Squared: -1.860533
Generation 90 has Chi-Squared: -1.860533
Generation 100 has Chi-Squared: -1.860533
Generation 110 has Chi-Squared: -1.860533
Generation 120 has Chi-Squared: -1.860533
Generation 130 has Chi-Squared: -1.860533
Generation 140 has Chi-Squared: -1.860533
Generation 150 has Chi-Squared: -1.860533
Generation 160 has Chi-Squared: -1.860533
Generation 170 has Chi-Squared: -1.860533
Generation 180 has Chi-Squared: -1.860533
Generation 190 has Chi-Squared: -1.860533
Generation 200 has Chi-Squared: -1.860533
Generation 210 has Chi-Squared: -1.860533
STOP("ChangeOverGeneration with {'tolerance': 0.005, 'generations': 200}")
[-0.17207128  0.73183465 -0.28218955]
-1.86053344078

mystic 非常灵活,可以处理任何类型的约束(例如等式、不等式),包括符号和功能约束。 我在上面将约束指定为“惩罚”,这是传统方式,因为它们在违反约束时对目标应用惩罚。 mystic 还提供非线性核变换,它通过减少有效解的空间(即通过空间映射或核变换)来限制解空间。

例如,这里的 mystic 解决了一个问题,该问题破坏了许多 QP 求解器,因为约束不是约束矩阵的形式。它正在优化压力容器的设计。

"Pressure Vessel Design"

def objective(x):
    x0,x1,x2,x3 = x
    return 0.6224*x0*x2*x3 + 1.7781*x1*x2**2 + 3.1661*x0**2*x3 + 19.84*x0**2*x2

bounds = [(0,1e6)]*4
# with penalty='penalty' applied, solution is:
xs = [0.72759093, 0.35964857, 37.69901188, 240.0]
ys = 5804.3762083

from mystic.symbolic import generate_constraint, generate_solvers, simplify
from mystic.symbolic import generate_penalty, generate_conditions

equations = """
-x0 + 0.0193*x2 <= 0.0
-x1 + 0.00954*x2 <= 0.0
-pi*x2**2*x3 - (4/3.)*pi*x2**3 + 1296000.0 <= 0.0
x3 - 240.0 <= 0.0
"""
cf = generate_constraint(generate_solvers(simplify(equations)))
pf = generate_penalty(generate_conditions(equations), k=1e12)


if __name__ == '__main__':

    from mystic.solvers import diffev2
    from mystic.math import almostEqual
    from mystic.monitors import VerboseMonitor
    mon = VerboseMonitor(10)

    result = diffev2(objective, x0=bounds, bounds=bounds, constraints=cf, penalty=pf, \ 
                     npop=40, gtol=50, disp=False, full_output=True, itermon=mon)

    assert almostEqual(result[0], xs, rel=1e-2)
    assert almostEqual(result[1], ys, rel=1e-2)

在这里找到这个,大约有 100 个类似的例子:https://github.com/uqfoundation/mystic .

我是作者,所以我有点偏见。然而,偏差非常轻微。 mystic 既成熟又得到了很好的支持,在解决硬约束非线性优化问题方面的能力无与伦比。

关于Python 约束非线性优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21765794/

相关文章:

r - 使用 RGLPK 在 R 中进行梦幻足球线性规划

python - ArithmeticError 导致 cvxpy 出现 "Rank(A) < p or Rank([G; A]) < n"错误

least-squares - CVXPY 在二次规划优化问题上返回不可行/不准确

Python单例/对象实例化

python - 您可以继续在运行时错误后运行代码吗?

python - 在 Python 3 中实现 Pythonic "i, j"风格的 for 循环?

python-3.x - 在 CVXPY 中广播

python - 如何使用Python的ElementTree获取child的child

algorithm - 公式,圆的周长与矩形的角相交

algorithm - 贪婪分配算法的复杂性