如何在Google OR-Tools CP-SAT中用布尔变量表示区间优先级?
在Google OR-Tools CP-SAT中用布尔变量表示区间优先级(序列相关准备时间)
要实现用布尔变量表示同一机器上作业j1排在j2之前的逻辑,并关联序列相关准备时间约束,你可以通过双向约束关联布尔变量与作业存在性、时间关系来完成。以下是针对你代码的修改和解释:
关键步骤与代码修改
- 定义布尔变量的双向约束
你已经声明了precedence[m][j1][j2]作为表示j1在机器m上排在j2之前的布尔变量,需要为它添加以下约束:
- 当该布尔变量为
1时,j1和j2必须都被分配到机器m上; - 当该布尔变量为
1时,j2的开始时间必须大于等于j1的结束时间加上对应准备时间; - 当j1和j2都在同一机器上时,必须有且仅有一个作业排在另一个之前。
- 修正代码中的
lit赋值与约束块
将你代码中lit = ?的部分替换为以下逻辑:
for m in machines: for j1 in jobs: for j2 in jobs: if j1 != j2: # 用已声明的precedence变量作为lit lit = precedence[m][j1][j2] # 约束1:如果j1排在j2前,则两个作业都必须在当前机器上 model.AddImplication(lit, presence_vars[m][j1]) model.AddImplication(lit, presence_vars[m][j2]) # 约束2:添加序列相关准备时间的时间约束,仅当lit为真时生效 # 修正原代码中的下标笔误:setup_matrix[m][j1][j2] model.Add(start_vars[m][j2] >= end_vars[m][j1] + setup_matrix[m][j1][j2]).OnlyEnforceIf(lit) # 约束3:当两个作业都在当前机器上时,必须有一个排在另一个之前 model.AddBoolOr([precedence[m][j1][j2], precedence[m][j2][j1]]).OnlyEnforceIf(presence_lit[m][j1][j2]) # 约束4:两个作业不能同时排在对方前面 model.Add(precedence[m][j1][j2] + precedence[m][j2][j1] <= 1) # 完善presence_lit的约束:表示j1和j2都在当前机器上 model.AddBoolAnd([presence_vars[m][j1], presence_vars[m][j2]]).OnlyEnforceIf(presence_lit[m][j1][j2]) model.AddImplication(presence_lit[m][j1][j2], presence_vars[m][j1]) model.AddImplication(presence_lit[m][j1][j2], presence_vars[m][j2])
- 补充非活跃作业的时间变量约束(可选但建议)
为了避免非活跃作业(未分配到当前机器的作业)的start/end变量影响目标函数,添加以下约束:
for m in machines: for j in jobs: # 当作业不在当前机器上时,start和end设为0 model.Add(start_vars[m][j] == 0).OnlyEnforceIf(presence_vars[m][j].Not()) model.Add(end_vars[m][j] == 0).OnlyEnforceIf(presence_vars[m][j].Not())
逻辑解释
AddImplication(a, b):表示如果a为真,则b必须为真,用来关联优先级布尔变量与作业存在性;OnlyEnforceIf(lit):仅当lit为真时,时间约束才生效;AddBoolOr和Add(<=1):确保同一机器上的两个作业要么j1在前,要么j2在前,不会出现矛盾。
内容的提问来源于stack exchange,提问作者Thomas J
相关产品推荐
相关产品推荐

