Hellow.
I try to solve some optimization problem using optaplanner, some error is happened.
Version: Optaplanner 6.5.1 - Snapshot
Score Type: Hard Soft Double Score
Score Method: DRL
rule "Insert count collections per manager in same grade"
salience 10
when
$gradeClass: GradeInfo($grade: grade)
$managerClass: ManagerInfo()
accumulate(
CollectionInfo(
manager == $managerClass,
$recoveryGrade: recoveryGrade == $grade),
$count : count($recoveryGrade))
then
insertLogical(new GradeStatic($gradeClass, $managerClass, $count.longValue()));
end
rule "Insert Compare total Receivables for each group"
salience 10
when
$groupClass: GroupInfo($groupId: groupId)
$managerClass: ManagerInfo($managerName: name, groupId == $groupId)
accumulate(
CollectionInfo(
manager == $managerClass,
$receivables : receivables),
$sum : sum($receivables))
then
insertLogical(new GroupStatic($groupClass, $managerClass, $sum.doubleValue()));
end
// Hard constraints
rule "Hard Score 1 Weight And Receivables"
when
GroupStatic($highReceivable: totalReceivables, $weight: groupInfo.weight)
GroupStatic(groupInfo.weight < $weight, $lowReceivable: totalReceivables)
eval($highReceivable < $lowReceivable)
then
scoreHolder.addHardConstraintMatch(kcontext, -$lowReceivable);
end
rule "Hard Score 2-3 There is a manager who is not arranged collecion"
when
accumulate(
GradeStatic(
$arrangedManagerName: managerInfo.name),
$arrangedManagerCnt : count($arrangedManagerName))
accumulate(
ManagerInfo($managerName: name),
$managerCnt : count($managerName))
accumulate(
GradeInfo($grade: grade),
$gradeCnt : count($grade))
eval($arrangedManagerCnt < $managerCnt * $gradeCnt)
then
scoreHolder.addHardConstraintMatch(kcontext, -99999999.0);
end
// Soft constraints
rule "Calculate Soft Score"
when
GroupStatic($totalReceivables: totalReceivables, $weight: groupInfo.weight)
accumulate(
CollectionInfo(
$receivables: receivables),
$average: average($receivables))
then
System.out.println("Soft Score: "+ Math.abs($average.doubleValue() - ($totalReceivables / $weight))/1000000.0);
scoreHolder.addSoftConstraintMatch(kcontext, -(Math.abs($average.doubleValue() - ($totalReceivables / $weight)))/1000000.0);
end
Here is my Class Diagram
With above Setting, In Construction Heuristic Step, below error is happened
2017-03-30 17:59:44,853 [main] DEBUG CH step (2), time spent (246), score (0.0hard/-34.78590672782874soft), selected move count (1), picked move (CollectionInfo-72 {null -> ManagerInfo-0}).
Soft Score: 4.969724770642201
...
Soft Score: 4.969724770642201
Soft Score: 4.966641437308868
Soft Score: 4.969724770642201
...
Soft Score: 4.969724770642201
Soft Score: 4.967558103975534
Soft Score: 4.969724770642201
...
Soft Score: 4.969724770642201
Soft Score: 4.967558103975534
Exception in thread "main" java.lang.IllegalStateException: Score corruption: the workingScore (0.0hard/-34.78590672782873soft) is not the uncorruptedScore (0.0hard/-34.785906727828745soft) after completedAction (Undo(CollectionInfo-39 {null -> ManagerInfo-0})):
The corrupted scoreDirector has no ConstraintMatch(s) which are in excess.
The corrupted scoreDirector has no ConstraintMatch(s) which are missing.
The corrupted scoreDirector has no ConstraintMatch(s) in excess or missing. That could be a bug in this class (class org.optaplanner.core.impl.score.director.drools.DroolsScoreDirector).
Check your score constraints.
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.assertWorkingScoreFromScratch(AbstractScoreDirector.java:378)
at org.optaplanner.core.impl.phase.scope.AbstractPhaseScope.assertExpectedUndoMoveScore(AbstractPhaseScope.java:142)
at org.optaplanner.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.doMove(ConstructionHeuristicDecider.java:124)
at org.optaplanner.core.impl.constructionheuristic.decider.ConstructionHeuristicDecider.decideNextStep(ConstructionHeuristicDecider.java:93)
at org.optaplanner.core.impl.constructionheuristic.DefaultConstructionHeuristicPhase.solve(DefaultConstructionHeuristicPhase.java:72)
at org.optaplanner.core.impl.solver.DefaultSolver.runPhases(DefaultSolver.java:215)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:176)
at org.optaplanner.examples.collectionarrange2.app.CollectionArrangeHelloWorld.main(CollectionArrangeHelloWorld.java:51)
Where is my correction point?
Please help me~~^^
What's the difference between these two?
Answer: a rounding error due to floating point arithmetic.
Javadocs of HardSoftDoubleScore
:
WARNING: NOT RECOMMENDED TO USE DUE TO ROUNDING ERRORS THAT CAUSE SCORE CORRUPTION. For example, this prints false:
System.out.println((0.01 + 0.05) == (0.01 + 0.02 + 0.03));
See the documentation section Avoid Floating Point Numbers in Score Calculation on how to work around that.