如何在触发afterVariableChanged前完成AnchorShadowVariable设置?
问题解答
你观察到的调用顺序是OptaPlanner链式变量模型的默认设计,无法直接调整内置锚点影子变量的更新顺序早于自定义的genuine变量监听器。OptaPlanner的执行逻辑中,针对原生规划变量的自定义监听器优先级始终高于内置的锚点、前后元素这类链式影子变量的更新监听器,因此你在afterVariableChanged中直接调用getAnchorShadowVariable()拿到的永远是上一次的旧值。
以下是两种成熟的可行替代方案:
方案1:使用内置供给工具直接获取最新锚点
OptaPlanner已经提供了开箱即用的锚点查询工具,不需要你自己递归遍历链表,内部做了缓存优化,查询效率极高,是官方推荐的处理方式。
具体使用方式:
- 在变量监听器的初始化阶段,通过
ScoreDirector的供给管理器提前获取锚点供给实例
// 初始化方法中执行一次即可 AnchorVariableSupply anchorSupply = scoreDirector.getSupplyManager() .demand(new AnchorVariableDemand(planningEntityDescriptor.getGenuineVariableDescriptor("previous")));
- 在
afterVariableChanged方法中直接调用获取最新锚点
// 直接获取当前实体对应的最新锚点,无需递归 Vehicle anchor = (Vehicle) anchorSupply.getAnchor(visit); // 后续直接从anchor获取运载方式计算到达时间即可
方案2:调整影子变量的监听依赖
如果你必须要通过getAnchorShadowVariable()方法获取锚点,可以将你的到达时间影子变量的监听源调整为同时包含原生规划变量和锚点影子变量,这样在锚点更新完成后,你的监听器会被第二次触发,此时就能拿到最新的锚点值:
@ShadowVariable( sources = { @PlanningVariableReference(variableName = "previous"), @PlanningVariableReference(variableName = "anchor") }, variableListenerClass = ArrivalTimeVariableListener.class ) public Long getArrivalTime() { return arrivalTime; }
内容的提问来源于stack exchange,提问作者Magnus Våge
相关产品推荐
相关产品推荐

