[rules-users] null planning value - Was: Planner 5.3.Final - "presumedScore is corrupted" when using "update" on the rules working memory
Geoffrey De Smet
ge0ffrey.spam at gmail.com
Wed Dec 7 10:49:05 EST 2011
Op 07-12-11 16:13, Patrik Dufresne schreef:
> 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.
>
Null is currently not supported as a planning value (the entity gets
seen as uninitialized). Please create an issue for that, you're not the
only one running into it.
I want to fix this for 5.4, but it's more that it looks on the surface.
> So how do I fix it ?
Workaround it really :(
Create a planning value that represents null, but isn't. Teach your
score rules to deal with that special value.
For example, if it's a Room, then give Room a property boolean
unassigned and add 1 Room with that boolean unassigned = true (all
others are false).
>
> 2011/12/7 Geoffrey De Smet <ge0ffrey.spam at gmail.com
> <mailto:ge0ffrey.spam at gmail.com>>
>
>
>
> 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
>> <ge0ffrey.spam at gmail.com <mailto:ge0ffrey.spam at 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
>> <http://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 at lists.jboss.org
>> <mailto:rules-users at lists.jboss.org>
>> > https://lists.jboss.org/mailman/listinfo/rules-users
>> >
>>
>> --
>> With kind regards,
>> Geoffrey De Smet
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org <mailto:rules-users at lists.jboss.org>
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>>
>> --
>> Patrik Dufresne
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org <mailto:rules-users at lists.jboss.org>
>> https://lists.jboss.org/mailman/listinfo/rules-users
>
> --
> With kind regards,
> Geoffrey De Smet
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org <mailto:rules-users at lists.jboss.org>
> https://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
>
> --
> Patrik Dufresne
>
>
> _______________________________________________
> rules-users mailing list
> rules-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/rules-users
--
With kind regards,
Geoffrey De Smet
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20111207/d7b9a2ea/attachment.html
More information about the rules-users
mailing list