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

Optaplanner多规划实体建模报错及优化方案咨询

问题

基于OptaPlanner的Task Assigning示例进行变体开发,业务中存在多种任务类型,每种类型有独特规划变量,因此将这些任务建模为多个规划实体,均继承自抽象类Activity,该类又继承根类ActivityOrActor。解决方案构建完成后出现如下错误:

INFO  [15:37:33] DefaultSolver |  Solving started: time spent (98), best score (0hard/0soft), environment mode (FULL_ASSERT), move thread count (4), random (JDK with seed 1).
INFO  [15:37:33] DefaultConstructionHeuristicPhase |  Construction Heuristic phase (0) ended: time spent (130), best score (0hard/0soft), score calculation speed (200/sec), step total (0).
INFO  [15:37:33] DefaultConstructionHeuristicPhase |  Construction Heuristic phase (1) ended: time spent (152), best score (0hard/0soft), score calculation speed (294/sec), step total (0).
 Exception in thread "main" java.lang.IllegalStateException: The move thread with moveThreadIndex (0) has thrown an exception. Relayed here in the parent thread.
        at org.optaplanner.core.impl.heuristic.thread.OrderByMoveIndexBlockingQueue.take(OrderByMoveIndexBlockingQueue.java:131)
        at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.forageResult(MultiThreadedLocalSearchDecider.java:185)
        at org.optaplanner.core.impl.localsearch.decider.MultiThreadedLocalSearchDecider.decideNextStep(MultiThreadedLocalSearchDecider.java:150)
        at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:72)
        at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:83)
        at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:193)
        at com.macro_optimizer.domain.solution.solver.MacroSolutionSolver.solve(MacroSolutionSolver.java:38)
        at com.macro_optimizer.PlannerApp.main(PlannerApp.java:27)
Caused by: java.lang.IllegalStateException: The supply (ExternalizedSingletonInverseVariableSupply(previousActivityOrActor)) is corrupted, because the entity (com.macro_optimizer.domain.activity.Deploy@418aaae1) for sourceVariable (previousActivityOrActor) cannot be inserted: another entity (com.macro_optimizer.domain.activity.Deploy@63aaede0) already has that value (com.macro_optimizer.domain.activity.Deploy@3585120c).
        at org.optaplanner.core.impl.domain.variable.inverserelation.ExternalizedSingletonInverseVariableSupply.insert(ExternalizedSingletonInverseVariableSupply.java:83)
        at org.optaplanner.core.impl.domain.variable.inverserelation.ExternalizedSingletonInverseVariableSupply.afterVariableChanged(ExternalizedSingletonInverseVariableSupply.java:61)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerAfter(VariableChangedNotification.java:20)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableChangedNotification.triggerAfter(VariableChangedNotification.java:6)
        at org.optaplanner.core.impl.domain.variable.listener.support.AbstractNotifiable.triggerAllNotifications(AbstractNotifiable.java:84)
        at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.triggerVariableListenersInNotificationQueues(VariableListenerSupport.java:180)
        at org.optaplanner.core.impl.score.director.AbstractScoreDirector.triggerVariableListeners(AbstractScoreDirector.java:261)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMoveOnly(AbstractMove.java:27)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:20)
        at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:15)
        at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:195)
        at org.optaplanner.core.impl.heuristic.thread.MoveThreadRunner.run(MoveThreadRunner.java:131)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)

2022-08-24更新:已将所有规划变量从抽象Activity类移至具体活动类,且仅保留一种活动类型(规划实体数量为1)进行优化测试,仍出现相同错误。

解决建议

错误排查与修复

核心问题是previousActivityOrActor这个单例逆变量的约束被打破:两个不同的Deploy实体同时指向了同一个前置实体,违反了每个前置实体只能被一个后续实体引用的唯一性规则。按以下步骤排查修复:

  • 检查注解配置:确认previousActivityOrActor的@InverseRelationShadowVariable注解是否关联了正确的源变量(比如nextActivityOrActor),且源变量的逻辑确保每个实体只能有一个后续实体。
  • 验证初始数据:检查初始解决方案中是否存在多个实体的previousActivityOrActor指向同一实体的情况——FULL_ASSERT模式会严格校验这种约束,初始数据违规直接触发报错。
  • 排查自定义逻辑:如果有自定义变量监听器或移动实现,检查修改变量时是否正确维护了逆变量的唯一性,比如修改某实体的前置变量时,是否遗漏了清除原前置实体的对应后续引用。
  • 临时切换单线程:将solverConfig中的moveThreadCount设为1,排除多线程环境下的变量同步问题,确认错误是否由多线程逻辑冲突导致。

领域建模优化(减少规划实体数量)

如果希望简化模型、减少规划实体类型,可采用以下思路:

  • 统一实体+类型字段:将所有任务合并为一个Activity规划实体,用taskType枚举区分类型,针对不同类型的独特规划变量,使用@Nullable标记为可选变量,在分数计算时仅对对应类型的任务校验该变量的约束。
  • 共享抽象+扩展变量:在抽象Activity类中定义通用规划变量(如previousActivityOrActor),具体任务类中扩展独特变量,确保影子变量、逆变量的注解在继承体系中配置一致,避免约束冲突。
  • 规划值分组替代多实体:如果不同任务类型需要分配到特定资源组,可给规划值(如Actor)添加分组标签,通过约束规则限制任务类型与资源组的匹配关系,无需拆分多个规划实体。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:18:17