我正在研究一个单机调度问题,其目标是最小化加权延迟。我使用Python/Gurobi创建了一个模型,但我遇到了目标函数的问题,因为它产生了次优结果。有趣的是,当我将模型转移到Excel中的OpenSolver中时,我得到了更好的结果。
import gurobipy as gp
N = 15 # number of jobs
# w: weights of jobs
w = [1, 10, 9, 10, 10, 4, 3, 2, 10, 3, 7, 3, 1, 3, 10]
# p: process time of jobs
p = [26, 24, 79, 46, 32, 35, 73, 74, 14, 67, 86, 46, 78, 40, 29]
# d: due dates of jobs
d = [397, 405, 433, 443, 424, 372, 392, 461, 432, 409, 400, 385, 464, 411, 427]
# Create a new model
m = gp.Model()
x = {}
goal = m.addVar(vtype=gp.GRB.CONTINUOUS)
#T : Tardiness
#C : Completion time
T = m.addVars(N,lb=0)
C = m.addVars(N)
K = m.addVars(N)
weight = {j: w[j] for j in range(N)}
#x[i,j]:The variable xij is a variable that takes a value of 1 when Job i is assigned to Sequence j, and takes a value of 0 in all other cases.
for i in range(N):
for j in range(N):
x[i,j] = m.addVar(vtype=gp.GRB.BINARY)
# Set objective function: "The sequencing of jobs in a way that minimizes the total weighted delay."
m.setObjective((goal), gp.GRB.MINIMIZE)
# Add constraints
# Constraint1: Each job must be assigned to a sequence.
for i in range(N):
m.addConstr(gp.quicksum(x[i,j] for j in range(N)) == 1)
#Constraint2: Each sequence must be assigned a job.
for j in range(N):
m.addConstr(gp.quicksum(x[i,j] for i in range(N)) == 1)
#Constraint3: If Job i is assigned to Sequence j, then the processing time of Job i is assigned to Sequence j.
for j in range(N):
m.addConstr(gp.quicksum(p[i]*x[i,j] for i in range(N)) == K[j])
#Constraint4: If Job i is assigned to Sequence j, then the weight of Job i is assigned to Sequence j.
for j in range(N):
m.addConstr(gp.quicksum(w[i]*x[i,j] for i in range(N)) == weight[j])
#Constraint 5: The completion time of Sequence j is the sum of the completion time of the previous sequence and the processing time of the job assigned to Sequence j.
C[0].lb = 0
for j in range(1, N):
m.addConstr(C[j-1] + K[j] == C[j])
#Constraint 6: If the completion time is greater than the due date, then there is a tardiness.
for j in range(N):
m.addConstr(T[j] >= C[j] - gp.quicksum(x[i,j]*d[i] for i in range(N)))
#goal: The sequencing of jobs in a way that minimizes the total weighted tardiness.
m.addConstr(gp.quicksum(T[j]*weight[j] for j in range (N)) <= goal)
m.addConstr(C[0] == K[0])
m.addConstr(T[0] >= C[0] - d[0])
# Solve the problem
m.optimize()
# Print solution
print('Optimal objective value: %g' % m.objVal)
print('Solution:')
for i in range(N):
for j in range(N):
if x[i,j].X > 0.5:
print('x[%d,%d] = %d' % (i,j,x[i,j].X))
如果您能帮助我改进Python/Gurobi模型中的目标函数,使其与Excel中OpenSolver获得的结果相匹配,我将不胜感激。
您应该为这两种方法写出LP文件,以查看它们是否在某些地方有所不同。通常建议仔细检查公式,看看它是否与数学模型相匹配。
我没有运行的gp版本,所以没有测试,但是....
您似乎将weight
视为约束4中的模型变量,它不是模型变量,所以我认为您在那里有一些未定义的行为,令人惊讶的是没有错误?
所以我认为你可以:
(a)使其成为模型变量
(b)不捕获约束6中的延迟T
,而将T
设为"加权延迟";并在那里包含w
参数,因为你有已知的工作配对来排序。比如:
#Constraint 6: If the completion time is greater than the due date, then there is a WEIGHTED tardiness.
for j in range(N):
m.addConstr(T[j] >= (C[j] - gp.quicksum(x[i,j]*d[i] for i in range(N))*w[i]) )
然后,当然,完全删除约束4;从问题中去掉weight
,w[i]
就足够了;并删除目标语句
weight
变量