You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 09:45:25