6

通常我一直在使用GNU Octave来解决二次规划问题。

我解决的问题像

x = 1/2x'Qx + c'x

受制于

A*x <= b
lb <= x <= ub

其中lbub是下限和上限,例如限制x

当我解决时,我的 Octave 代码看起来像这样。只需一条简单的线

U = quadprog(Q, c, A, b, [], [], lb, ub);

方括号[]是空的,因为我不需要等式约束

Aeq*x = beq,

所以我的问题是:Python 中是否有一个易于使用的二次求解器来解决问题

x = 1/2x'Qx + c'x

受制于

A*x <= b
lb <= x <= ub

或受制于

b_lb <= A*x <= b_ub
lb <= x <= ub
4

2 回答 2

5

您可以编写自己的基于求解器的求解器scipy.optimize,这里有一个关于如何编写自定义 python 代码的小示例quadprog()

# python3
import numpy as np
from scipy import optimize

class quadprog(object):

    def __init__(self, H, f, A, b, x0, lb, ub):
        self.H    = H
        self.f    = f
        self.A    = A
        self.b    = b
        self.x0   = x0
        self.bnds = tuple([(lb, ub) for x in x0])
        # call solver
        self.result = self.solver()

    def objective_function(self, x):
        return 0.5*np.dot(np.dot(x.T, self.H), x) + np.dot(self.f.T, x)

    def solver(self):
        cons = ({'type': 'ineq', 'fun': lambda x: self.b - np.dot(self.A, x)})
        optimum = optimize.minimize(self.objective_function, 
                                    x0          = self.x0.T,
                                    bounds      = self.bnds,
                                    constraints = cons, 
                                    tol         = 10**-3)
        return optimum

以下是如何使用它,使用matlab-quadprog中提供的第一个示例中的相同变量:

# init vars
H  = np.array([[ 1, -1],
               [-1,  2]])

f  = np.array([-2, -6]).T

A  = np.array([[ 1, 1],
               [-1, 2],
               [ 2, 1]])

b  = np.array([2, 2, 3]).T
x0 = np.array([1, 2])
lb = 0
ub = 2

# call custom quadprog
quadprog  = quadprog(H, f, A, b, x0, lb, ub)
print(quadprog.result)

这个简短片段的输出是:

     fun: -8.222222222222083
     jac: array([-2.66666675, -4.        ])
 message: 'Optimization terminated successfully.'
    nfev: 8
     nit: 2
    njev: 2
  status: 0
 success: True
       x: array([0.66666667, 1.33333333])

有关如何使用的更多信息,scipy.optimize.minimize请参阅文档

于 2019-05-04T17:05:56.397 回答
2

如果您需要一个通用的二次规划求解器quadprog,我建议您使用其中一条评论中提到的开源软件cvxopt。这是强大且真正最先进的。主要贡献者是该领域的主要专家,也是一本关于凸优化的经典书籍的合著者。

您要使用的函数是cvxopt.solvers.qpNumpy下面是一个简单的包装器来使用它quadprog。请注意,边界可以作为不等式约束的特例包含在内。

import numpy as np
from cvxopt import matrix, solvers

def quadprog(P, q, G=None, h=None, A=None, b=None, options=None):
     """
    Quadratic programming problem with both linear equalities and inequalities

        Minimize      0.5 * x @ P @ x + q @ x
        Subject to    G @ x <= h
        and           A @ x = b
    """
    P, q = matrix(P), matrix(q)

    if G is not None:
        G, h = matrix(G), matrix(h)

    if A is not None:
        A, b = matrix(A), matrix(b)

    sol = solvers.qp(A, b, G, h, A, b, options=options)

    return np.array(sol['x']).ravel()

cvxopt过去很难安装,但现在也包含在Anaconda 发行版中,并且可以使用conda install cvxopt.

相反,如果您对带边界的线性最小二乘优化的更具体情况感兴趣,它是一般二次规划的子集,即

Minimize || A @ x - b ||
subject to lb <= x <= ub

然后Scipy就有了特定的功能scipy.optimize.lsq_linear(A, b, bounds)

请注意,接受的答案是一种非常低效的方法,不应推荐。它没有利用您要优化的函数是二次的这一关键事实,而是使用通用的非线性优化程序,甚至没有指定解析梯度。

于 2019-12-11T13:29:58.023 回答