What does "x[i,j].x" means?
AnsweredI'm still a beginner in Python & Gurobi, I started with a simple (Capacitated facility planning location problem).. I understood all the code terms except for a line in printing out the solution (I've marked this line by making it bold and italic) ... I don't know why we add (.x) after x[i,j].....and if I tried to remove it and write only if x[i,j] !=0 the model couldn't be optimized and the following error appears
File "E:/Gurobi/My models ;)/Capacitated facility location problem.py", line 63, in <module>
if x[i,j] !=0:
File "var.pxi", line 263, in gurobipy.Var.__ne__
GurobiError: Inequality constraints not supported
from gurobipy import*
#Model parameters
J=[1,2,3,4,5] #Customers
I=[1,2,3] #Facilities
D={1:80, 2:270, 3:250, 4:160, 5:180} #Demand for each customer
M={1:500, 2:500, 3:500} #Production Capacity of each facility
F={1:1000, 2:1000, 3:1000}
c={(1,1):4, (1,2):5, (1,3):6, (1,4):8, (1,5):10,
(2,1):6, (2,2):4, (2,3):3, (2,4):5, (2,5):8,
(3,1):9, (3,2):7, (3,3):4, (3,4):3, (3,5):4} #Transportation cost for faicility i to customer j
m=Model("Capacitated facility location problem")
#Decision variables
x={} #Dictionary contains the amount served from facility i to customer j
for i in I:
for j in J:
x[i,j]=m.addVar(vtype="C", name="x(%s,%s)"%(i,j))
y={} #Dictionary with binary values if facility established at location i or not
for i in I:
y[i]=m.addVar(vtype="B", name="y(%s)"%(i))
#Objective function
m.setObjective((quicksum(F[i]*y[i] for i in I )+ quicksum(c[i,j]*x[i,j] for i in I for j in J)),GRB.MINIMIZE)
#Constriants
#Demand must be satisfied
for j in J:
m.addConstr(quicksum(x[i,j] for i in I)==D[j], name="Demand(%s)"%j)
#All sent products for facility i is smaller than or equal to its capacity if the facility is opened
for i in I:
m.addConstr(quicksum(x[i,j] for j in J)<=M[i]*y[i], name="Capacity(%s)"%i)
#sent items from facility i to customer j is smaller than or equal to the customer's demand if the facility was opened
for i in I:
for j in J:
m.addConstr(x[i,j] <= D[j]*y[i], name="C3(%s,%s)"%(i,j))
m.optimize()
#print("transported quantities", x)
#print("facilities opened", y)
edges={}
for i in I:
for j in J:
if x[i,j].x !=0: #.........................Why do they wirte (.x) here???
keys= ((i,j) for (i,j) in x )
edges[keys]=x[i,j]
facilities=[i for i in y if y[i]==1 ]
print (facilities)
print(edges)

Welcome to Gurobi!
With the X attribute, you access the variable's value in the current solution. Note that the code first does
m.optimize()
to find the optimal solution. The /(x[i,j].x/) is then part of the code that prints the solution to the screen.
You should actually add the same to y[i] in this line:
facilities=[i for i in y if y[i]==1 ]
Also, it is recommended to allow for some tolerances when comparing the values of variables with other numbers (because some small deviations are unavoidable in computations with floatingpoint numbers). E.g. instead of \(x[i,j].x \neq 0\) you should check for \(x[i,j].X > \epsilon\) or \(x[i,j].X < \epsilon\) for some appropriate \(\epsilon\) (e.g. 1e6). Since y is binary, you could instead of \(y[i].X == 1\) simply check for \(y[i].X > 0.5\).
A few more remarks on your code: The line
keys= ((i,j) for (i,j) in x )
building the same object for each i in I and j in J and could be moved outside the loop. (The variables i and j in this line are not the ones your looping over with "for i in I" and "for j in J".)
The line
edges[keys]=x[i,j]
also does not really make sense it keeps overwriting edges[keys] in each iteration of the loop.
0 
Thank you very much, your support is greatly appreciated :)
0
Please sign in to leave a comment.
Comments
2 comments