是否有任何二次规划函数可以同时具有下限和上限 - Python
Is there any quadratic programming function that can have both lower and upper bounds - Python
平时我都是用GNU Octave来求解二次规划问题
我解决了像
这样的问题
x = 1/2x'Qx + c'x
受制于
A*x <= b
lb <= x <= ub
其中 lb
和 ub
是下限和上限,例如 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
您可以根据 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
的更多信息,请参阅docs。
如果您需要像 quadprog
这样的通用二次规划求解器,我建议您使用 Convex Optimization 上的开源软件 cvxopt as noted in one of the comments. This is robust and really state-of-the-art. The main contributor is a major expert in the field and the co-author of a classic book。
您要使用的函数是cvxopt.solvers.qp。下面是一个在 Numpy
中使用它的简单包装器,例如 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 distribution 中并且可以用 conda install cvxopt
安装(甚至在 Windows 上)。
相反,如果您对带边界的线性最小二乘优化的更具体情况感兴趣,它是一般二次规划的子集,即
Minimize || A @ x - b ||
subject to lb <= x <= ub
那么Scipy
就有了特定的函数scipy.optimize.lsq_linear(A, b, bounds)
.
请注意,接受的答案是一种非常低效的方法,不应推荐使用。它没有利用要优化的函数是二次函数这一关键事实,而是使用通用的非线性优化程序,甚至没有指定解析梯度。
平时我都是用GNU Octave来求解二次规划问题
我解决了像
这样的问题x = 1/2x'Qx + c'x
受制于
A*x <= b
lb <= x <= ub
其中 lb
和 ub
是下限和上限,例如 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
您可以根据 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
的更多信息,请参阅docs。
如果您需要像 quadprog
这样的通用二次规划求解器,我建议您使用 Convex Optimization 上的开源软件 cvxopt as noted in one of the comments. This is robust and really state-of-the-art. The main contributor is a major expert in the field and the co-author of a classic book。
您要使用的函数是cvxopt.solvers.qp。下面是一个在 Numpy
中使用它的简单包装器,例如 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 distribution 中并且可以用 conda install cvxopt
安装(甚至在 Windows 上)。
相反,如果您对带边界的线性最小二乘优化的更具体情况感兴趣,它是一般二次规划的子集,即
Minimize || A @ x - b ||
subject to lb <= x <= ub
那么Scipy
就有了特定的函数scipy.optimize.lsq_linear(A, b, bounds)
.
请注意,接受的答案是一种非常低效的方法,不应推荐使用。它没有利用要优化的函数是二次函数这一关键事实,而是使用通用的非线性优化程序,甚至没有指定解析梯度。