当前位置: 首页 > 知识库问答 >
问题:

可变侦听器损坏

鄢选
2023-03-14

我在玩自定义阴影变量和自定义变量侦听器。我发现“考试时间表”示例使用自定义阴影变量在“主要考试”更改时更新“后续考试”。因此,我在这个问题中所做的断言是真的自定义变量Listener更新了多个影子变量我在下面的考试类中添加了第二个影子变量,它引用了变量“period”,然后在LeadingExam计划实体的变量侦听器(PeriodUpdatengVariableListener)中,我更新了这两个变量。

这是“以下考试”课程的代码

@PlanningEntity
@XStreamAlias("FollowingExam")
public class FollowingExam extends Exam {

protected LeadingExam leadingExam;

// Shadow variables
protected Period period;
protected Integer var;

@CustomShadowVariable(variableListenerClass = PeriodUpdatingVariableListener.class, sources = {
        @CustomShadowVariable.Source(entityClass = LeadingExam.class, variableName = "period") })
public Period getPeriod() {
    return period;
}

public void setPeriod(Period period) {
    this.period = period;
}

@CustomShadowVariable(variableListenerRef = @PlanningVariableReference(variableName = "period"))
public Integer getVar() {
    return var;
}

public void setVar(Integer var) {
    this.var = var;
}

public LeadingExam getLeadingExam() {
    return leadingExam;
}

public void setLeadingExam(LeadingExam leadingExam) {
    this.leadingExam = leadingExam;
}

}

在“PeriodUpdatengVariableListener”中,我有下一个代码

public class PeriodUpdatingVariableListener implements VariableListener<LeadingExam> {

public void beforeEntityAdded(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    // Do nothing
}

public void afterEntityAdded(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    updatePeriod(scoreDirector, leadingExam);
}

public void beforeVariableChanged(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    // Do nothing
}

public void afterVariableChanged(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    updatePeriod(scoreDirector, leadingExam);
}

public void beforeEntityRemoved(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    // Do nothing
}

public void afterEntityRemoved(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    // Do nothing
}

protected void updatePeriod(ScoreDirector scoreDirector, LeadingExam leadingExam) {
    Period period = leadingExam.getPeriod();
    for (FollowingExam followingExam : leadingExam.getFollowingExamList()) {
        scoreDirector.beforeVariableChanged(followingExam, "period");
        followingExam.setPeriod(period);
        scoreDirector.afterVariableChanged(followingExam, "period");

        //additional lines of code to update the "var" variable
        Integer var = followingExam.getVar();
        if(var == null){
            var = new Integer(1);
        }
        else var++;
        scoreDirector.beforeVariableChanged(followingExam, "var");
        followingExam.setVar(var);
        scoreDirector.afterVariableChanged(followingExam, "var");

    }
}

}

OptaPlanner注册这是另一个影子变量似乎也没有问题,因为我在运行应用程序时收到了这条消息

2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE     Model annotations parsed for Solution Examination:
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE         Entity Exam:
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE             Variable room (genuine)
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE         Entity LeadingExam:
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE             Variable period (genuine)
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE         Entity FollowingExam:
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE             Variable period (shadow)
2016-04-11 15:26:15,309 [AWT-EventQueue-0] TRACE             Variable var (shadow)

我得到的错误是下一个错误,只有当我将环境模式更改为FULL_ASSERT时,才会出现此错误,但当它保留为默认的可复制时,它会运行而不会出现任何错误。

