Python 仅依赖于NumPy/SciPy的二次规划(QP)解算器?

Python 仅依赖于NumPy/SciPy的二次规划(QP)解算器?,python,numpy,scipy,mathematical-optimization,Python,Numpy,Scipy,Mathematical Optimization,我希望学生在作业中解决二次规划,而不必安装额外的软件,如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 Ax

我希望学生在作业中解决二次规划,而不必安装额外的软件,如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')

我遇到了一个很好的解决方案,想把它推出去。NICTA的ELEFANT机器学习工具包中有一个LOQO的python实现(截至本文)。看看optimization.intpointsolver。这是Alex Smola编写的代码,我使用了同一代码的C版本并取得了巨大成功。

这可能是一个迟来的答案,但我发现
CVXOPT
-是用于
二次规划的常用免费python库。但是,它不容易安装,因为它需要安装其他依赖项

mystic
提供了非线性/非凸优化算法的纯python实现,具有高级约束功能,通常仅在QP解算器中才能找到
mystic
实际上提供了比大多数QP解算器更强大的约束。但是,如果您正在寻找优化算法的速度,那么以下内容不适合您
mystic不慢,但它是纯python,而不是python绑定到C。如果您正在非线性求解器中寻找灵活性和QP约束功能,那么您可能会感兴趣

"""
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:

这个包裹似乎也很合身。它只依赖于NumPy,可以通过
pip install qpsolver
安装。然后,您可以执行以下操作:

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)
来自numpy导入数组,点
从QPSolver导入解算\u qp
M=数组([[1,2,0.],[-8,3,2.],[0,1,1.]))
P=dot(M.T,M)#构建对称矩阵的快速方法
q=点(数组([3,2,3]),M)。重塑((3,))
G=数组([[1,2,1.],[2,0,1.],[-1,2.,-1.]))
h=数组([3,2.,-2.])。重塑((3,))

#最小1/2x^tpx+q^tx和gx如果你能提供一些关于二次规划的链接,也许还有一两个例子,这将允许更多的人回答这个问题。请更新您的问题,因为我不太确定QP是什么意思,我可能知道如何编写您的程序,尽管我不知道它需要什么。非常感谢。对不起,没有澄清。QP是一个特殊的线性代数问题,请参见Wikipedia()。我觉得奇怪的是,一个问题要求一个python实现的QP解算器,它只依赖于
numpy
/
scipy
,不需要像cvxopt这样的附加软件…有一个答案推荐
cvxopt
,还有另一个答案(公认的答案)这建议将本质上未维护的python绑定推荐给另一种语言(即非python实现),我怀疑这是否非常有效。我认为LOQO的实现:二次规划的内点代码()会更快。你需要学生解决的问题有多难?SLSQP在大约1.33毫秒的时间内解决了我的示例(承认相当简单)。它还可以处理边界、不等式和等式约束的任意组合。如果你一心想使用针对QP优化的特定解算器,那么你可能需要(a)让你的学生安装额外的依赖项,或者(B)自己编写。谢谢你的后续跟进。学生应该使用它来解决支持向量机问题,并将其与他们应该实现的更有效的算法进行比较。这是一个大约100个变量的凸问题。我可能会实现LOQO,只是觉得我不可能是第一个。值得在约束定义中添加“jac”:(lambda x:-A),以使解算器更健壮。我试图从头开始实现一些基本的机器学习算法。SVM在待办事项清单上,但我没有信心把它拿出来。在阅读了你的答案之后,我成功地编写了一个我自己的svm(),它的工作原理与预期的一样。我真的非常感谢你的回答,非常感谢。我不相信这个项目是积极的。下载链接被破坏了,但是这个链接工作:在项目中有一个C++分支,但是我不相信它是活跃的。这个答案中的链接被破坏了,建议的软件不是纯Python(+Nuppy/Spyy),正如你所描述的,安装并不容易:-)谢谢你的建议,但我想我会先尝试其他选项。@JimRaynor我可以在OS X中直接使用
pip install cvxopt
安装
cvxopt
。就是这样<代码>pip
处理所有事情。我已经在几台机器上安装了
cvxopt
。当然,您需要安装编译器,但这也很简单,如果您使用的是
scipy
,您很可能已经安装了编译器。如果有帮助,我将Anaconda用作Python发行版(完全免费),安装Anaconda也很简单。您不需要管理员权限,也不需要配置任何内容。只要下载、安装它,它就可以运行了。这个库是我切换到Anaconda以便于管理依赖关系的原因之一。我就是不能用pip安装它。如果您已经有蟒蛇,请使用
conda安装-chttps://conda.anaconda.org/omnia cvxopt
完成了。我使用的是Windows 10和Python 2.7。请注意,这个问题明确要求不需要安装
cvxopt
qpsolvers
的解算器只是其他二次规划包(如
cvxopt
)的包装器,它需要编译器进行安装,而不是纯Python(+Numpy/Scypy)根据要求,建议的解决方案不使用二次规划解算器,而是使用非线性解算器。如果一个通用的非线性解算器足够了,一个更好的答案
Optimization terminated successfully.
         Current function value: -2.000000
         Iterations: 3
         Function evaluations: 103

x* = [ 2.  1.]; f(x*) = 2.0
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)