I'm still experimenting with Drools Planner and I also have the exact same
issue :
java.lang.IllegalStateException: The presumedScore (0hard/-1soft) is
corrupted because it is not the realScore (0hard/0soft).
Presumed workingMemory:
Score rule (soft-ReduceNullAssignment) has count (1) and weight total (1).
Real workingMemory:
at
org.drools.planner.core.solution.director.DefaultSolutionDirector.assertWorkingScore(DefaultSolutionDirector.java:157)
at
org.drools.planner.core.solver.DefaultSolverScope.assertWorkingScore(DefaultSolverScope.java:105)
at
org.drools.planner.core.phase.AbstractSolverPhaseScope.assertWorkingScore(AbstractSolverPhaseScope.java:132)
at
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:69)
at
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:166)
at
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:138)
...
I've read this (
), but it
didn't help :
- I'm using IntConstraintOccurrence
- I double check the soft constraint named "soft-ReduceNullAssignment"
-- it's include all the cause.
- I'm using Drools 5.3
After more digging, I think something is missing in
DefaultSolutionDirector.java:153. The facts are added, but the
planningEntity are not added. So when the score calculation is running,
there is two different result. I'v place a breakpoint
at DefaultSolutionDirector.java:157 and looking
in tmpWorkingMemory->defaultEntryPoint->objectStore->identifyMap->table, I
don't see the planningEntity.
Here is the my rule :
rule "soft-ReduceNullAssignment"
when
$planif : PlanifEventAssignment( employee == null )
then
insertLogical(new
IntConstraintOccurrence("soft-ReduceNullAssignment",
ConstraintType.NEGATIVE_SOFT,
1,
$planif));
end
Thanks
On Tue, Dec 6, 2011 at 11:12 AM, Geoffrey De Smet
<ge0ffrey.spam(a)gmail.com>wrote:
Op 06-12-11 05:38, guyramirez schreef:
> Still the same issue, starting with the construction heuristic phase.
Please
> let me know if you need more explanations in what I am trying to do.
>
> Here is the error. Please note that there is only one planning entity
> (ShiftAssignment) object instance in this test.
>
> Total Staffing required: 8
> 2011-12-05 22:21:49,627 [main] INFO Solver started: time spend (0),
score
> (null), new best score (null), random seed (0).
> ShiftAssignment: emp. id: 10 [st: 100, dur: 3]
> ShiftAssignment: emp. id: 10 [st: 100, dur: 2]
> ShiftAssignment: emp. id: 10 [st: 100, dur: 4]
> ShiftAssignment: emp. id: 10 [st: 100, dur: 1]
> 2011-12-05 22:21:49,678 [main] TRACE Building ConstraintOccurrence
summary
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 101, position id: 1, staffingRequired: 2, [ShiftAssignment: emp. id: 10
[st:
> 100, dur: 1]]]=1)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 103, position id: 1, staffingRequired: 2, []]=2)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 102, position id: 1, staffingRequired: 2, []]=2)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 100, position id: 1, staffingRequired: 2, [ShiftAssignment: emp. id: 10
[st:
> 100, dur: 1], ShiftAssignment: emp. id: 10 [st: 100, dur: 1]]]=0)
> 2011-12-05 22:21:49,678 [main] TRACE Building ConstraintOccurrence
summary
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 101, position id: 1, staffingRequired: 2, []]=2)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 103, position id: 1, staffingRequired: 2, []]=2)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 100, position id: 1, staffingRequired: 2, [ShiftAssignment: emp. id: 10
[st:
> 100, dur: 1]]]=1)
> 2011-12-05 22:21:49,678 [main] TRACE Adding ConstraintOccurrence
> (intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement: interval:
> 102, position id: 1, staffingRequired: 2, []]=2)
> Exception in thread "main" java.lang.IllegalStateException: The
> presumedScore (-5hard/-1soft) is corrupted because it is not the
realScore
> (-7hard/-1soft).
> Presumed workingMemory:
> Score rule (intervalRequirementCovered) has count (4) and weight total
> (5).
> Real workingMemory:
> Score rule (intervalRequirementCovered) has count (4) and weight total
> (7).
So the score rule intervalRequirementCovered is to blame.
> at
>
org.drools.planner.core.solution.director.DefaultSolutionDirector.assertWorkingScore(DefaultSolutionDirector.java:157)
> at
>
org.drools.planner.core.solver.DefaultSolverScope.assertWorkingScore(DefaultSolverScope.java:105)
> at
>
org.drools.planner.core.phase.AbstractSolverPhaseScope.assertWorkingScore(AbstractSolverPhaseScope.java:132)
> at
>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.decideNextStep(DefaultGreedyDecider.java:65)
> at
>
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:62)
> at
>
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:166)
> at
>
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:138)
> at
com.lfsoscience.planner.LfsoPlannerMain.execute(LfsoPlannerMain.java:36)
> at
com.lfsoscience.planner.LfsoPlannerMain.main(LfsoPlannerMain.java:27)
>
>
>
> The drl:
> rule "intervalRequirementCovered"
Let's take a look
> when
> $intervalReq : IntervalRequirement($interval : interval,
$position :
> position, $staffingRequired : staffingRequired)
> $matchingShiftAssignments : ArrayList( size<= $staffingRequired
)
>
from collect ( ShiftAssignment(shiftStartTime<= $interval,
> shiftEndTime> $interval, position == $position) )
I never used "from collect" in my examples yet.
You probably stumbled upon a "statefull memory corruption bug" in drools.
First try this alternative way:
$intervalReq : IntervalRequirement($interval : interval,
$position : position, $staffingRequired : staffingRequired)
$matchingShiftAssignmentSize : Number(intValue <=
$staffingRequired) from accumulate(
$x : ShiftAssignment(shiftStartTime <= $interval,
shiftEndTime > $interval, position == $position),
count($x)
)
If that works, file a ticket in
issues.jboss.org for the project JBRULES
about "statefull working memory corruption by using collect"
and include that rule and - if possible - testdata how to reproduce it.
> then
> #actions
> insertLogical(new
IntConstraintOccurrence("intervalRequirementCovered",
> ConstraintType.NEGATIVE_HARD,
> $staffingRequired -
$matchingShiftAssignments.size(),
> $intervalReq,
$matchingShiftAssignments));
> end
> rule "hardConstraintsBroken"
> salience -1 // Do the other rules first (optional, for
performance)
> when
> $hardTotal : Number() from accumulate(
> IntConstraintOccurrence(constraintType ==
> ConstraintType.NEGATIVE_HARD, $weight : weight), sum($weight)
> )
> then
> scoreCalculator.setHardConstraintsBroken($hardTotal.intValue());
> end
> rule "softConstraintsBroken"
> when
> eval(true)
> then
> scoreCalculator.setSoftConstraintsBroken(1);
> end
>
>
>
> The Planning Entity:
>
> @PlanningEntity
> public class ShiftAssignment implements Cloneable {
> private Employee employee;
> private int day;
> private Position position;
> private TimeLengthPair timeLengthPair = null;
> // Immutable object. Does not need to be cloned when calling clone
> private List<TimeLengthPair> possibleShiftStartTimeLengthPairList;
> private Set<TimeLengthPair> possibleShiftStartTimeLengthPairSet;
>
>
> public ShiftAssignment(Employee employee, int day, Position
position,
> Set<TimeLengthPair> shiftStartTimeLengthPairs) {
> this.employee = employee;
> this.day = day;
> this.position = position;
> this.possibleShiftStartTimeLengthPairSet = new
> HashSet<TimeLengthPair>(shiftStartTimeLengthPairs);
> }
>
> public int getShiftStartTime() {
> return this.timeLengthPair != null ?
this.timeLengthPair.getStartTime() :
> -1;
> }
>
> public int getShiftEndTime() {
> return this.timeLengthPair != null ?
this.timeLengthPair.getStartTime() +
> this.timeLengthPair.getLength() : -1;
> }
>
> public void setShiftStartTimeLengthPair(TimeLengthPair
timeLengthPair) {
> this.timeLengthPair = timeLengthPair;
> System.out.println(this);
> }
looks good
>
> public void addPossibleShiftStartTimeLengthPair(TimeLengthPair
> timeLengthPair) {
>
this.possibleShiftStartTimeLengthPairSet.add(timeLengthPair);
> // Clear the list since the Set has changed. The list will
be recreated
> from the set when needed (see getPossibleShiftStartTimeLengthPairs())
> this.possibleShiftStartTimeLengthPairList = null;
> }
this isn't called during planning I presume?
> @PlanningVariable
> @ValueRangeFromPlanningEntityProperty(propertyName =
> "possibleShiftStartTimeLengthPairs")
> public TimeLengthPair getShiftStartTimeLengthPair() {
> return this.timeLengthPair;
> }
looks good
> public List<TimeLengthPair>
getPossibleShiftStartTimeLengthPairs() {
> if (this.possibleShiftStartTimeLengthPairList == null) {
> this.possibleShiftStartTimeLengthPairList = new
> ArrayList<TimeLengthPair>(this.possibleShiftStartTimeLengthPairSet);
> }
> return this.possibleShiftStartTimeLengthPairList;
> }
>
> public Employee getEmployee() {
> return this.employee;
> }
>
> public int getDay() {
> return this.day;
> }
>
> public Position getPosition() {
> return this.position;
> }
>
> public boolean solutionEquals(Object o) {
> if (this == o) {
> return true;
> } else if (o instanceof ShiftAssignment) {
> ShiftAssignment other = (ShiftAssignment) o;
> return new EqualsBuilder()
> .append(this.employee, other.employee)
> .append(this.position, other.position)
> .append(this.timeLengthPair, other.timeLengthPair)
> .isEquals();
> } else {
> return false;
> }
> }
>
> public int solutionHashCode() {
> HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
> hashCodeBuilder.append(getClass())
> .append(this.employee)
> .append(this.position)
> .append(this.timeLengthPair);
> return hashCodeBuilder.toHashCode();
> }
>
> @Override
> public Object clone() throws CloneNotSupportedException {
> return super.clone();
> }
>
> @Override
> public String toString() {
> StringBuilder sb = new StringBuilder();
> sb.append("ShiftAssignment: ")
> .append("emp. id: ").append(this.employee.getId())
> .append(" ")
> .append(this.timeLengthPair != null ?
this.timeLengthPair.toString() :
> "Not Initialized");
> return sb.toString();
> }
>
> @Override
> public int hashCode() {
> return solutionHashCode();
> // return super.hashCode();
> }
>
> @Override
> public boolean equals(Object obj) {
> return solutionEquals(obj);
> // return super.equals(obj);
> }
> }
>
>
> --
> View this message in context:
http://drools.46999.n3.nabble.com/Planner-5-3-Final-presumedScore-is-corr...
> Sent from the Drools: User forum mailing list archive at
Nabble.com.
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
--
With kind regards,
Geoffrey De Smet
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users