Caused by: java.lang.IllegalStateException: VariableListener corruption: the entity (426)'s shadow variable (FollowingExam.var)'s corrupted value (null) changed to uncorrupted value (1) after all VariableListeners were triggered without changes to the genuine variables.
Probably the VariableListener class for that shadow variable (FollowingExam.var) forgot to update it when one of its sources changed after completedAction (Initial score calculated).
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.assertShadowVariablesAreNotStale(AbstractScoreDirector.java:349)
at org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.solvingStarted(BestSolutionRecaller.java:84)
at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:196)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:175)
at org.optaplanner.examples.common.business.SolutionBusiness.solve(SolutionBusiness.java:307)
at org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame$SolveWorker.doInBackground(SolverAndPersistenceFrame.java:287)
at org.optaplanner.examples.common.swingui.SolverAndPersistenceFrame$SolveWorker.doInBackground(SolverAndPersistenceFrame.java:1)
at javax.swing.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at javax.swing.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

共有1个答案

秦珂
2023-03-14

变量侦听器中的此代码不正确:

    Integer var = followingExam.getVar();
    ...
    var++;
    ...
    followingExam.setVar(var);
    ...

如果多次调用,即使真正的var没有更改,var也会更改。如果在评分规则中使用该var,那么对于同一个解决方案,该解决方案的评分并不总是相同的。

阴影变量是基于至少一个真实变量(直接或间接)的公式结果的缓存。例如,阴影C=真正的问题属性B。因此,如果B是10,范围A从1到5,那么如果A是1,C将是11,如果A是2,等等。

 类似资料:
  • 问题内容: 我当时在上网,但找不到很好的信息。我试图在每次运行应用程序时检测按键。我正在使用JavaFX并将其与FXML一起运行。我尝试了很多事情,但没有任何效果。请帮我。 问题答案: 您应该签出Ensemble示例。这是关键的侦听器代码。

  • 我正在使用Realex Payments的HPP API开发一个卡支付页面,其中包含一个iFrame,用于托管Realex页面。在Realex请求表单上,我将字段HPP_POST_维度和HPP_POST_响应设置为我的URL,如下所示: 付款页: www.example.com/account/payment.html 隐藏字段值用于在HPP页面大小更改和事务完成时,使用事件侦听器将数据从Real

  • 虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过watch选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。例如: <div id="watch-example"> <p> Ask a yes/no question: <input v-model="question">

  • 1. 前言 本节介绍侦听器 watch 的使用方法。包括什么是侦听器,侦听器的特点,以及如何对不同类型的数据进行监听。其中重点掌握对不同类型的数据如何使用侦听器,了解它之后,在才能在之后的日常开发中熟练运用。 2. 慕课解释 Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。 — 官方定义 侦听器 watch 是 Vue 提供的一种用来观察和响应 Vue 实例上的数据

  • 我在我的一个工作流应用程序中使用了Camunda BPMN2.0。在我的一个服务任务中,我在start事件中创建了一个执行侦听器,在create事件中创建了一个任务侦听器。我不确定在开始时同时分配这些是否合适。如果是正确的,它们中的哪一个将首先执行--执行监听器或任务监听器,分别在start或create事件中执行?

  • 问题内容: 我正在尝试添加一个包含一个的键侦听器。 当收到ctrl + tab时,应该切换标签。 但是按键事件从未发送过,我尝试将其添加到面板和选项卡式对象中,但是没有成功。 这是我的代码 问题答案: 通常,正确的Swing组件不会拦截您的按键事件。您必须了解,光标下方的第一个组件将收到键盘事件。如果您使用键盘选择一个按钮,则将是这个JButton接收按键事件。 为了确保获得所有这些事件,您不必在

  • 下面的代码是项目的动作侦听器。基本上,我有 4 个单选按钮,当我单击一个时,我希望它更改屏幕上的变量。当我运行代码时,它只是将所有值相加。还有其他方法可以做到这一点吗?

  • 如果该成员被弹出,我会看到MapLoader从数据库重新加载数据时,条目添加的侦听器被激发。 然而,这向客户机提示已经添加了新条目,而实际上,它们只是由于节点引导而被“添加”的。 基本上,我不希望这些侦听器由于MapLoader引导映射而被解雇--它们应该只在之后被解雇。 如何阻止这些MapLoader事件从EntryAdded侦听器中触发?