docplex构建CVRP添加子回路约束触发重复约束告警问题求助
问题根因
- 约束书写存在语法错误:你在
mdl.add_constraints()的迭代参数内部嵌套了mdl.add()方法,导致每一条生成的约束都会被先后添加两次到模型中,这是触发重复告警的直接原因。 - MTZ子回路消除约束的遍历逻辑冗余:你当前遍历所有
i,j ∈ N且i≠j的节点对,但二元变量x[i,j]仅在允许的弧集合A中存在定义,不在A中的节点对不需要加约束,冗余遍历可能增加异常概率。 - 未排除配送中心节点:标准MTZ约束仅需对客户节点生效,如果你的节点集合
N包含配送中心,会生成大量无效约束。
修复后的正确代码
from docplex.mp.model import Model mdl = Model('CVRP') # 节点定义说明:V为所有节点集合(包含配送中心,默认编号为0),N为客户节点集合,A为允许通行的弧集合 x = mdl.binary_var_dict(A, name='x') # 为连续变量u设置上下界,减少求解器搜索空间,此处假设u代表节点访问顺序 u = mdl.continuous_var_dict(N, lb=1, ub=len(N), name='u') # 目标函数:最小化总行驶距离 mdl.minimize(mdl.sum(distanceList[i][j]*x[i, j] for i, j in A)) # 客户节点出入度约束:每个客户仅被访问一次 mdl.add_constraints(mdl.sum(x[i, j] for j in V if j != i) == 1 for i in N) mdl.add_constraints(mdl.sum(x[i, j] for i in V if i != j) == 1 for j in N) # 修正后的MTZ子回路消除约束:去掉内层mdl.add,仅对客户节点间的有效弧加约束 customer_count = len(N) mdl.add_constraints( u[i] - u[j] + customer_count * x[i,j] <= customer_count - 1 for i,j in A if i in N and j in N and i != j )
优化建议
如果需要使用负载型MTZ约束(u[i]代表车辆到达节点i时的累计负载),可以将子回路约束替换为以下写法,约束紧密度更高,求解速度更快:
# Q为车辆额定载重,demand为各节点的需求数组 mdl.add_constraints( u[i] + demand[j] - u[j] <= Q * (1 - x[i,j]) for i,j in A if i in N and j in N and i != j ) # 补充配送中心的负载约束 mdl.add_constraint(u[0] == 0)
内容的提问来源于stack exchange,提问作者Mustafa
相关产品推荐
相关产品推荐

