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'
-
Hi 子龙 王,
Please provide values for the model input Data. A small instance with some comments is better.
Thanks
- Ahmed
1 -
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 -
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
Please sign in to leave a comment.
Comments
7 comments