OptaPlanner多约束配置:同项目不同方案类型约束复用问询
OptaPlanner多约束配置实现方案
问题描述
在同一项目中,OptaPlanner无法依据不同约束配置求解不同问题。若属于同一解决方案但方案类型不同,能否复用同一约束配置?例如在代码中通过不同pickingType约束不同类型的解决方案,或是有更优的实现思路?
用户示例代码
return constraintFactory.forEach(TrolleyStep.class) .filter(ele -> ele.getPickingType() == 0) //仅约束pickingType == 0 .groupBy(trolleyStep -> trolleyStep.getOrderNumber(), countDistinctLong(TrolleyStep::getTrolley)) .penalizeLong("Minimize order split by trolley", HardSoftLongScore.ONE_SOFT, (order, trolleySpreadCount) -> trolleySpreadCount * 10000);
可行实现思路
1. 基于业务标识的条件约束复用
你当前通过pickingType过滤约束的思路完全可行,适合同一解决方案下多类型场景的复用。可以进一步优化灵活性:
- 将目标
pickingType提升为解决方案类(如TrolleySolution)的属性,而非仅在实体类中判断,这样约束规则能直接适配整个求解方案的类型。 - 优化后的示例代码:
// 假设TrolleySolution是你的解决方案类,包含targetPickingType属性 return constraintFactory.forEach(TrolleyStep.class) .filter(ele -> ele.getPickingType() == solution.getTargetPickingType()) .groupBy(trolleyStep -> trolleyStep.getOrderNumber(), countDistinctLong(TrolleyStep::getTrolley)) .penalizeLong("Minimize order split by trolley", HardSoftLongScore.ONE_SOFT, (order, trolleySpreadCount) -> trolleySpreadCount * 10000);
2. 拆分约束提供者,动态加载
如果不同方案类型的约束差异较大,建议拆分多个ConstraintProvider实现类,根据方案类型动态选择加载:
- 为不同类型分别实现约束提供者:比如
PickingType0Constraints、PickingType1Constraints - 求解时根据方案类型指定对应的约束类:
// 自定义方法,根据类型返回对应的约束提供者类 private Class<? extends ConstraintProvider> getConstraintProvider(int pickingType) { return pickingType == 0 ? PickingType0Constraints.class : PickingType1Constraints.class; } // 创建Solver时动态指定约束提供者 SolverFactory<TrolleySolution> solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(TrolleySolution.class) .withEntityClasses(TrolleyStep.class) .withConstraintProviderClass(getConstraintProvider(solution.getPickingType())));
3. 参数化约束配置
将约束的权重、过滤规则等抽离为可配置参数,避免硬编码,进一步提升复用性:
- 在解决方案类中添加约束配置参数,比如
constraintConfig,包含不同类型的权重值 - 约束中动态读取配置:
return constraintFactory.forEach(TrolleyStep.class) .filter(ele -> ele.getPickingType() == solution.getTargetPickingType()) .groupBy(trolleyStep -> trolleyStep.getOrderNumber(), countDistinctLong(TrolleyStep::getTrolley)) .penalizeLong("Minimize order split by trolley", HardSoftLongScore.ofSoft(solution.getConstraintConfig().getOrderSplitWeight()), (order, trolleySpreadCount) -> trolleySpreadCount);
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

