<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#ffffff">
<br>
<br>
Op 07-12-11 16:13, Patrik Dufresne schreef:
<blockquote
cite="mid:CAJ=kj5z4ZMA4GJOk6PfvVfbyT6xZWYbwZ-DF6sMJDvXjSYYxAA@mail.gmail.com"
type="cite">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.
<div>
<br>
</div>
<div>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.</div>
<div><br>
</div>
</blockquote>
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.<br>
I want to fix this for 5.4, but it's more that it looks on the
surface.<br>
<blockquote
cite="mid:CAJ=kj5z4ZMA4GJOk6PfvVfbyT6xZWYbwZ-DF6sMJDvXjSYYxAA@mail.gmail.com"
type="cite">
<div>So how do I fix it ?</div>
</blockquote>
Workaround it really :(<br>
Create a planning value that represents null, but isn't. Teach your
score rules to deal with that special value.<br>
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).<br>
<blockquote
cite="mid:CAJ=kj5z4ZMA4GJOk6PfvVfbyT6xZWYbwZ-DF6sMJDvXjSYYxAA@mail.gmail.com"
type="cite">
<div><br>
<div class="gmail_quote">2011/12/7 Geoffrey De Smet <span
dir="ltr"><<a moz-do-not-send="true"
href="mailto:ge0ffrey.spam@gmail.com" target="_blank">ge0ffrey.spam@gmail.com</a>></span><br>
<blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt
0.8ex; border-left: 1px solid rgb(204, 204, 204);
padding-left: 1ex;">
<div text="#000000" bgcolor="#ffffff"> <br>
<br>
Op 07-12-11 02:18, Patrik Dufresne schreef:
<div>
<blockquote type="cite">I'm still experimenting with
Drools Planner and I also
have the exact same issue :
<blockquote style="margin: 0pt 0pt 0pt 40px; border:
medium none; padding: 0px;">
<div>
<div>
<div>
<div>java.lang.IllegalStateException: The
presumedScore
(0hard/-1soft) is corrupted because it is
not the
realScore (0hard/0soft).</div>
</div>
</div>
</div>
<div>
<div>
<div>
<div>Presumed workingMemory:</div>
</div>
</div>
</div>
<div>
<div>
<div>
<div> Score rule (soft-ReduceNullAssignment)
has count
(1) and weight total (1).</div>
</div>
</div>
</div>
<div>
<div>
<div>
<div>Real workingMemory:</div>
</div>
</div>
</div>
<div>
<div>at
org.drools.planner.core.solution.director.DefaultSolutionDirector.assertWorkingScore(DefaultSolutionDirector.java:157)</div>
</div>
<div>
<div>at
org.drools.planner.core.solver.DefaultSolverScope.assertWorkingScore(DefaultSolverScope.java:105)</div>
</div>
<div>
<div>at
org.drools.planner.core.phase.AbstractSolverPhaseScope.assertWorkingScore(AbstractSolverPhaseScope.java:132)</div>
</div>
<div>
<div>at
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:69)</div>
</div>
<div>
<div>at
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:166)</div>
</div>
<div>
<div>at
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:138)</div>
</div>
<div>
<div>
<div>...</div>
</div>
</div>
<div><br>
</div>
</blockquote>
<div>I've read this (<a moz-do-not-send="true"
href="https://issues.jboss.org/browse/JBRULES-3301"
target="_blank">https://issues.jboss.org/browse/JBRULES-3301</a>),
but
it didn't help :</div>
<ul>
<li>I'm using IntConstraintOccurrence</li>
<li>I double check the soft constraint named
"soft-ReduceNullAssignment" -- it's include all
the cause.</li>
<li>I'm using Drools 5.3</li>
</ul>
<div>After more digging, I think something is missing
in
DefaultSolutionDirector.java:153. The facts are
added, but the
planningEntity are not added.</div>
</blockquote>
</div>
They are added:<br>
<br>
for (Object fact : getWorkingFacts()) {<br>
tmpWorkingMemory.insert(fact);<br>
}<br>
<br>
public Collection<Object> getWorkingFacts() {<br>
return
solutionDescriptor.getAllFacts(workingSolution); //
returns the problem facts + the initiliazed
planningEntity's
<div><br>
}<br>
<br>
<blockquote type="cite">
<div>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.</div>
</blockquote>
</div>
That's weird.<br>
<br>
Could you try this with the latest drools-planner-core
5.4.0.SNAPSHOT from the jboss nexus repository too?<br>
You'll have to branch and upgrade your local code:<br>
<a moz-do-not-send="true"
href="https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-distribution/src/main/assembly/filtered-resources/UpgradeFromPreviousVersionRecipe.txt"
target="_blank">https://github.com/droolsjbpm/drools-planner/blob/master/drools-planner-distribution/src/main/assembly/filtered-resources/UpgradeFromPreviousVersionRecipe.txt</a><br>
<br>
As a side affect, you'll notice that the exception message
will be
much much clearer too, which will help in discovering the
problem.
<div>
<div><br>
<blockquote type="cite">
<div><br>
</div>
<div>Here is the my rule :</div>
<blockquote style="margin: 0pt 0pt 0pt 40px; border:
medium none; padding: 0px;">
<div>
<div>rule "soft-ReduceNullAssignment"</div>
</div>
<div>when</div>
<div>$planif : PlanifEventAssignment( employee ==
null )</div>
<div>then</div>
<div>
<div> insertLogical(new
IntConstraintOccurrence("soft-ReduceNullAssignment",</div>
</div>
<div>
<div> <span style="white-space:
pre-wrap;"> </span>ConstraintType.NEGATIVE_SOFT,</div>
</div>
<div>
<div> 1,</div>
</div>
<div>
<div> $planif));</div>
</div>
<div>
<div>end</div>
</div>
</blockquote>
<div><br>
</div>
<div>Thanks</div>
<div><br>
<div class="gmail_quote">On Tue, Dec 6, 2011 at
11:12 AM,
Geoffrey De Smet <span dir="ltr"><<a
moz-do-not-send="true"
href="mailto:ge0ffrey.spam@gmail.com"
target="_blank">ge0ffrey.spam@gmail.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:
0pt 0pt 0pt 0.8ex; border-left: 1px solid
rgb(204, 204, 204); padding-left: 1ex;"><br>
<br>
Op 06-12-11 05:38, guyramirez schreef:<br>
<div>
<div>> Still the same issue, starting
with
the construction heuristic phase. Please<br>
> let me know if you need more
explanations in what I
am trying to do.<br>
><br>
> Here is the error. Please note that
there is only
one planning entity<br>
> (ShiftAssignment) object instance in
this test.<br>
><br>
> Total Staffing required: 8<br>
> 2011-12-05 22:21:49,627 [main] INFO
Solver
started: time spend (0), score<br>
> (null), new best score (null), random
seed (0).<br>
> ShiftAssignment: emp. id: 10 [st:
100, dur: 3]<br>
> ShiftAssignment: emp. id: 10 [st:
100, dur: 2]<br>
> ShiftAssignment: emp. id: 10 [st:
100, dur: 4]<br>
> ShiftAssignment: emp. id: 10 [st:
100, dur: 1]<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Building
ConstraintOccurrence summary<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 101, position id: 1,
staffingRequired: 2,
[ShiftAssignment: emp. id: 10 [st:<br>
> 100, dur: 1]]]=1)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 103, position id: 1,
staffingRequired: 2, []]=2)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 102, position id: 1,
staffingRequired: 2, []]=2)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 100, position id: 1,
staffingRequired: 2,
[ShiftAssignment: emp. id: 10 [st:<br>
> 100, dur: 1], ShiftAssignment: emp.
id: 10 [st:
100, dur: 1]]]=0)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Building
ConstraintOccurrence summary<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 101, position id: 1,
staffingRequired: 2, []]=2)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 103, position id: 1,
staffingRequired: 2, []]=2)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 100, position id: 1,
staffingRequired: 2,
[ShiftAssignment: emp. id: 10 [st:<br>
> 100, dur: 1]]]=1)<br>
> 2011-12-05 22:21:49,678 [main] TRACE
Adding
ConstraintOccurrence<br>
>
(intervalRequirementCovered/NEGATIVE_HARD:[IntervalRequirement:
interval:<br>
> 102, position id: 1,
staffingRequired: 2, []]=2)<br>
> Exception in thread "main"
java.lang.IllegalStateException: The<br>
> presumedScore (-5hard/-1soft) is
corrupted because
it is not the realScore<br>
> (-7hard/-1soft).<br>
> Presumed workingMemory:<br>
> Score rule
(intervalRequirementCovered) has
count (4) and weight total<br>
> (5).<br>
> Real workingMemory:<br>
> Score rule
(intervalRequirementCovered) has
count (4) and weight total<br>
> (7).<br>
</div>
</div>
So the score rule intervalRequirementCovered
is to blame.<br>
<div>> at<br>
>
org.drools.planner.core.solution.director.DefaultSolutionDirector.assertWorkingScore(DefaultSolutionDirector.java:157)<br>
> at<br>
>
org.drools.planner.core.solver.DefaultSolverScope.assertWorkingScore(DefaultSolverScope.java:105)<br>
> at<br>
>
org.drools.planner.core.phase.AbstractSolverPhaseScope.assertWorkingScore(AbstractSolverPhaseScope.java:132)<br>
> at<br>
>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.decideNextStep(DefaultGreedyDecider.java:65)<br>
> at<br>
>
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:62)<br>
> at<br>
>
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:166)<br>
> at<br>
>
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:138)<br>
> at
com.lfsoscience.planner.LfsoPlannerMain.execute(LfsoPlannerMain.java:36)<br>
> at
com.lfsoscience.planner.LfsoPlannerMain.main(LfsoPlannerMain.java:27)<br>
><br>
><br>
><br>
> The drl:<br>
> rule "intervalRequirementCovered"<br>
</div>
Let's take a look<br>
<div>> when<br>
> $intervalReq :
IntervalRequirement($interval : interval,
$position :<br>
> position, $staffingRequired :
staffingRequired)<br>
> $matchingShiftAssignments :
ArrayList(
size<= $staffingRequired )<br>
>
from collect (
ShiftAssignment(shiftStartTime<=
$interval,<br>
> shiftEndTime> $interval, position
== $position) )<br>
</div>
I never used "from collect" in my examples
yet.<br>
You probably stumbled upon a "statefull memory
corruption
bug" in drools.<br>
<br>
First try this alternative way:<br>
<div><br>
$intervalReq :
IntervalRequirement($interval :
interval,<br>
$position : position, $staffingRequired :
staffingRequired)<br>
</div>
$matchingShiftAssignmentSize :
Number(intValue <=<br>
$staffingRequired) from accumulate(<br>
$x :
ShiftAssignment(shiftStartTime <=
$interval,<br>
shiftEndTime > $interval, position ==
$position),<br>
count($x)<br>
)<br>
<br>
If that works, file a ticket in <a
moz-do-not-send="true"
href="http://issues.jboss.org"
target="_blank">issues.jboss.org</a>
for the project JBRULES<br>
about "statefull working memory corruption by
using collect"<br>
and include that rule and - if possible -
testdata how to
reproduce it.<br>
<div>
<div>> then<br>
> #actions<br>
> insertLogical(new
IntConstraintOccurrence("intervalRequirementCovered",<br>
> ConstraintType.NEGATIVE_HARD,<br>
>
$staffingRequired -
$matchingShiftAssignments.size(),<br>
>
$intervalReq,
$matchingShiftAssignments));<br>
> end<br>
> rule "hardConstraintsBroken"<br>
> salience -1 // Do the other
rules first
(optional, for performance)<br>
> when<br>
> $hardTotal : Number() from
accumulate(<br>
>
IntConstraintOccurrence(constraintType
==<br>
> ConstraintType.NEGATIVE_HARD, $weight
: weight),
sum($weight)<br>
> )<br>
> then<br>
>
scoreCalculator.setHardConstraintsBroken($hardTotal.intValue());<br>
> end<br>
> rule "softConstraintsBroken"<br>
> when<br>
> eval(true)<br>
> then<br>
>
scoreCalculator.setSoftConstraintsBroken(1);<br>
> end<br>
><br>
><br>
><br>
> The Planning Entity:<br>
><br>
> @PlanningEntity<br>
> public class ShiftAssignment
implements Cloneable {<br>
> private Employee employee;<br>
> private int day;<br>
> private Position position;<br>
> private TimeLengthPair
timeLengthPair = null;<br>
> // Immutable object. Does not
need to be
cloned when calling clone<br>
> private
List<TimeLengthPair>
possibleShiftStartTimeLengthPairList;<br>
> private
Set<TimeLengthPair>
possibleShiftStartTimeLengthPairSet;<br>
><br>
><br>
> public ShiftAssignment(Employee
employee, int
day, Position position,<br>
> Set<TimeLengthPair>
shiftStartTimeLengthPairs) {<br>
> this.employee =
employee;<br>
> this.day = day;<br>
> this.position =
position;<br>
>
this.possibleShiftStartTimeLengthPairSet =
new<br>
>
HashSet<TimeLengthPair>(shiftStartTimeLengthPairs);<br>
> }<br>
><br>
> public int getShiftStartTime()
{<br>
> return
this.timeLengthPair != null ?
this.timeLengthPair.getStartTime() :<br>
> -1;<br>
> }<br>
><br>
> public int getShiftEndTime() {<br>
> return
this.timeLengthPair != null ?
this.timeLengthPair.getStartTime() +<br>
> this.timeLengthPair.getLength() : -1;<br>
> }<br>
><br>
> public void
setShiftStartTimeLengthPair(TimeLengthPair
timeLengthPair) {<br>
> this.timeLengthPair =
timeLengthPair;<br>
>
System.out.println(this);<br>
> }<br>
</div>
</div>
looks good<br>
<div>><br>
> public void
addPossibleShiftStartTimeLengthPair(TimeLengthPair<br>
> timeLengthPair) {<br>
>
this.possibleShiftStartTimeLengthPairSet.add(timeLengthPair);<br>
> // Clear the list since
the Set has
changed. The list will be recreated<br>
> from the set when needed (see
getPossibleShiftStartTimeLengthPairs())<br>
>
this.possibleShiftStartTimeLengthPairList =
null;<br>
> }<br>
</div>
this isn't called during planning I presume?<br>
<div>> @PlanningVariable<br>
>
@ValueRangeFromPlanningEntityProperty(propertyName
=<br>
> "possibleShiftStartTimeLengthPairs")<br>
> public TimeLengthPair
getShiftStartTimeLengthPair() {<br>
> return
this.timeLengthPair;<br>
> }<br>
</div>
looks good<br>
<div>
<div>> public
List<TimeLengthPair>
getPossibleShiftStartTimeLengthPairs() {<br>
> if
(this.possibleShiftStartTimeLengthPairList
== null) {<br>
>
this.possibleShiftStartTimeLengthPairList
= new<br>
>
ArrayList<TimeLengthPair>(this.possibleShiftStartTimeLengthPairSet);<br>
> }<br>
> return
this.possibleShiftStartTimeLengthPairList;<br>
> }<br>
><br>
> public Employee getEmployee() {<br>
> return this.employee;<br>
> }<br>
><br>
> public int getDay() {<br>
> return this.day;<br>
> }<br>
><br>
> public Position getPosition() {<br>
> return this.position;<br>
> }<br>
><br>
> public boolean
solutionEquals(Object o) {<br>
> if (this == o) {<br>
> return true;<br>
> } else if (o instanceof
ShiftAssignment) {<br>
> ShiftAssignment other =
(ShiftAssignment) o;<br>
> return new
EqualsBuilder()<br>
>
.append(this.employee,
other.employee)<br>
>
.append(this.position,
other.position)<br>
>
.append(this.timeLengthPair,
other.timeLengthPair)<br>
> .isEquals();<br>
> } else {<br>
> return false;<br>
> }<br>
> }<br>
><br>
> public int solutionHashCode() {<br>
> HashCodeBuilder
hashCodeBuilder = new
HashCodeBuilder();<br>
>
hashCodeBuilder.append(getClass())<br>
>
.append(this.employee)<br>
>
.append(this.position)<br>
>
.append(this.timeLengthPair);<br>
> return
hashCodeBuilder.toHashCode();<br>
> }<br>
><br>
> @Override<br>
> public Object clone() throws
CloneNotSupportedException {<br>
> return super.clone();<br>
> }<br>
><br>
> @Override<br>
> public String toString() {<br>
> StringBuilder sb = new
StringBuilder();<br>
>
sb.append("ShiftAssignment: ")<br>
> .append("emp.
id:
").append(this.employee.getId())<br>
> .append(" ")<br>
>
.append(this.timeLengthPair
!= null ? this.timeLengthPair.toString() :<br>
> "Not Initialized");<br>
> return sb.toString();<br>
> }<br>
><br>
> @Override<br>
> public int hashCode() {<br>
> return
solutionHashCode();<br>
> // return
super.hashCode();<br>
> }<br>
><br>
> @Override<br>
> public boolean equals(Object
obj) {<br>
> return
solutionEquals(obj);<br>
> // return
super.equals(obj);<br>
> }<br>
> }<br>
><br>
><br>
> --<br>
> View this message in context: <a
moz-do-not-send="true"
href="http://drools.46999.n3.nabble.com/Planner-5-3-Final-presumedScore-is-corrupted-when-using-update-on-the-rules-working-memory-tp3546932p3563446.html"
target="_blank">http://drools.46999.n3.nabble.com/Planner-5-3-Final-presumedScore-is-corrupted-when-using-update-on-the-rules-working-memory-tp3546932p3563446.html</a><br>
> Sent from the Drools: User forum
mailing list
archive at Nabble.com.<br>
>
_______________________________________________<br>
> rules-users mailing list<br>
> <a moz-do-not-send="true"
href="mailto:rules-users@lists.jboss.org"
target="_blank">rules-users@lists.jboss.org</a><br>
> <a moz-do-not-send="true"
href="https://lists.jboss.org/mailman/listinfo/rules-users"
target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
><br>
<br>
</div>
</div>
<div>--<br>
With kind regards,<br>
Geoffrey De Smet<br>
<br>
<br>
</div>
<div>
<div>_______________________________________________<br>
rules-users mailing list<br>
<a moz-do-not-send="true"
href="mailto:rules-users@lists.jboss.org"
target="_blank">rules-users@lists.jboss.org</a><br>
<a moz-do-not-send="true"
href="https://lists.jboss.org/mailman/listinfo/rules-users"
target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
</div>
</div>
</blockquote>
</div>
<br>
<br clear="all">
<div><br>
</div>
-- <br>
Patrik Dufresne<br>
</div>
<pre><fieldset></fieldset>
_______________________________________________
rules-users mailing list
<a moz-do-not-send="true" href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a>
<a moz-do-not-send="true" href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a>
</pre>
</blockquote>
<br>
<pre cols="72">--
With kind regards,
Geoffrey De Smet</pre>
</div>
</div>
</div>
<br>
_______________________________________________<br>
rules-users mailing list<br>
<a moz-do-not-send="true"
href="mailto:rules-users@lists.jboss.org" target="_blank">rules-users@lists.jboss.org</a><br>
<a moz-do-not-send="true"
href="https://lists.jboss.org/mailman/listinfo/rules-users"
target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
<br>
</blockquote>
</div>
<br>
<br clear="all">
<div><br>
</div>
-- <br>
Patrik Dufresne<br>
</div>
<pre wrap="">
<fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
rules-users mailing list
<a class="moz-txt-link-abbreviated" href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/rules-users">https://lists.jboss.org/mailman/listinfo/rules-users</a>
</pre>
</blockquote>
<br>
<pre class="moz-signature" cols="72">--
With kind regards,
Geoffrey De Smet</pre>
</body>
</html>