Matrix Interface for Python
CompletedI want to use gurobi from python, but the highlevel API with addVars() and addConstrs() is cumbersome for large problems.
It seems that there exists a matrix interface for C, R and MATLAB where you can directly pass the matrices and vectors (Q, c, A, b) that describe the problem (https://en.wikipedia.org/wiki/Quadratic_programming)
Does such an interface really not exist for python?
What is the intended workflow for problems with +100k constraints and variables in python?

Hi Johannes,
I think the main reason why python does not provide a raw interface is that the highlevel API is MUCH better in terms of debugging and extending a model while the overhead is minimal. Could you elaborate a bit more what exactly makes the interface not suited for your needs?
In my experience building a model by creating a matrix first and then feeding it to gurobi (or any other LP/MIP solver) is very cumbersome and error prone as you have to keep track of all the indices for yourself. In contrast, the API provided by gurobi allows a nice expressive way of creating a model. For example if I have to add some additional constraints and variables to an existing model I can do this directly via the addVars and addConstrs constructors and do not have to adjust any matrix that would involve inconvenient adjustments involving indices.
You could also easily create a small function that takes a matrix and creates variables and constraints automatically...

I currently work with the python interface of osqp.
I want to solve linearisations / convexifications of robot motions for varying scenarios of
in the workspace.
Osqp was easy to integrate into the rest of my code, but it is not as fast as I have hoped.
Therefore I wanted to try gurobi and compare the two tools for my use case.
But with this iterative way gurobi takes way longer to build the model than osqp.
I would expect a speedup if all the information could be passed in one step
(I suppose gurobi builds the matrices internal anyway).
Maybe i will find the time to write a wrapper witch calls the C routine directly,
but i have hoped, that such a thing exists already.
Ideally I want to use scipy sparse matrices and numpy arrays. 
Hi Johannes,
you could try to use cvxpy (https://www.cvxpy.org/examples/basic/quadratic_program.html) as an intermediate interface to gurobi. From what I've seen it should offer a similar interface as osqp and can use gurobi as a solver. But be aware that this brings another layer and thus some overhead when building the model.
Do you solve a series of smaller problems or is it rather one (or a small bunch of) bigger model? If it's the latter case, the overhead might not be a problem but if building the model takes also a nonnegligible percentage of the overall time, going with a self coded function that takes the matrices/vectors and builds a model (or even going with calling the C API) might be better suited for your application.

The Gurobi 9.0 Python API supports matrixoriented modeling with NumPy and SciPy matrices. A good place to learn about it is the documentation for the MLinExpr object and the matrix1.py example.
Thanks!
Eli

So I'm experimenting with the matrix API in a model.
While it looks helpful, a downside is that an MLinExpr is something completely different from a LinExpr and the two cannot be combined.
Concrete example:
I want to take a weighted sum of all elements of a matrix A; someting like (w*A).sum(), where A is a matrix of variables, and w is a (samesize) matrix of constant numbers (elementwise multiplication).
Of course, it doesn't work as written, so I tried the "old" way with quicksum(A[i,j]*w[i,j] for i ... for j ...),
but since the product A[i,j]*w[i,j] is an MLinExpr it cannot be used within a quicksum().
Any suggestions on how to write a weighted sum of all matrix elements?
Sven

Hello Sven,
our first step towards a matrix friendly API for gurobipy indeed lacks such operations like pointwise multiplication with MVar objects, but I have taken note of this feature request. A workaround without resorting to the scalar level would be to do
import gurobipy as gp
import numpy as np
n = 100
m = gp.Model()
A = m.addMVar((n,n))
w = np.random.rand(n,n)
m.addConstr(sum(A[:,i] @ w[:,i] for i in range(n)) <= 42)Robert
Please sign in to leave a comment.
Comments
7 comments