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

Optaplanner自定义影子变量报错:如何修复通知计数异常问题?

问题修复方案

错误原因分析

你遇到的IllegalStateException是因为VariableListener的实现违反了OptaPlanner的核心规则:

  • 错误地针对真实规划变量x调用了beforeVariableChanged/afterVariableChanged,而非要更新的影子变量y
  • 方法内引用了未定义的sourcevariable,应该使用方法传入的variable参数
  • 泛型参数和类名不符合Java命名规范(首字母需大写,如PlanningSolution、Variable)

修正后的VariableListener代码

public class YVariableListener implements VariableListener<PlanningSolution, Variable> {

    @Override
    public void beforeEntityAdded(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 初始化影子变量y
        scoreDirector.beforeVariableChanged(variable, "y");
        variable.setY(variable.getX() * 10);
        scoreDirector.afterVariableChanged(variable, "y");
    }

    @Override
    public void afterEntityAdded(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 无需额外操作
    }

    @Override
    public void beforeVariableChanged(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 无需额外操作
    }

    @Override
    public void afterVariableChanged(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 更新影子变量y
        scoreDirector.beforeVariableChanged(variable, "y");
        variable.setY(variable.getX() * 10);
        scoreDirector.afterVariableChanged(variable, "y");
    }

    @Override
    public void beforeEntityRemoved(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 无需额外操作
    }

    @Override
    public void afterEntityRemoved(ScoreDirector<PlanningSolution> scoreDirector, Variable variable) {
        // 无需额外操作
    }
}

关键修正点说明

  1. 针对影子变量操作:更新影子变量y时,必须调用scoreDirector.beforeVariableChanged(variable, "y")和scoreDirector.afterVariableChanged(variable, "y"),告知ScoreDirector要修改的是影子变量y,而非真实变量x。
  2. 初始化影子变量:在beforeEntityAdded方法中初始化y,确保实体添加时影子变量就有正确值,避免初始分数计算错误。
  3. 修正变量引用:使用方法传入的variable参数,替代未定义的sourcevariable。
  4. 规范命名:泛型参数和类名遵循Java大驼峰命名规范(如PlanningSolution、Variable、YVariableListener)。

额外检查项

确保在PlanningEntity类中,影子变量y通过@ShadowVariable注解正确关联到真实变量x:

@PlanningEntity
public class Variable {
    @PlanningVariable(...)
    private Integer x;

    @ShadowVariable(variableListenerClass = YVariableListener.class, sourceVariableName = "x")
    private Integer y;

    // getter和setter方法
    public Integer getX() { return x; }
    public void setX(Integer x) { this.x = x; }
    public Integer getY() { return y; }
    public void setY(Integer y) { this.y = y; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 10:15:47