Collecting decision variables together
AnsweredI am executing a somewhat complicated calculation in order to eventually add the final result to the objective (linear program). The calculation is iterative and involves the same decision variables over and over again. After about 6 iterations everything turns really slow and gets stuck because there are too many terms in the expression.
My question is if there's any way to collect/simplify/reduce the coefficients of the similar decision variables to just the unique N, and then I won't have the problem with accumulating variables.
As a minimum working example, consider something like this where x is the decision variable:
obj = gp.LinExpr()
y = 0
for i in range(10):
y += x * np.random.randn(1)
obj += y
>> y = <gurobi.LinExpr: -0.03200917347423779 x + 1.0295208235628268 x + -1.507006757436228 x + ...>
Thank you.
-
Official comment
This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?. -
Hi Guy,
In your case, it is enough to just add the floating point numbers instead of working with variable expressions. So it would be enough to
import gurobipy as gp
import numpy as np
m = gp.Model("test")
x = m.addVar()
y = 0
for i in range(10):
y += np.random.randn(1)
obj = gp.LinExpr(y[0]*x)In general, it is best to use the LinExpr() constructor or the addTerms() function. In both cases, you should sum the coefficient of individual variables by using floating point operations only instead of working with variable expressions.
Best regards,
Jaromił0 -
Hi, thanks for the answer but my case is more complicated than the example I've shown.
Think of an iterative computation involving N Boolean variables with decisions and computations at each iteration. Although the result is linear in the variables, trying to maintain a coefficient list to then multiply the variables would be very hard.
Is there no way to reduce or simplify an expression?
0 -
Is there no way to reduce or simplify an expression?
You could call the Model.update() function, but this will result in additional overhead.
The expressions objects are not meant to be used for actual computations but rather only to be constructed once. You could try using the add() function. However, in long term, I think that coming up with a data structure for maintaining the coefficients only during your computations is the best way to go.
0 -
I think that model.update() would not help because I can't reach adding the objective expression to the model since my expression gets huge and gets stuck even before I reach the final expression I want. What's worse, is that it even carries expressions like 0.0 * x.
I know the right way to go would be to express the iterations in matrix notation and try to simplify the math, but at least for now, I want to check that my program is at least in the right direction.
For future reference, if anybody searches and have the same problem as I did, I'm posting my quick and dirty solution where I wrap my expression with this function in every iteration to keep the expressions manageable:
# helper function to simplify and reduce all the coefficients of an expression of variables
def simplify_expression(expr):
try:
N = expr.size()
coeff_dict = {}
C = expr.getConstant()
for i in range(N):
coeff = expr.getCoeff(i)
dv = expr.getVar(i) # .VarName
if(coeff_dict.get(dv) is None):
# first time, initialize
coeff_dict[dv] = coeff
else:
coeff_dict[dv] += coeff
new_tuple = [ (val, key) for key, val in coeff_dict.items() ]
new_expr = gp.LinExpr(new_tuple) + C
except:
# we sent something else, like a scalar / numpy array, so return the input
new_expr = expr
return new_expr0
Post is closed for comments.
Comments
5 comments