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-corrupted-when-using-update-on-the-rules-working-memory-tp3546932p3563446.html > Sent from the Drools: User forum mailing list archive at Nabble.com. > _______________________________________________ > rules-users mailing list > rules-users@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users > -- With kind regards, Geoffrey De Smet _______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users