首页 > 解决方案 > Optaplanner 影子变量损坏检查机制

问题描述

我在使用 FULL_ASSERT 的构造启发式阶段遇到分数损坏异常:

java.lang.IllegalStateException: VariableListener 损坏:实体 (Task{6661-30}) 的影子变量 (Task.plannedDateTime) 的损坏值 (null) 更改为未损坏值 (2018-06-04T07:00) 毕竟VariableListeners 被触发而不改变真正的变量。也许该影子变量 (Task.plannedDateTime) 的 VariableListener 类 (VrpTaskStartTimeListener) 在完成操作 (Task{6661-30} {Shift{Tech1:2018-06-04} -> Shift{技术 1:2018-06-04}})。

在 org.optaplanner.core.impl.score.director.AbstractScoreDirector.assertShadowVariablesAreNotStale(AbstractScoreDirector.java:462) 在 org.optaplanner.core.impl.solver.scope.DefaultSolverScope.assertShadowVariablesAreNotStale(DefaultSolverScope.java:140) 在 org.optaplanner .core.impl.phase.scope.AbstractPhaseScope.assertShadowVariablesAreNotStale(AbstractPhaseScope.java:171) 在 org.optaplanner.core.impl.phase.AbstractPhase.predictWorkingStepScore(AbstractPhase.java:169) 在 org.optaplanner.core.impl.constructionheuristic .DefaultConstructionHeuristicPhase.doStep(DefaultConstructionHeuristicPhase.java:108) at org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:95) at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:87) 在 org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:173) 在...

现在在查看 DefaultConstructionHeuristicPhase.doStep 时,它确实:

private void doStep(ConstructionHeuristicStepScope<Solution_> stepScope) {
        Move<Solution_> nextStep = stepScope.getStep();
        nextStep.doMove(stepScope.getScoreDirector()); //Step-1
        predictWorkingStepScore(stepScope, nextStep);
        ...
    }

predictWorkingStepScore()调用AbstractScoreDirector.assertShadowVariablesAreNotStale()并且assertShadowVariablesAreNotStale()是:

    public void assertShadowVariablesAreNotStale(Score expectedWorkingScore, Object completedAction) {
                SolutionDescriptor<Solution_> solutionDescriptor = getSolutionDescriptor();
    //Step2
                Map<Object, Map<ShadowVariableDescriptor, Object>> entityToShadowVariableValuesMap = new IdentityHashMap<>();
                ...
                    entityToShadowVariableValuesMap.put(entity, shadowVariableValuesMap);
                }
//Step3
                variableListenerSupport.triggerAllVariableListeners();
                for (Iterator<Object> it = solutionDescriptor.extractAllEntitiesIterator(workingSolution); it.hasNext();) {
                    Object entity = it.next();
                    EntityDescriptor<Solution_> entityDescriptor
                            = solutionDescriptor.findEntityDescriptorOrFail(entity.getClass());
                    Collection<ShadowVariableDescriptor<Solution_>> shadowVariableDescriptors = entityDescriptor.getShadowVariableDescriptors();
                    Map<ShadowVariableDescriptor, Object> shadowVariableValuesMap = entityToShadowVariableValuesMap.get(entity);
                    for (ShadowVariableDescriptor shadowVariableDescriptor : shadowVariableDescriptors) {
                        Object newValue = shadowVariableDescriptor.getValue(entity);
                        Object originalValue = shadowVariableValuesMap.get(shadowVariableDescriptor);
    //Step4
                        if (!Objects.equals(originalValue, newValue)) {
                            throw new IllegalStateException(VariableListener.class.getSimpleName() + " corruption:"

        }
        }

这是描述,我相信:

现在,问题出在真正变量上的自定义侦听器上,顺序如下:

  1. 反向关系影子变量监听器
  2. 自定义监听器
  3. 锚阴影变量

我该怎么做才能使自定义侦听器最后执行?

标签: optaplanner

解决方案


正确配置 的sources属性@CustomShadowVariable

有这个保证: 在此处输入图像描述


推荐阅读