During my debugging, I notice the call to getWorkingFacts() doesn't include the planning entities. To make sure, I've run the NQueens example (that use the same construction heuristic) : the call to getWorkingFacts() include the planning entities.
After more debugging, I figure out the problem. The ValueRange of my PlanningEntity include 'null'. I use null for un-assigned shift. In PlanningVariableDescriptor.java:149, the check for initialized variable return False if the value is null. Then my planning entity is wrongly identify as not initialized and the SolutionDescriptor.java:135 doesn't include it in the facts list. So how do I fix it ? 2011/12/7 Geoffrey De Smet <[email protected]> > ** > > > Op 07-12-11 02:18, Patrik Dufresne schreef: > > 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 (https://issues.jboss.org/browse/JBRULES-3301), 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. > > They are added: > > for (Object fact : getWorkingFacts()) { > tmpWorkingMemory.insert(fact); > } > > public Collection<Object> getWorkingFacts() { > return solutionDescriptor.getAllFacts(workingSolution); // returns > the problem facts + the initiliazed planningEntity's > > } > > 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. > > That's weird. > > Could you try this with the latest drools-planner-core 5.4.0.SNAPSHOT from > the jboss nexus repository too? > You'll have to branch and upgrade your local code: > > https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-distribution/src/main/assembly/filtered-resources/UpgradeFromPreviousVersionRecipe.txt > > As a side affect, you'll notice that the exception message will be much > much clearer too, which will help in discovering the problem. > > > 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 <[email protected] > > 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-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 >> > [email protected] >> > https://lists.jboss.org/mailman/listinfo/rules-users >> > >> >> -- >> With kind regards, >> Geoffrey De Smet >> >> >> _______________________________________________ >> rules-users mailing list >> [email protected] >> https://lists.jboss.org/mailman/listinfo/rules-users >> > > > > -- > Patrik Dufresne > > > _______________________________________________ > rules-users mailing > [email protected]https://lists.jboss.org/mailman/listinfo/rules-users > > > -- > With kind regards, > Geoffrey De Smet > > > _______________________________________________ > rules-users mailing list > [email protected] > https://lists.jboss.org/mailman/listinfo/rules-users > > -- Patrik Dufresne
_______________________________________________ rules-users mailing list [email protected] https://lists.jboss.org/mailman/listinfo/rules-users
