使用OptaPlanner ConstraintVerifier验证约束时首个约束始终返回0分
问题分析与解决
你遇到的首个约束规则分数始终为0的问题,大概率是分数类型不匹配或测试数据/断言不匹配导致的,结合你的代码细节,具体排查点和修复方案如下:
1. 分数类型与断言方法不匹配
你的约束使用了penalizeLong和HardSoftLongScore(长整型分数),但测试中却用了针对整型分数的penalizesBy(1)断言,两者类型不兼容,导致断言无法识别实际产生的长整型分数,误以为分数为0。
修复方案:
如果你的规划方案确实需要长整型分数,将测试中的断言改为长整型版本:
verifier.verifyThat(OrderPickingConstraintProvider::requiredNumberOfBuckets) .given(trolleyStep) .penalizesByLong(10L); // 与约束中返回的10对应
如果不需要长整型分数,修改约束为普通整型分数:
public Constraint requiredNumberOfBuckets(ConstraintFactory constraintFactory) { return constraintFactory.forEach(TrolleyStep.class) .penalize("Required number of buckets", HardSoftScore.ONE_SOFT, trolleyStep -> 1); // 返回1,匹配测试的penalizesBy(1) }
2. 测试未传入约束依赖的必要数据
你的约束逻辑是验证“所需桶数量”,必然需要用到Trolley的容量和现有桶数,但测试中只传入了TrolleyStep,没有传入Trolley对象。即使当前约束代码写死了返回10,后续业务逻辑中如果加入了基于Trolley的判断,约束也会因为缺少数据而无法触发。
修复方案:
测试时传入所有依赖对象,并完善约束的业务逻辑:
// 测试代码修改 verifier.verifyThat(OrderPickingConstraintProvider::requiredNumberOfBuckets) .given(trolley, trolleyStep) // 同时传入Trolley和TrolleyStep .penalizesByLong(19999L); // 20000000/1000 -1 = 19999,对应超出的桶数 // 约束逻辑完善 public Constraint requiredNumberOfBuckets(ConstraintFactory constraintFactory) { return constraintFactory.forEach(TrolleyStep.class) .join(Trolley.class) // 关联Trolley对象 .filter((step, trolley) -> { // 计算所需桶数(向上取整) long requiredBuckets = (step.getProductVolume() + trolley.getBucketCapacity() - 1) / trolley.getBucketCapacity(); return requiredBuckets > trolley.getBucketNum(); // 超出现有桶数则触发约束 }) .penalizeLong("Required number of buckets", HardSoftLongScore.ONE_SOFT, (step, trolley) -> { long requiredBuckets = (step.getProductVolume() + trolley.getBucketCapacity() - 1) / trolley.getBucketCapacity(); return requiredBuckets - trolley.getBucketNum(); // 按超出数量扣分 }); }
3. 检查ConstraintVerifier初始化
确保你的verifier初始化时正确绑定了约束提供者和解决方案类,否则约束可能无法被正确加载:
@BeforeEach void setUp() { verifier = ConstraintVerifier.build() .withConstraintProvider(new OrderPickingConstraintProvider()) .withSolutionClass(你的解决方案类.class) // 替换为包含Trolley、TrolleyStep的Solution类 .build(); }
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

