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.
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(a)gmail.com
<mailto:ge0ffrey.spam@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-d...
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(a)gmail.com <mailto:ge0ffrey.spam@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-corr...
> > Sent from the Drools: User forum mailing list archive at
>
Nabble.com.
> > _______________________________________________
> > rules-users mailing list
> > rules-users(a)lists.jboss.org
> <mailto: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(a)lists.jboss.org <mailto:rules-users@lists.jboss.org>
>
https://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
>
> --
> Patrik Dufresne
>
>
> _______________________________________________
> rules-users mailing list
> rules-users(a)lists.jboss.org <mailto: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(a)lists.jboss.org <mailto:rules-users@lists.jboss.org>
https://lists.jboss.org/mailman/listinfo/rules-users
--
Patrik Dufresne
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users