2D MVar in expression for objective function
Is it possible to include 2D MVar in the objective function? I am using Python 3.7. with Gurobi 9.0.
I get "GurobiError: Variable is not a 1D MVar object" when trying to include 2D MVar in the objective function expression.
Matrix dimensions are compatible and result in a scalar value.
Example of expression: np.ones((1,10)) @ Var[10,5] @ np.ones((5,1))

Hello Victor,
thanks for letting us know! Unfortunately the only linear transformations that we currently support are onesided, and only for 1D MVar objects, viz., A @ x. I have logged your example as a feature request for more general twosided affine transformations A @ X @ B + C, where X is an 2D MVar objects, and the rest are ndarrays (or sparse matrices).
Robert

Thanks for your answer Robert,
I was trying to define a model with an array structure instead of dictionaries as I had been doing so far. The idea was to speed the model definition and solving time. My optimization model is not very difficult, but it has binary variables and a lot of data (93,726 rows, 81,648 columns and 241,008 nonzeros). Each variable has two sets: times and units, then I defined them as two dimensional in the matrix structure I was trying to define. I wonder what is the purpose of allowing creating two dimensional variables with addMvar if these cannot be used in objective functions or constraint expressions. Do you have any suggestions on how to speed a model definition and solution for a large MILP problem?
Thanks,
Victor

Victor,
without knowing the particular bottleneck you are encountering, it's difficult to give specific advice. Formulating constraints and objectives in terms of data matrices and MVar objects is the most general advice I can give to improve model building performance  just as you are trying to do.
For now, however, we'll have to live with the fact that operations on 2D MVar objects are fairly limited. But in many cases you can rewrite expressions involving 2D MVar objects in terms of 1D MVar objects by slicing the 2D MVar. Typically the performance should be still much better than constructing linear expressions on the scalar level from dicts of scalar Var objects.
Let's make one concrete example: In your code you want to form an expression "ones * (2D MVar) * ones". We will aim at the slightly more general expression (a @ X @ b) where a and b are 1D data, and X is a 2D MVar object. By expanding this expression, say, column wise, we get an equivalent form as shown in the following code:
import gurobipy as gp
import numpy as np
m = 3
n = 4
model = gp.Model()
X = model.addMVar((m,n))
a = np.random.rand(m)
b = np.random.rand(n)
# Set objective to a @ X @ b
model.setObjective(sum(b[j] * a @ X[:, j] for j in range(n)))Hope this helps!
Robert
Please sign in to leave a comment.
Comments
4 comments