Reputation: 21
My local search part in solver config looks like:
<acceptor>
<lateAcceptanceSize>400</lateAcceptanceSize>
<entityTabuSize>9</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>2000</acceptedCountLimit>
</forager>
and everything works fine but when I change it to(what can cause optimization gain I think):
<acceptor>
<lateAcceptanceSize>600</lateAcceptanceSize>
</acceptor>
<forager>
<acceptedCountLimit>4</acceptedCountLimit>
</forager>
After solver starts working I got exception
Score corruption: the solution's score (-20hard/-8medium/-4soft) is not the uncorruptedScore (-20hard/-8medium/-8soft)
What can cause this problem? (It is only information from FULL_ASSERT mode)
EDIT:
Something can be connected to rule:
// Boundary lessons have to be schedulead at the beginning/end in a day
rule "boundaryLesson"
when
$oddzial : Oddzial()
$boundaryLesson : Lesson(scheduled == true, containsOddzial($oddzial), base.lessonLimits.isBoundaryLesson == true, $base : base)
exists Lesson(scheduled == true, containsOddzial($oddzial), dayLessonNumber.day == $base.day, base.lessonNumberFrom < $base.lessonNumberFrom)
and exists Lesson(scheduled == true, containsOddzial($oddzial), dayLessonNumber.day == $base.day, base.lessonNumberTo > $base.lessonNumberTo)
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
because, sometimes I get following error also:
Score corruption: the workingScore (0hard/-2medium/0soft) is not the uncorruptedScore (-1hard/-2medium/0soft) after completedAction (8848-537:Tuesday-3 {com.pbz.plek.model.simple.DayLessonNr@5924af87 -> com.pbz.plek.model.simple.DayLessonNr@5924af87}):
The corrupted scoreDirector has no ConstraintMatch(s) which are in excess.
The corrupted scoreDirector has 1 ConstraintMatch(s) which are missing:
com.praca.mgr.cp.algorytm.solver/boundaryLesson/level0/[8854-537:Tuesday-2, com.krakfin.pbz.plek.model.simple.Oddzial@c9d4]=-1
Check your score constraints.
I know how incremental score calculation works but I cannot see what can be wrong with this rule
Upvotes: 1
Views: 709
Reputation: 21
To sum up:
Problems with corrupted score exists at every score level so I left only hard constraints rules section, which looks like that:
// ############################################################################ // Hard constraints // ############################################################################
// two Lessons at the same time should be in another rooms.
rule "salaOccupancy"
when
$leftLesson : Lesson($id : base.numericId, scheduled == true, $sala : sala)
not Lesson(scheduled == true, timeCollision($leftLesson), sala == $sala, base.numericId < $id)
$rightLesson : Lesson(scheduled == true, timeCollision($leftLesson), sala == $sala, base.numericId > $id)
then
scoreHolder.addHardConstraintMatch(kcontext, -10);
end
// each oddzial and nauczyciel can't have two lessons at the same time
rule "przydzialCollision"
when
$przydzialConflict : PrzydzialConflict($leftPrzydzial : leftPrzydzial, $rightPrzydzial : rightPrzydzial)
$leftLesson : Lesson(scheduled == true, base.przydzial == $leftPrzydzial)
$rightLesson : Lesson(scheduled == true, base.przydzial == $rightPrzydzial, timeCollision($leftLesson), this != $leftLesson)
then
scoreHolder.addHardConstraintMatch(kcontext, -2 * $przydzialConflict.getConflictCount());
end
// sala's capacity shouldn't be exceeded
rule "salaCapacity"
when
$sala : Sala($capacity : ograniczenia.maxLiczbaUczniow.max)
$lesson : Lesson(scheduled == true, sala == $sala)
$limit : LessonStudentLimit(lesson == $lesson, numberOfStudents > $capacity)
then
scoreHolder.addHardConstraintMatch(kcontext, -2);
end
// cannot put lesson into not available time period in Sala or Przydzial
rule "availability"
when
Lesson( scheduled == true , dostepnaSala == false )
or Lesson( scheduled == true , dostepnyPrzydzial == false)
then
scoreHolder.addHardConstraintMatch(kcontext, -2);
end
// Oddzials cannot have gaps between classes during a day
rule "gaps"
when
$oddzial : Oddzial()
$dzien : DzienTygodnia()
$lessonList : ArrayList(LessonBlockCounter.calculateOddzialGaps($lessonList,TimetableSolution.maxLessonNr)>0) from collect (
Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $dzien)
)
then
scoreHolder.addHardConstraintMatch(kcontext, -5*LessonBlockCounter.calculateOddzialGaps($lessonList,TimetableSolution.maxLessonNr));
end
// If Przydzial has blocks distribution defined, only one lesson per day is allowed
rule "blocks"
when
$przydzial : Przydzial( ograniczenia.ograniczeniaBlokiLekcyjnePrzydzialu.czyTylkoJednaLekcjaNaDzien.isAktywne() == true )
$dzien : DzienTygodnia()
$lessonCount : Number( intValue > 1 ) from accumulate (
$lesson : Lesson(scheduled == true, base.przydzial == $przydzial,dzienNrLekcji.dzien == $dzien),
count($lesson)
)
then
scoreHolder.addHardConstraintMatch(kcontext, -2);
end
// Boundary lessons have to be schedulead at the beginning/end in a day
rule "boundaryLesson"
when
$oddzial : Oddzial()
$boundaryLesson : Lesson(scheduled == true, containsOddzial($oddzial), base.ograniczeniaLekcja.czyLekcjaGraniczna.aktywne == true, $base : base)
exists Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $base.dzien, base.lekcjaNrOd < $base.lekcjaNrOd)
and exists Lesson(scheduled == true, containsOddzial($oddzial), dzienNrLekcji.dzien == $base.dzien, base.lekcjaNrDo > $base.lekcjaNrDo)
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
// Linked lessons have to take place at the same time
rule "linkedLesson"
when
$linkedLesson : Lesson(scheduled == true, base.ograniczeniaLekcja.lekcjePolaczone.empty == false, $dzienNrLekcji : dzienNrLekcji)
Lesson(scheduled == true, base.ograniczeniaLekcja.lekcjePolaczone contains $linkedLesson.base, dzienNrLekcji != $dzienNrLekcji)
then
scoreHolder.addHardConstraintMatch(kcontext, -5);
end
// Linked lessons have to take place at the same time
rule "scheduledLinkedLesson"
when
$linkedLesson : Lesson(scheduled == false, base.ograniczeniaLekcja.lekcjePolaczone.empty == false)
then
scoreHolder.addHardConstraintMatch(kcontext, -10*$linkedLesson.getBase().getCzasTrwania());
end
// Lessons have to be placed in the school time boundaries
rule "schoolTime"
when
$lesson : Lesson(scheduled == true, base.czasTrwania > 1 , base.lekcjaNrOd > TimetableSolution.maxLessonNr - base.czasTrwania)
then
scoreHolder.addHardConstraintMatch(kcontext, -5);
end
// Lessons have to be scheduled in one of the preferred sala
rule "assignedSalaPrzydzialu"
when
$lesson : Lesson( scheduled == true,
sala not memberOf base.przydzial.ograniczenia.perferowaneSale.preferowaneSale.saleList )
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
// ############################################################################
// Medium constraints
// ############################################################################
//lesson have to have sala and day assigned, not assigned lessons are acceptable in overconstrained problem
rule "scheduledLesson"
when
$lesson : Lesson( scheduled == false )
then
scoreHolder.addMediumConstraintMatch(kcontext, -$lesson.getBase().getCzasTrwania());
end
After running algorithm, I'am getting exception:
2015-11-04 10:39:21,493 [http-8080-3] INFO org.optaplanner.core.impl.solver.DefaultSolver - Solving started: time spent (426), best score (uninitialized/-160hard/-165medium/0soft), environment mode (FULL_ASSERT), random (JDK with seed 0).
2015-11-04 10:39:23,969 [http-8080-3] INFO org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase - Construction Heuristic phase (0) ended: step total (165), time spent (2903), best score (-160hard/-165medium/0soft).
2015-11-04 10:39:24,615 [http-8080-3] ERROR org.apache.struts2.dispatcher.Dispatcher - Exception occurred during processing request: Score corruption: the solution's score (-123hard/-161medium/0soft) is not the uncorruptedScore (-126hard/-160medium/0soft).
java.lang.IllegalStateException: Score corruption: the solution's score (-123hard/-161medium/0soft) is not the uncorruptedScore (-126hard/-160medium/0soft).
at org.optaplanner.core.impl.score.director.AbstractScoreDirectorFactory.assertScoreFromScratch(AbstractScoreDirectorFactory.java:100)
at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.assertScoreFromScratch(DefaultSolverScope.java:127)
at org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller.processWorkingSolutionDuringStep(BestSolutionRecaller.java:107)
...
After studied problem I am pretty sure that it's connected with incremental score calculation and drl file. I thought that problem causes "gaps" rule because "calulateOddzialGaps" method checks day and lesson number of collected $lessonList, but after commented this rule problem still exists. Any other rule doesn't use lessons(planningEntity) at WHEN section inside java method. What can be wrong? I don't have any other ideas...
Upvotes: 0
Reputation: 27312
In both cases you'll have potential score corruption, but only in the second case it surfaces. For production reliability, you'll definitely want to fix it.
See docs on "incremental score calculation" to understand what score corruption is. Usual causes:
processWorkingSolutionDuringStep()
.If you use Drools calculation:
If you use incremental score calculation:
<assertScoreDirectorFactor>
with an easy score calculator too. Good luck in this case.Upvotes: 1