在 OptaPlanner 中使用 HardSoftDoubleScore 对 DRL 评分规则进行评分损坏
Score corruption with DRL Score rule with HardSoftDoubleScore in OptaPlanner
你好。
我尝试使用 optaplanner 解决一些优化问题,但出现了一些错误。
版本:Optaplanner 6.5.1 - 快照
乐谱类型:硬软双乐谱
评分方法: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
这是我的Class图表
ClassDiagram
使用上述设置,在构造启发式步骤中,发生以下错误
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)
我的修正点在哪里?
请帮帮我~~^^
这两个有什么区别?
- 0.0硬/-34.78590672782873软
- 0.0硬/-34.785906727828745软
答案:由于浮点运算导致的舍入误差。
HardSoftDoubleScore
的 Javadoc:
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));
请参阅文档部分 Avoid Floating Point Numbers in Score Calculation 了解如何解决该问题。
你好。
我尝试使用 optaplanner 解决一些优化问题,但出现了一些错误。
版本:Optaplanner 6.5.1 - 快照
乐谱类型:硬软双乐谱
评分方法: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
这是我的Class图表
ClassDiagram
使用上述设置,在构造启发式步骤中,发生以下错误
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)
我的修正点在哪里?
请帮帮我~~^^
这两个有什么区别?
- 0.0硬/-34.78590672782873软
- 0.0硬/-34.785906727828745软
答案:由于浮点运算导致的舍入误差。
HardSoftDoubleScore
的 Javadoc:
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));
请参阅文档部分 Avoid Floating Point Numbers in Score Calculation 了解如何解决该问题。