Google OR-Tools添加析取约束实现两车辆会面节点同步访问
问题原因
你之前的代码存在三个核心问题导致约束不生效或运行报错:
- 第一版可运行代码的判断逻辑错误,所有条件均只校验了
first_vehicle_meet的分配状态,完全没有关联second_vehicle_meet的变量,自然无法拦截异常场景。 - OR-Tools 求解器不支持 Python 原生的
and/or关键字编写逻辑约束,必须使用求解器提供的位运算符&/|/~,且每个子逻辑必须包裹括号避免优先级错误。 OnlyEnforceIf方法的入参要求是求解器的布尔Literal对象,不能直接传入比较表达式,需要调用.Var()方法将比较结果转为符合要求的变量类型。
正确实现代码
你要求的约束本质是两个会面节点的访问状态完全等价:要么都不访问,要么都被对应车辆访问,有三种等效实现方式:
1. 最简等价判断(最推荐)
直接约束两个节点的访问状态相等即可:
# 定义两个节点可选访问,不访问无惩罚 routing.AddDisjunction([first_vehicle_meet], 0) routing.AddDisjunction([second_vehicle_meet], 0) solver = routing.solver() # 定义两个节点是否被访问的布尔变量 first_visited = (routing.VehicleVar(first_vehicle_meet) != -1) second_visited = (routing.VehicleVar(second_vehicle_meet) != -1) # 约束访问状态完全等价 solver.Add(first_visited == second_visited) # 额外补充:限制两个节点只能分配给对应车辆(可选,根据你的业务需求添加) solver.Add(routing.VehicleVar(first_vehicle_meet) == 0).OnlyEnforceIf(first_visited) solver.Add(routing.VehicleVar(second_vehicle_meet) == 1).OnlyEnforceIf(second_visited)
2. 显式OR逻辑写法(适合需要自定义复杂逻辑的场景)
如果你需要显式编写OR逻辑,可以参考如下写法:
routing.AddDisjunction([first_vehicle_meet], 0) routing.AddDisjunction([second_vehicle_meet], 0) solver = routing.solver() first_visited = (routing.VehicleVar(first_vehicle_meet) != -1) second_visited = (routing.VehicleVar(second_vehicle_meet) != -1) # 显式编写:要么都访问,要么都不访问 solver.Add( (first_visited & second_visited) | (~first_visited & ~second_visited) )
3. OnlyEnforceIf 写法
如果你习惯用条件约束的写法,正确代码如下:
routing.AddDisjunction([first_vehicle_meet], 0) routing.AddDisjunction([second_vehicle_meet], 0) solver = routing.solver() # 注意:比较表达式后加.Var()转为布尔Literal,才能传入OnlyEnforceIf first_unused = (routing.VehicleVar(first_vehicle_meet) == -1).Var() second_unused = (routing.VehicleVar(second_vehicle_meet) == -1).Var() # 第二个节点未访问时,第一个节点必须不访问 solver.Add(routing.VehicleVar(first_vehicle_meet) == -1).OnlyEnforceIf(second_unused) # 第一个节点未访问时,第二个节点必须不访问 solver.Add(routing.VehicleVar(second_vehicle_meet) == -1).OnlyEnforceIf(first_unused)
内容的提问来源于stack exchange,提问作者user3931595
相关产品推荐
相关产品推荐

