Hello Victor,

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

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 2-D MVar objects are fairly limited.  But in many cases you can rewrite expressions involving 2-D MVar objects  in terms of 1-D MVar objects by slicing the 2-D 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 * (2-D MVar)  * ones".  We will aim at the  slightly more general expression (a @ X @ b) where a and b are 1-D data, and X is a 2-D MVar object.  By expanding this expression, say, column wise, we get an equivalent form as shown in the following code:

import gurobipy as gpimport numpy as npm = 3n = 4model = gp.Model()X = model.addMVar((m,n))a = np.random.rand(m)b = np.random.rand(n)# Set objective to a @ X @ bmodel.setObjective(sum(b[j] * a @ X[:, j] for j in range(n)))

Hope this helps!

Robert