Add a new constraint to the model
Openfrom gurobipy import Model, GRB, quicksum
import sys
def MIPModel(Data):
n = Data['n']
m = Data['m']
J = Data['J']
OJ = Data['OJ']
oj=OJ
operations_machines = Data['operations_machines']
operations_times = Data['operations_times']
largeM = Data['largeM']
# starttime=[0,1,2,3,4,5,6,7,8]
D = [[60, 60, 65, 60, 65, 90, 60, 65],
[65, 65, 85, 75, 60, 75, 85, 80],
[60, 70, 75, 80, 75, 80, 80, 75],
[65, 65, 80, 75, 80, 75, 75, 80],
[60, 65, 65, 60, 75, 80, 80, 75],
[60, 65, 65, 80, 75, 75, 80, 75],
[60, 60, 75, 80, 75, 70, 60, 75]]
# preprocessing
# obtain the earliest starting time for each operation
stimeOp = {}
stimeOpMax = 0
for i in J:
for j in OJ[i]:
if j == 1:
# stimeOp[i, j] = starttime[i]
stimeOp[i, j] = 0
else:
opt_time_min = sys.maxsize
for k in operations_machines[i, j - 1]:
if operations_times[i, j - 1, k] < opt_time_min:
opt_time_min = operations_times[i, j - 1, k]
stimeOp[i, j] = stimeOp[i, j - 1] + opt_time_min
if stimeOpMax < stimeOp[i, j]:
stimeOpMax = stimeOp[i, j]
print(stimeOp)
# the latest completion time for each operation
ltimeOp = {}
for i in J:
for jj in range(len(OJ[i]) - 1, -1, -1):
j = OJ[i][jj]
opt_time_min = sys.maxsize
for k in operations_machines[i, j]:
if operations_times[i, j, k] < opt_time_min:
opt_time_min = operations_times[i, j, k]
if jj == len(OJ[i]) - 1:
ltimeOp[i, j] = largeM - opt_time_min
else:
ltimeOp[i, j] = ltimeOp[i, j + 1] - opt_time_min
print(ltimeOp)
model = Model("model")
x, y, s = {}, {}, {}
cmax = model.addVar(lb=stimeOpMax, ub=largeM, vtype="I", name="cmax")
# define x
for j in J: # job
for i in OJ[j]: # operation
# s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
s[j, i] = model.addVar(lb=stimeOp[j, i], ub=largeM, vtype="I", name="s(%s,%s)" % (j, i)) # ltimeOp[j,i]
for k in operations_machines[j, i]:
x[j, i, k] = model.addVar(lb=0, ub=1, vtype="I", name="x(%s,%s,%s)" % (j, i, k))
# define y
for i in J:
for ip in J:
for j in OJ[i]:
for jp in OJ[ip]:
y[i, j, ip, jp] = model.addVar(lb=0, ub=1, vtype="I", name="y(%s,%s,%s,%s)" % (i, j, ip, jp))
# define objective function
model.setObjective(cmax, GRB.MINIMIZE)
# constraint(3)
for i in J:
for j in OJ[i]:
model.addConstr(sum(x[i, j, k] for k in operations_machines[i, j]) == 1, "assignment(%s,%s)" % (i, j))
# constraint(4)
for i in J:
for j in OJ[i]:
if j != OJ[i][0]:
model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])
,"stime(%s,%s)" % (i, j))
# constraint(5) 自己
for k in operations_machines[1, 1] :
for i in J:
model.addConstr(sum(x[i, j, k] for j in OJ[i] ) == 1, "cons_x(%s,%s)" % (i, j))
# constraint(6)
for i in J:
for ip in J:
if i < ip:
for j in OJ[i]:
for jp in OJ[ip]:
kkp = [k for k in operations_machines[i, j] if k in operations_machines[ip, jp]]
if len(kkp):
for iipk in kkp:
model.addConstr(s[ip, jp] >= s[i, j] + operations_times[i, j, iipk] - largeM * (
3 - y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
"cons_6_(%s,%s,%s,%s)" % (i, j, ip, jp))
model.addConstr(
s[i, j] >= s[ip, jp] +
operations_times[ip, jp, iipk] - largeM *
(2 + y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
"cons_5_(%s,%s,%s,%s)" % (i, j, ip, jp))
# cmax constraint
for i in J:
model.addConstr(cmax >= s[i, OJ[i][len(OJ[i]) - 1]] + quicksum(
operations_times[i, OJ[i][len(OJ[i]) - 1], k] * x[i, OJ[i][len(OJ[i]) - 1], k] for k in
operations_machines[i, OJ[i][len(OJ[i]) - 1]]), "cmax_cons_(%s)" % (i))
model.params.TimeLimit=90
model.update()
model.optimize()
# print(y)
for j in J: # job
for i in OJ[j]: # operation
# s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
for k in operations_machines[j, i]:
string= ''
if abs( x[j, i, k].x-1) <= 0.01:
string =j+i+k+s[j,i].x
print(j,i,k,s[j,i].x)
# print(s[j,i].x)
# print(s)
return model
I have now written a model of shop scheduling that considers many constraints, and now I want to add a new one: the cost of transport between machines
The existing constraint is that the start time of the current operation s[i, j] must be later than the end time of the previous operation s[i, j-1]+ the time taken by the previous operation
There is a distance transport matrix D, representing the time cost between all machines, and the start time of the current operation s[i, j] must be later than the end time of the previous operation s[i, j-1]+ the time taken by the previous operation + the transport time of the machine on which the two operations are located
我现在写好了一个有关车间调度的模型,考虑了众多约束,现在我想添加一个新约束:机器之间的运输代价
现有的约束是:当前操作的开始时间s[i, j]必须晚于前一个操作的结束时间s[i, j-1]+前一个操作所需的时间
我希望额外考虑两个操作之间的运输时间代价 ,存在一个距离运输矩阵D,代表所有机器之间的时间代价,当前操作的开始时间s[i, j]必须晚于前一个操作的结束时间s[i, j-1]+前一个操作所需的时间+两个操作所在机器的运输时间
我尝试在约束4中添加如下代码:
# constraint(4)
for i in J:
for j in OJ[i]:
if j != OJ[i][0]:
previous_machine = None
current_machine = None
model.update()
for k in operations_machines[i, j-1]:
if x[i, j-1, k] >0.5 : # 根据机器分配情况确定前一个操作所在的机器
previous_machine = k
break
for k in operations_machines[i, j]:
if x[i, j, k] > 0.5: # 根据机器分配情况确定当前操作所在的机器
current_machine = k
break
model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
D(previous_machine,operations_machines),"stime(%s,%s)" % (i, j))
result:TypeError: '>' not supported between instances of 'Var' and 'float'
-
Official comment
This post is more than two 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 try Gurobot, our chatbot interface offering instant, expert-level support. -
The last line of code is wrong. My new code should read:
D[previous_machine][operations_machines],
Instead ofD(previous_machine,operations_machines),
But it also fails in the following parts:for k in operations_machines[i, j-1]:
if x[i, j-1, k] >0.5:
previous_machine = k
break
for k in operations_machines[i, j]:
if x[i, j, k] > 0.5:
current_machine = k
break0 -
I don't know if adding the corresponding code in constraint 4 is the right thing to do, and I appreciate someone giving me some guidance
0 -
I also tried the following:
# constraint(4)
# for i in J:
# for j in OJ[i]:
# if j ! = OJ[i][0]:# p = None
# current_machine = None
# model.update()
# model. addConstr(s[i, j] >= s[i, j - 1] + quicksum(
# operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
# quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]] for p in operations_machines[i, j - 1] for q in operations_machines[i, j])
# ,"stime(%s,%s)" % (i, j))
There will be:
TypeError: list indices must be integers or slices, not gurobipy. LinExprSomeone told me I should use the indicator, but I still don't know how to do it
0 -
Hi 子龙 王,
Please provide values for the model input Data. A small instance with some comments is better.
Thanks
- Ahmed
1 -
The complete executable code is as follows:
from gurobipy import Model, GRB, quicksum
import sys
import numpy as np
import time
import osfrom DataRead import getdata
from itertools import chain
def MPModel(Data):
n = Data['n']
m = Data['m']
J = Data['J']
OJ = Data['OJ']
oj=OJ
operations_machines = Data['operations_machines']
operations_times = Data['operations_times']
largeM = Data['largeM']
# starttime=[0,1,2,3,4,5,6,7,8]
D = [[60, 60, 65, 60, 65, 90, 60, 65],
[65, 65, 85, 75, 60, 75, 85, 80],
[60, 70, 75, 80, 75, 80, 80, 75],
[65, 65, 80, 75, 80, 75, 75, 80],
[60, 65, 65, 60, 75, 80, 80, 75],
[60, 65, 65, 80, 75, 75, 80, 75],
[60, 60, 75, 80, 75, 70, 60, 75]]# preprocessing
# obtain the earliest starting time for each operation
stimeOp = {}
stimeOpMax = 0
for i in J:
for j in OJ[i]:
if j == 1:
# stimeOp[i, j] = starttime[i]
stimeOp[i, j] = 0
else:
opt_time_min = sys.maxsize
for k in operations_machines[i, j - 1]:
if operations_times[i, j - 1, k] < opt_time_min:
opt_time_min = operations_times[i, j - 1, k]
stimeOp[i, j] = stimeOp[i, j - 1] + opt_time_min
if stimeOpMax < stimeOp[i, j]:
stimeOpMax = stimeOp[i, j]
print(stimeOp)
# the latest completion time for each operation
ltimeOp = {}
for i in J:
for jj in range(len(OJ[i]) - 1, -1, -1):
j = OJ[i][jj]
opt_time_min = sys.maxsize
for k in operations_machines[i, j]:
if operations_times[i, j, k] < opt_time_min:
opt_time_min = operations_times[i, j, k]if jj == len(OJ[i]) - 1:
ltimeOp[i, j] = largeM - opt_time_min
else:
ltimeOp[i, j] = ltimeOp[i, j + 1] - opt_time_min
print(ltimeOp)model = Model("model")
x, y, s = {}, {}, {}
cmax = model.addVar(lb=stimeOpMax, ub=largeM, vtype="I", name="cmax")# define x
for j in J: # job
for i in OJ[j]: # operation
# s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
s[j, i] = model.addVar(lb=stimeOp[j, i], ub=largeM, vtype="I", name="s(%s,%s)" % (j, i)) # ltimeOp[j,i]
for k in operations_machines[j, i]:
x[j, i, k] = model.addVar(lb=0, ub=1, vtype="I", name="x(%s,%s,%s)" % (j, i, k))
# define y
for i in J:
for ip in J:
for j in OJ[i]:
for jp in OJ[ip]:
y[i, j, ip, jp] = model.addVar(lb=0, ub=1, vtype="I", name="y(%s,%s,%s,%s)" % (i, j, ip, jp))# define objective function
model.setObjective(cmax, GRB.MINIMIZE)
# constraint(3)
for i in J:
for j in OJ[i]:
model.addConstr(sum(x[i, j, k] for k in operations_machines[i, j]) == 1, "assignment(%s,%s)" % (i, j))
# constraint(4)
for i in J:
for j in OJ[i]:
if j != OJ[i][0]:p = None
current_machine = None
model.update()
model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])
,"stime(%s,%s)" % (i, j))
# constraint(4) idea1
# for i in J:
# for j in OJ[i]:
# if j != OJ[i][0]:# p = None
# current_machine = None
# model.update()
# model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
# operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
# quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]] for p in operations_machines[i, j - 1] for q in operations_machines[i, j])
# ,"stime(%s,%s)" % (i, j))
# # constraint(4) idea2
# for i in J:
# for j in OJ[i]:
# if j != OJ[i][0]:# previous_machine = None
# current_machine = None
# model.update()
# for k in operations_machines[i, j-1]:
# if x[i, j-1, k] > 0.5: # 根据机器分配情况确定前一个操作所在的机器
# previous_machine = k
# break
# for k in operations_machines[i, j]:
# if x[i, j, k] > 0.5: # 根据机器分配情况确定当前操作所在的机器
# current_machine = k
# break
# model.addConstr(s[i, j] >= s[i, j - 1] + quicksum(
# operations_times[i, j - 1, k] * x[i, j - 1, k] for k in operations_machines[i, j - 1])+
# D[[previous_machine][current_machine]]
# ,"stime(%s,%s)" % (i, j))
# constraint(5)
for k in operations_machines[1, 1] :
for i in J:
model.addConstr(sum(x[i, j, k] for j in OJ[i] ) == 1, "cons_x(%s,%s)" % (i, j))
# constraint(6)
for i in J:
for ip in J:
if i < ip:
for j in OJ[i]:
for jp in OJ[ip]:
kkp = [k for k in operations_machines[i, j] if k in operations_machines[ip, jp]]
if len(kkp):
for iipk in kkp:
model.addConstr(s[ip, jp] >= s[i, j] + operations_times[i, j, iipk] - largeM * (
3 - y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
"cons_6_(%s,%s,%s,%s)" % (i, j, ip, jp))
model.addConstr(
s[i, j] >= s[ip, jp] +
operations_times[ip, jp, iipk] - largeM *
(2 + y[i, j, ip, jp] - x[i, j, iipk] - x[ip, jp, iipk]),
"cons_5_(%s,%s,%s,%s)" % (i, j, ip, jp))
# cmax constraint
for i in J:
model.addConstr(cmax >= s[i, OJ[i][len(OJ[i]) - 1]] + quicksum(
operations_times[i, OJ[i][len(OJ[i]) - 1], k] * x[i, OJ[i][len(OJ[i]) - 1], k] for k in
operations_machines[i, OJ[i][len(OJ[i]) - 1]]), "cmax_cons_(%s)" % (i))model.params.TimeLimit=90
model.update()
model.optimize()
# print(y)for j in J: # job
for i in OJ[j]: # operation
# s[j,i]=model.addVar(lb=0,ub=largeM,vtype="I",name="s(%s,%s)"%(j,i))
for k in operations_machines[j, i]:
string= ''
if abs( x[j, i, k].x-1) <= 0.01:
string =j+i+k+s[j,i].x
print(j,i,k,s[j,i].x)
# print(s[j,i].x)
# print(s)
return model
filename='datasss.txt'
Data=getdata(filename)n=Data['n']
m=Data['m']
J=Data['J']
OJ=Data['OJ']
print(OJ)
operations_machines=Data['operations_machines']
operations_times=Data['operations_times']
largeM=Data['largeM']mipmodel=MPModel(Data)
txt document content is:
4 4 1
4 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2 4 3 54 1 34 4 61 2 2
4 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70 4 4 9 1 15 2 89 3 70
4 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87 4 1 38 2 19 3 28 4 87
4 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29 4 1 95 3 34 2 7 4 29txt explanation:
-in the first line there are (at least) 2 numbers: the first is the number of jobs and the second the number of machines (the 3rd is not necessary, it is the average number of machines per operation)
-Every row represents one job: the first number is the number of operations of that job, the second number (let's say k>=1) is the number of machines that can process the first operation; then according to k, there are k pairs of numbers (machine,processing time) that specify which are the machines and the processing times; then the data for the second operation and so on...
Example: Fisher and Thompson 6x6 instance, alternate name (mt06)6 6 1
6 1 3 1 1 1 3 1 2 6 1 4 7 1 6 3 1 5 6
6 1 2 8 1 3 5 1 5 10 1 6 10 1 1 10 1 4 4
6 1 3 5 1 4 4 1 6 8 1 1 9 1 2 1 1 5 7
6 1 2 5 1 1 5 1 3 5 1 4 3 1 5 8 1 6 9
6 1 3 9 1 2 3 1 5 5 1 6 4 1 1 3 1 4 1
6 1 2 3 1 4 3 1 6 9 1 1 10 1 5 4 1 3 1first row = 6 jobs and 6 machines 1 machine per operation
second row: job 1 has 6 operations, the first operation can be processed by 1 machine that is machine 3 with processing time 1.0 -
The reasons for the errors you have in constraint 4 are as follows:
# constraint(4) idea1
quicksum(D[p*x[i, j - 1, p]][q*x[i, j, q]]
TypeError: list indices must be integers or slices, not gurobipy.LinExpr
This error occurred because you used linear expressions p*x[i, j - 1, p] and q*x[i, j, q] as the index for D where D is a Python list.
# constraint(4) idea2if x[i, j-1, k] > 0.5:
TypeError: '>' not supported between instances of 'Var' and 'float'
Here, you attempted to add an if condition forx[i, j-1, k], which does not yet have a value, since it is a decision variable.
Please refer to this article for more details about How do I model conditional statements in Gurobi?
- Ahmed0 -
I have looked at the relevant website and understood the application of the if constraint in gurobi, but I still don't know how to write my own questions I wonder if it is convenient to provide specific code details
0
Post is closed for comments.
Comments
8 comments