optaplanner - 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 步:执行 step 的 move(它也执行 shadow var listeners)
- 第 2 步:获取当前实体 shadow vars 值。(这里 shadow vars 没有有效值)
- 第 3 步:执行 ShadowsVariable listehttp://example.comners(现在阴影将具有正确的值)
- 第 4 步:获取新值并与第 2 步进行比较。
现在,问题出在真正变量上的自定义侦听器上,顺序如下:
- 反向关系影子变量监听器
- 自定义监听器
- 锚阴影变量
我该怎么做才能使自定义侦听器最后执行?
解决方案
推荐阅读
- reactjs - Firebase On Value 获取状态反应钩子
- json - 递归地将 JSON 切片为数据框列
- spring-boot - 如何在spring中创建注释
- html - “Background-size:” 不影响背景图片 HTML CSS Flask
- python-3.x - 有什么方法可以改革 ptyhon 的 list 和 dic 中的建设吗?
- python - 任意上报 MemoryError 和 OverflowError
- reactjs - 使用 React + Redux 设计 Websocket
- java - Java 明显死锁
- c++ - 为什么此代码中存在分段错误?
- pdf - r 中的制表器库在 PDF 中识别表格上的非字母数字(符号)字符时出现问题