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

OptaPlanner ProblemFact引用的规划实体反向关系影子变量未更新问题

问题根因

OptaPlanner的默认解决方案克隆机制遵循以下规则:仅克隆标注了@PlanningEntity的类实例,@ProblemFact类的实例会被直接复用。你的场景中:

  • Agent是规划实体,求解过程中会生成克隆副本,所有的影子变量shiftSet更新都作用在这个克隆副本上
  • AgentAvailability是问题事实,实例直接复用,其内部存储的agent引用指向初始输入的原始Agent实例,该实例的shiftSet从未被更新,因此永远为空

可行解决方案

方案1:调整约束写法(最推荐)

完全不需要修改现有类结构,仅调整约束逻辑即可,通过@PlanningId匹配关联正确的克隆Agent实例,示例代码如下:

return constraintFactory.from(Agent.class)
        // 关联匹配同ID的AgentAvailability
        .join(AgentAvailability.class,
              Joiners.equal(Agent::getRegistrationNumber, availability -> availability.getAgent().getRegistrationNumber()))
        // 按Agent分组统计可用时段数
        .groupBy((agent, availability) -> agent, count())
        .filter((agent, availabilities) -> availabilities - agent.getShiftSet().size() > 0)
        .penalizeConfigurableLong(ShiftSchedulingConstraintConfiguration.PRO_HAS_SHIFT, 
                                  (agent, availabilities) -> availabilities - agent.getShiftSet().size());

该方案无需改动核心模型,也不会引入额外风险,是最优选择。

方案2:自定义解决方案克隆器

如果你必须保留原有约束写法,可以为Schedule实现自定义克隆器,在克隆完成后手动修正AgentAvailability中的Agent引用:

  1. 实现SolutionCloner<Schedule>接口,克隆完成后遍历所有AgentAvailability,通过registrationNumber匹配克隆后的Agent实例,替换原有引用
  2. 在@PlanningSolution注解上指定cloner = 你自定义的克隆器类.class
    注意该方案需要你自行保证克隆逻辑的正确性,避免破坏OptaPlanner的求解流程。

禁止操作

不要尝试同步原始Agent实例和克隆Agent实例的shiftSet值,OptaPlanner求解过程是多线程运行的,修改原始实例会引发线程安全问题,直接导致求解结果错误。


内容的提问来源于stack exchange,提问作者minioim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:54:03