How can I get values of variables awaiting model update in Gurobi python
AnsweredI develop a quadratic programming model using Gurobi python API. In terms of objective formulation containing a function associated with decision variable, such as obj = f(x) + g(y), I need to get values of the decision variables for the functions f(), g(). This is why the input of functions f(), g() should be list or array type acceptable format to the functions while Gurobi model uses tupledict structure that does not fit for general calculation. How can I get values of variables awaiting model update as below?
: x[0]
: <gurobi.Var Awaiting Model Update>
---------------------- psedo code ---------------------------
import gurobipy as gp
from gurobipy import GRB
def func():
mdl = gp.Model()
x = mdl.addVars(100, lb=0, vtype=GRB.INTEGER)
for i in range(100):
_x[i] = x[i] # TypeError: float() argument must be a string or a number, not 'Var'
_x[i] = x[i].X # AttributeError: Index out of range for attribute 'X'
obj = func(_x)
mdl.setObjective(obj, GRB.MINIMIZE)
-
The code snippet you provided is not executable and does not lead to the errors you described. It makes it harder to provide help in this case.
If you get the "Awaiting Model Update" error, you can execute the update method to make variable's properties accessible before optimization. Please note that the X attribute is only available if a feasible solution point is available, e.g., through a previous optimization run. You can check whether a solution is available via the SolCount attribute.
Best regards,
Jaromił0 -
The same question has also been posted on StackOverflow: How can I get values of variables awaiting model update in Gurobi python - Stack Overflow
0 -
Firstly, I apologize insufficient previous inquiry.
The point is value extraction of variables before optimization, which cannot be captured with X attribute and it's hard to search update method cases.
I present the simple code as below but real quadratic function represented by cal_module() in the sample is much more complicated. In other word, the quadratic function is the object to be combined like MIP + domain function -> MIQP. Therefore during optimizing steps, the decision variables such as x, y need to be converted to numpy or pandas as input for quadratic formulation included in objective function. This is why I asked how to get values of variables which is uncertain at every model iteration?
---------------------- sample ---------------------------import numpy as np
import gurobipy as gp
from gurobipy import GRBdef cal_module(x,y):
m = np.array([])
for i in np.arange(len(x)-1):
r = x[i]**2 + y[i+1]**3
m = np.append(m, r)
return mmdl = gp.Model()
x = mdl.addVars(20, lb=-5, ub=5, vtype=GRB.INTEGER)
y = mdl.addVars(20, lb=-5, ub=5, vtype=GRB.INTEGER)mdl.addConstrs(x[t] + y[t] <= 3 for t in range(20))
pre_x, pre_y = [], []
for i in range(20):
pre_x = x[i].value_method or any other approach
pre_y = y[i].value_method or any other approach
obj = gp.quicksum(-2*x[t] + y[t] for t in range(20)) + cal_module(pre_x,pre_y)
mdl.setObjective(obj, GRB.MINIMIZE)mdl.optimize()
0 -
If I understand correctly, you are trying to construct a quadratic expression, add it to the objective function, and optimize it. You can and should work with the variable objects directly to achieve this. The following code should do what you have in mind
import gurobipy as gp
from gurobipy import GRB
def cal_module(x, y, model):
qExpr = gp.QuadExpr(0)
for i in range(len(x)-1):
z = model.addVar(lb=0, ub=25, vtype=GRB.INTEGER, name="aux_y_sqr_%d"%(i+1))
model.addConstr(z == y[i+1]*y[i+1], name="aux_y_sqr_constr_%d"%(i+1))
qExpr.add(x[i]**2 + y[i+1]*z)
return qExpr
mdl = gp.Model()
x = mdl.addVars(20, lb=-5, ub=5, vtype=GRB.INTEGER, name="x")
y = mdl.addVars(20, lb=-5, ub=5, vtype=GRB.INTEGER, name="y")
mdl.addConstrs(x[t] + y[t] <= 3 for t in range(20))
obj = gp.quicksum(-2*x[t] + y[t] for t in range(20)) + cal_module(x,y,mdl)
mdl.setObjective(obj, GRB.MINIMIZE)
mdl.setParam("NonConvex",2)
mdl.write("myLP.lp")
mdl.optimize()Note that the variable tupledicts \(\texttt{x,y}\) are directly passed to the \(\texttt{def_module}\) function.
Since Gurobi does not support cubic terms \(y^3\), you have to add an auxiliary variable to model the cubic term as a quadratic and a bilinear term \(z = y^2\) and \(y\cdot z\), see How do I model multilinear terms in Gurobi?
Your model is nonconvex, thus the parameter NonConvex has to be set. I used the write method to write an LP file, which makes analyzing whether the model is indeed a correct one, easier.
Best regards,
Jaromił0 -
Hi Jaromił,
Your comments were really helpful to understand Gurobi's solving flow. Many thanks.
When it comes to the quadratic expression, my problem is actually nonlinear (not quadratic), which represents a physical formulation and seems like almost impossible to convert into model using gurobi library based variable because of its complexity.
As a result, I want to capture any attribute of variable before solved with update() method. The attribute I look for is something like a state that the variable contains 0(zero) or other value, however I couldn't find such attributes in the gurobi document, https://www.gurobi.com/documentation/9.5/refman/attributes.html#sec:Attributes.
Rephrasing the question, I wonder I can get to know if the value of variable before optimization is zero(0) or not.
Best regards,
Namkyoung Lee
0 -
Hi Namkyoung Lee,
If I understand your comment correctly, you are trying to model a conditional statement, i.e., something like if variable \(x=0\) then use constraint \(a\) otherwise use constraint \(b\). Is this correct?
If yes, then the article How do I model conditional statements in Gurobi? should be what you are looking for.
If not, could you please elaborate a bit further? Maybe provide a small example of what you are tying to model.Best regards,
Jaromił0 -
Hi Jaromił,
I appreciate your continuance of help.
This is another sample code, which contains an error about indicator constraint.
I pursue constructing formulation with input whether variables have value of 0 or positive integer.Best regards,
Nam-kyoung
import gurobipy as gp
from gurobipy import GRB
def tmp_f(x):
k = np.array([1 for i in range(10)])
for j in x:
k[j] = 0
return sum((k+1)**2)
m = gp.Model("qp")
x = m.addVars(10 ,lb=0, ub=10, vtype=GRB.INTEGER, name="x")
y = m.addVars(10, lb=0, ub=10, vtype=GRB.INTEGER, name="y")
b = m.addVars(10, vtype=GRB.BINARY, name="b")
# Basic constraints
m.addConstrs(x[i] + 2 * y[i] <= 21 for i in range(10))
m.addConstrs(x[i] - y[i] >= 0 for i in range(10))
m.addConstr(x.sum('*') == 9)
# big-M approach
eps = 0.000001
M = 100 + eps
# Model if x > 0 then b = 1, otherwise b = 0
m.addConstrs(x[i] >= eps - M * (1 - b[i]) for i in range(10))
m.addConstrs(x[i] <= M * b[i] for i in range(10))
# Indicator constraints
z = [] # ← ← ← Initialization of an input for nonlinear-type formulation
t = -1
for i in range(10):
m.addConstr((b[i] == 1) >> (t == i))
z.append(t)
# Objective function
obj = gp.quicksum(x[i] + y[i] for i in range(10))
m.setObjective(obj + tmp_f(z), GRB.MAXIMIZE)
m.optimize()0 -
This thread is continued in Indicator constraint which contains constant value.
0
Please sign in to leave a comment.
Comments
8 comments