2016-04-11 2 views
1

Je jouais avec les variables d'ombre personnalisées et les écouteurs de variables personnalisées. J'ai trouvé que l'exemple "Exam timetabling" utilise des variables d'ombre personnalisées pour mettre à jour "Examens suivants" lorsque l'examen "principal" change. J'ai ajouté une deuxième variable shadow dans la classe Exam suivante qui fait référence à la variable "period", puis dans l'écouteur variable de l'entité de planification LeadingExam (PeriodUpdatingVariableListener) je mets à jour les deux les variables.VariableListener corruption

Voici le code pour la « FollowingExam » classe

@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; 
} 

} 

Et dans le « PeriodUpdatingVariableListener » J'ai le code suivant

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"); 

    } 
} 

} 

Il semble aussi que qu'il n'y a pas de problème pour OptaPlanner enregistrement que c'est une autre variable d'ombre parce que je reçois ce message quand je cours l'application

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) 

L'erreur que j'obtiens est la prochaine erreur, cette erreur apparaît seulement quand je change le mode d'environnement à FULL_ASSERT, mais quand il est laissé à REPRODUCIBLE par défaut il s'exécute sans erreurs.

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) 

Répondre

2

Ce code dans un écouteur de variable est mauvaise:

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

Si elle est appelée à plusieurs reprises, les changements var, même si le véritable var n'a pas changé. Si cette variable est utilisée dans les règles de score, le score de la solution n'est pas toujours le même pour la même solution.

Une variable d'ombre est la mise en cache du résultat d'une formule basée sur au moins 1 véritable variable (directement ou indirectement). Par exemple ombre C = véritable A + propriété de problème B. Donc, si B est 10 et va de 1 à 5, alors C sera 11 si A est 1, 12 si A est 2, etc

+0

Merci pour votre aide tout a plus de sens maintenant. –