我希望学生们在作业中解决二次规划问题时不需要安装额外的软件,如cvxopt等。是否有仅依赖于NumPy/SciPy的Python实现可用?
我希望学生们在作业中解决二次规划问题时不需要安装额外的软件,如cvxopt等。是否有仅依赖于NumPy/SciPy的Python实现可用?
我对二次规划不是很熟悉,但我认为你可以使用scipy.optimize
的约束最小化算法来解决这类问题。以下是一个示例:
import numpy as np
from scipy import optimize
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
# minimize
# F = x[1]^2 + 4x[2]^2 -32x[2] + 64
# subject to:
# x[1] + x[2] <= 7
# -x[1] + 2x[2] <= 4
# x[1] >= 0
# x[2] >= 0
# x[2] <= 4
# in matrix notation:
# F = (1/2)*x.T*H*x + c*x + c0
# subject to:
# Ax <= b
# where:
# H = [[2, 0],
# [0, 8]]
# c = [0, -32]
# c0 = 64
# A = [[ 1, 1],
# [-1, 2],
# [-1, 0],
# [0, -1],
# [0, 1]]
# b = [7,4,0,0,4]
H = np.array([[2., 0.],
[0., 8.]])
c = np.array([0, -32])
c0 = 64
A = np.array([[ 1., 1.],
[-1., 2.],
[-1., 0.],
[0., -1.],
[0., 1.]])
b = np.array([7., 4., 0., 0., 4.])
x0 = np.random.randn(2)
def loss(x, sign=1.):
return sign * (0.5 * np.dot(x.T, np.dot(H, x))+ np.dot(c, x) + c0)
def jac(x, sign=1.):
return sign * (np.dot(x.T, H) + c)
cons = {'type':'ineq',
'fun':lambda x: b - np.dot(A,x),
'jac':lambda x: -A}
opt = {'disp':False}
def solve():
res_cons = optimize.minimize(loss, x0, jac=jac,constraints=cons,
method='SLSQP', options=opt)
res_uncons = optimize.minimize(loss, x0, jac=jac, method='SLSQP',
options=opt)
print '\nConstrained:'
print res_cons
print '\nUnconstrained:'
print res_uncons
x1, x2 = res_cons['x']
f = res_cons['fun']
x1_unc, x2_unc = res_uncons['x']
f_unc = res_uncons['fun']
# plotting
xgrid = np.mgrid[-2:4:0.1, 1.5:5.5:0.1]
xvec = xgrid.reshape(2, -1).T
F = np.vstack([loss(xi) for xi in xvec]).reshape(xgrid.shape[1:])
ax = plt.axes(projection='3d')
ax.hold(True)
ax.plot_surface(xgrid[0], xgrid[1], F, rstride=1, cstride=1,
cmap=plt.cm.jet, shade=True, alpha=0.9, linewidth=0)
ax.plot3D([x1], [x2], [f], 'og', mec='w', label='Constrained minimum')
ax.plot3D([x1_unc], [x2_unc], [f_unc], 'oy', mec='w',
label='Unconstrained minimum')
ax.legend(fancybox=True, numpoints=1)
ax.set_xlabel('x1')
ax.set_ylabel('x2')
ax.set_zlabel('F')
输出:
Constrained:
status: 0
success: True
njev: 4
nfev: 4
fun: 7.9999999999997584
x: array([ 2., 3.])
message: 'Optimization terminated successfully.'
jac: array([ 4., -8., 0.])
nit: 4
Unconstrained:
status: 0
success: True
njev: 3
nfev: 5
fun: 0.0
x: array([ -2.66453526e-15, 4.00000000e+00])
message: 'Optimization terminated successfully.'
jac: array([ -5.32907052e-15, -3.55271368e-15, 0.00000000e+00])
nit: 3
scipy.optimize
教程/文档(https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html,https://docs.scipy.org/doc/scipy/reference/optimize.html),scipy-lectures(https://www.scipy-lectures.org/advanced/mathematical_optimization/#practical-guide-to-optimization-with-scipy)。 - ximiki可能有点晚了,但我发现 CVXOPT
- http://cvxopt.org/ - 是常用的免费Python库,用于二次规划
。然而,安装并不容易,因为它需要安装其他依赖项。
pip install cvxopt
安装 cvxopt
没有任何问题。 pip
会搞定一切。而且,我已经在几台机器上安装了 cvxopt
。当然,你需要安装编译器,但这也很简单,如果您正在使用 scipy
,则很可能已经安装好了。如果有帮助的话,我使用 Anaconda 作为 Python 分发工具(完全免费),安装 Anaconda 也很简单。无需管理员权限,也没有任何需要配置的内容。只需下载、安装即可使用。 - Amelio Vazquez-Reina这个qpsolvers包似乎也符合要求。它只依赖于NumPy,可以通过pip install qpsolvers
安装。然后,你可以这样做:
from numpy import array, dot
from qpsolvers import solve_qp
M = array([[1., 2., 0.], [-8., 3., 2.], [0., 1., 1.]])
P = dot(M.T, M) # quick way to build a symmetric matrix
q = dot(array([3., 2., 3.]), M).reshape((3,))
G = array([[1., 2., 1.], [2., 0., 1.], [-1., 2., -1.]])
h = array([3., 2., -2.]).reshape((3,))
# min. 1/2 x^T P x + q^T x with G x <= h
print "QP solution:", solve_qp(P, q, G, h)
solver
关键字参数,例如solver='cvxopt'
或solver='osqp'
。qpsolvers
只是其他二次规划包(如cvxopt
)的包装器,它需要编译器进行安装,并且不符合所需的纯Python(+Numpy/Scipy)要求。 - divenex"""
Maximize: f = 2*x[0]*x[1] + 2*x[0] - x[0]**2 - 2*x[1]**2
Subject to: -2*x[0] + 2*x[1] <= -2
2*x[0] - 4*x[1] <= 0
x[0]**3 -x[1] == 0
where: 0 <= x[0] <= inf
1 <= x[1] <= inf
"""
import numpy as np
import mystic.symbolic as ms
import mystic.solvers as my
import mystic.math as mm
# generate constraints and penalty for a nonlinear system of equations
ieqn = '''
-2*x0 + 2*x1 <= -2
2*x0 - 4*x1 <= 0'''
eqn = '''
x0**3 - x1 == 0'''
cons = ms.generate_constraint(ms.generate_solvers(ms.simplify(eqn,target='x1')))
pens = ms.generate_penalty(ms.generate_conditions(ieqn), k=1e3)
bounds = [(0., None), (1., None)]
# get the objective
def objective(x, sign=1):
x = np.asarray(x)
return sign * (2*x[0]*x[1] + 2*x[0] - x[0]**2 - 2*x[1]**2)
# solve
x0 = np.random.rand(2)
sol = my.fmin_powell(objective, x0, constraint=cons, penalty=pens, disp=True,
bounds=bounds, gtol=3, ftol=1e-6, full_output=True,
args=(-1,))
print 'x* = %s; f(x*) = %s' % (sol[0], -sol[1])
mystic
可以对任何给定的优化器普遍应用LP、QP和高阶等式和不等式约束,而不仅仅是一个特殊的QP求解器。其次,mystic
能够处理符号数学,因此定义/输入约束的便利性比使用函数的矩阵和导数要好一些。mystic
依赖于 numpy
,如果已安装,则将使用 scipy
(但是,scipy
不是必需的)。mystic
利用 sympy
来处理符号约束,但这在一般情况下并不是必需的优化工具。Optimization terminated successfully.
Current function value: -2.000000
Iterations: 3
Function evaluations: 103
x* = [ 2. 1.]; f(x*) = 2.0
获取 mystic
:在这里https://github.com/uqfoundation
numpy
/scipy
的QP问题的东西...而且,mystic
中的求解器基本上只有一个numpy
依赖项(请注意没有scipy
依赖项!)。从投票数可以看出,@ali_m有一个更直接的解决方案(即使用scipy
)——我知道这一点。我的观点是,mystic
可以解决QP问题以及非线性问题...所以,值得一提。 - Mike McKernsmystic
不包括这样的 QP 求解器。实际上,您的通用优化器 mystic.fmin_powell
是您的软件包中包含的 Scipy
代码的副本。我建议直接调用 Scipy
。 - divenexfmin_powell
代码确实是从scipy.optimize
派生出来的,但它已经被修改为接受任意硬性和软性约束(因此,如果需要,它可以在有效地使其成为QP、LP或MIP求解器的空间中执行)。如果创建硬性QP约束,则将约束应用于的任何神秘求解器都只会在QP空间中寻找解决方案。这就是我发帖的全部意图,也是mystic
的主要特点之一。如果您对mystic
的工作原理有疑问,请随时直接与我联系。 - Mike McKernsmystic
中约束条件的工作方式,它们本质上是坐标变换,这可能会对你有所帮助。 - Mike McKerns
numpy
/scipy
而且不需要额外软件(如 cvxopt)的 Python 实现 QP 求解器的问题,有一个答案推荐使用cvxopt
,而另一个答案(即被采纳的答案)推荐的实际上是绑定到另一种语言的未维护的 Python 库(即非 Python 实现)。 - Mike McKerns