【发布时间】:2018-06-13 18:26:56
【问题描述】:
我在使用 FULL_ASSERT 的构造启发式阶段遇到分数损坏异常:
java.lang.IllegalStateException:VariableListener 损坏: 实体 (Task{6661-30}) 的影子变量 (Task.plannedDateTime) 的 损坏的值 (null) 更改为未损坏的值 (2018-06-04T07:00) 在所有 VariableListeners 都被触发而不改变 真正的变量。也许是 VariableListener 类 (VrpTaskStartTimeListener) 为那个影子变量 (Task.plannedDateTime) 当它的一个来源忘记更新它 完成操作后更改(任务{6661-30} {Shift{Tech1:2018-06-04} -> 转移{Tech1: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) 在 org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:95) 在 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 步:执行 step 的 move(它还执行 shadow var listeners)
- 第 2 步:获取当前实体 shadow vars 值。(此处为 shadow vars 不会有有效值)
- 第三步:执行ShadowsVariable listehttp://example.comners(now 阴影将具有正确的值)
- 第 4 步:获取新值并进行比较 与步骤 2。
现在,问题出在真正变量上的自定义侦听器上,顺序如下:
- 反向关系影子变量监听器
- 自定义监听器
- 锚阴影变量
我该怎么做才能使自定义侦听器最后执行?
【问题讨论】:
标签: optaplanner