如何使用Or-Tools(Java)为路径优化弧段添加特定容量约束
可以基于OR-Tools Routing模块实现弧段级的载重约束,Java版本有完整API支持,不需要魔改源码,具体实现方案如下:
实现前提
你已经完成基础CVRP逻辑搭建,且通过addDimension方法注册了载重维度(常规命名为Capacity),维度中每个节点的累计变量(CumulVar)对应该节点位置的货车实时载重。
核心逻辑
你需要的约束本质是:当路径选择弧(i,j)通行时,货车在i点的实时载重(即驶入弧段时的载重)必须小于等于该弧段的最大允许载重。
你提到的规则capacity(i) - capacity(j) <= allowed capacity between the two steps和上述逻辑完全等价:弧段(i,j)之间无装卸货操作,j点的载重等于i点载重减去j点的卸货量/加上j点的装货量,差值为节点j的固定需求值,天然为非负且远小于常规限重,真正触发限制的是弧段上的实时载重值。
Java版本具体实现步骤
- 第一步:预处理弧段限重矩阵
构建二维数组long[][] arcMaxLoad存储所有节点对之间的载重上限:无特殊限制的普通路段直接填车辆最大额定载重,存在桥梁、限高杆等限重要求的弧段填入对应限制值,完全禁止货车通行的弧段可直接在距离/成本矩阵中赋值为极大值(大于所有可行路径的总成本即可),提前剪枝提升求解效率。 - 第二步:获取模型核心实例
拿到已经初始化完成的三个核心对象:路由索引管理器RoutingIndexManager、路由模型RoutingModel、载重维度实例RoutingDimension capacityDim。 - 第三步:逐弧段绑定约束
遍历所有可通行的节点对,针对有限重要求的弧段,通过onlyEnforceIf方法绑定约束生效条件:仅当路径实际选中该弧段时,才校验载重是否符合限重要求。核心代码如下:// 全局车辆最大载重,用于跳过无特殊限制的弧段减少冗余约束 final long VEHICLE_MAX_CAP = 6; for (int i = 0; i < manager.getNumberOfNodes(); i++) { for (int j = 0; j < manager.getNumberOfNodes(); j++) { if (i == j) continue; long currentArcLimit = arcMaxLoad[i][j]; // 限重等于车辆最大载重的弧段无需额外加约束,减少求解器计算量 if (currentArcLimit >= VEHICLE_MAX_CAP) continue; // 转换节点索引为模型内部索引 long indexI = manager.nodeToIndex(i); long indexJ = manager.nodeToIndex(j); // 获取i点的实时载重变量 IntVar loadAtINode = capacityDim.getCumulVar(indexI); // 添加约束:i点载重 <= 弧段限重,仅当弧(i,j)被选中通行时生效 model.addLessOrEqual(loadAtINode, currentArcLimit) .onlyEnforceIf(routing.arcVarAsBool(indexI, indexJ)); } }
验证说明
针对你提到的测试场景:节点i处货车载重为3单位,弧(i,j)对应桥梁限重2单位,求解器会自动识别该弧段违反约束,不会将其纳入最终规划路径,完全符合预期。
内容的提问来源于stack exchange,提问作者thomaslprr
相关产品推荐
相关产品推荐

