pythonnumpyscipyquadratic-programmingscipy-optimize

Is there any quadratic programming function that can have both lower and upper bounds - Python


Normally I have been using GNU Octave to solve quadratic programming problems.

I solve problems like

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

With subject to

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

Where lb and ub are lower bounds and upper bounds, e.g limits for x

My Octave code looks like this when I solve. Just one simple line

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

The square brackets [] are empty because I don't need the equality constraints

Aeq*x = beq,

So my question is: Is there a easy to use quadratic solver in Python for solving problems

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

With subject to

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

Or subject to

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

Solution

  • If you need a general quadratic programming solver like quadprog, I would suggest the open-source software 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 on Convex Optimization.

    The function you want to use is cvxopt.solvers.qp. A simple wrapper to use it in Numpy like quadprog is the following. Note that bounds can be included as a special case of inequality constraints.

    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 used to be difficult to install, but is nowadays also included in the Anaconda distribution and can be installed (even on Windows) with conda install cvxopt.

    If instead, you are interested in the more specific case of linear least-squares optimisation with bounds, which is a subset of the general quadratic programming, namely

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

    Then Scipy has the specific function scipy.optimize.lsq_linear(A, b, bounds).

    Note that the accepted answer is a very inefficient approach and should not be recommended. It makes no use of the crucial fact that the function you want to optimize is quadratic but instead uses a generic nonlinear optimization program and does not even specify the analytic gradient.