Ok,
I changed periodId > $periodId back into periodId != $periodId as I already discovered
that this change resulted in invalid solutions.
Though, then I was back to the exception.
I now made another change which seems to be the solution... I think... I hope
Though, I do not understand the solution myself for 100%
What I did was testing if period is not null:
rule "tasksInSameJobMustBeInSamePeriod"
when
$taskA : MaintenanceTask(period!=null, $id : id, $jobId : jobId, $periodId :
periodId )
$taskB : MaintenanceTask(period!=null, id > $id, jobId == $jobId, periodId !=
$periodId )
then
insertLogical(new
IntConstraintOccurrence("tasksInSameJobMustBeInSamePeriod", $taskA, $taskB));
end
I just tried that because all the sudden I tought checking null != null might not be such
a good idea.
I now get the right combinations.
Can you please tell me if this is a correct change?
Once again one of my earlier questions arises: why is a rule tested upon an entity before
the planning variables are set?
Or am I wrong here?
Thanks,
Michiel
-----------------
http://www.codessentials.com - Your essential software, for free!
Follow us at
http://twitter.com/#!/Codessentials
________________________________
From: Geoffrey De Smet <ge0ffrey.spam(a)gmail.com
To: Rules
Users List <rules-users(a)lists.jboss.org>
Sent: Monday, September 3, 2012 2:15 PM
Subject: Re: [rules-users] Best model for planning? technicians, airplanes and shifts
=> insertLogical problems
Op 03-09-12 13:59, Michiel Vermandel schreef:
Hi,
I'm not keen on spending time on a temp solution if I cannot
estimate -
at this time - how much time it will take me to build
it correctly afterwards.
Budgets are limited... (as with anyone I guess :-)
Once again, it gives me a bad feeling that such a simple setup
is giving me
such a hard to solve issue.
Incremental score calculation isn't a simple concept nor
easy to implement.
But I agree that Drools and Planner should shield you from that
complexity and take the heat there.
Planner already has extensive support to detect score corruption in
incremental score calculation,
and Drools's compensation action looks promising to take greatly
simply the complexity to the user.
I had thought that - given the project is only a very few classes - it would be peanuts
for you or any other expert to pinpoint what I'm doing wrong.
I didn't have the time to read all the classes in detail,
just glimpsed over them.
>Non the less...
>I tried to have a look again to a number of examples and I
changed my rules, with a positive result!
I seem to get the correct solution. But... I do not know if my
changes are valid.
I mean, is it possible that I threw a number of possible
solutions away?
Maybe this will not show right now but will have it's effect
when numbers grow and possible solutions shrink.
>So what I did is going from
>rule "tasksInSameJobMustBeInSamePeriod"
> when
> $taskA : MaintenanceTask($id : id, $jobId : jobId,
$periodId : periodId )
MaintenanceTask(id != $id, jobId == $jobId, periodId !=
$periodId ) // <============ a != $a
then
System.out.println("r3: " + $taskA );
insertLogical(new
IntConstraintOccurrence("tasksInSameJobMustBeInSamePeriod",
$taskA));
>end
>to
>rule
"tasksInSameJobMustBeInSamePeriod"
> when
> $taskA : MaintenanceTask($id : id, $jobId : jobId,
$periodId : periodId )
$taskB:
MaintenanceTask(id > $id,
Good, because if you count the combination task5-task7, you
don't want to count the combination task7-task5 too.
jobId == $jobId, periodId > $periodId ) // <================ a > $a
Bad, keep this on periodId != $periodId (or even period !=
$period)
then
System.out.println("r3: " + $taskA );
insertLogical(new
IntConstraintOccurrence("tasksInSameJobMustBeInSamePeriod",
$taskA));
Add $taskB too:
insertLogical(new IntConstraintOccurrence("tasksInSameJobMustBeInSamePeriod",
$taskA, $taskB));
end
>Can you please tell me if this
is THE solution or a dangerous move that works out now but will give issues when numbers
grow?
The id > $id change is good, the periodId != $periodId
isn't.
The above fixes could explain score corruption. You no longer get
any exceptions in environmentMode DEBUG or TRACE?
Keep looking at the examples: they work and they scale.
Keep providing feedback as to the pain points too of course.
Hope that helps.
>Thanks a lot.
>Michiel
>
>-----------------
>http://www.codessentials.com - Your essential software, for
free!
>Follow us at
http://twitter.com/#!/Codessentials
>________________________________
> From: Geoffrey De Smet <ge0ffrey.spam(a)gmail.com
>To:
Michiel Vermandel <mvermand(a)yahoo.com>; Rules Users List
<rules-users(a)lists.jboss.org>
>Sent: Monday, September 3, 2012 11:56 AM
>Subject: Re: Best model for planning? technicians, airplanes and shifts =>
insertLogical problems
>
>Op
03-09-12 11:30, Michiel Vermandel schreef:
>I did not really start on one example. I have scrolled
through several to try to figure out how to do it, then started from scratch for the
POJO's and Rules.
>
>>The config file was copies from one of the examples
because it contained too many things that were hard to get right in the beginning.
>>I know that is a risk but I needed to start somewhere.
>
>
I am thinking how to standardize the
getting started with planner experience.
The cloud balance quick start is the example I pushing
at the moment.
But for specific use case, it's better to start from an
example that's similar to the user's use case.
The trouble is, it's often hard to see which example is
similar and which is not.
>
>>3) What does "The workingMemory has 2 ConstraintOccurrence(s) in
excess:" really mean?
>> - Are the constraints there more than once?
No, it means that in a clean WorkingMemory, those 2 ConstraintOccurrences aren't
there,
but in the incremental WorkingMemory, they are there.
So they are in excess: they should have been
automatically retracted
by the rule engine, but for some
reason, they are not.
>Read this section about incremental score calculation to
understand why this complexity is needed:
>
http://docs.jboss.org/drools/release/5.4.0.Final/drools-planner-docs/html...
>If you just want to prove that a Planner POC works for
now (especially if you're close to giving up),
just take a few minutes to switch to a simple Java score
calculator for now:
(but it
should still be faster than anything you can
invent yourself within reasonable time).
Once that works fine and you get a good result on your
toy problem and you can scale out to 100+ jobs,
then switch back to drools to scale out to 10000+ jobs
and follow the rest of this mail.
> - has this something to do
with the equals and hashcode (which I did implement (see below))?
Likely. The equals/hashcode methods are used of all objects in the causes parameter.
It's a design issue in Planner that the planner entity's
equals/hashcode() needs to be used for the
ConstraintOccurrence's causes.
>Compensation action
>
>> About the compensation action: is it already available on 5.4.0 final?
Should I try that?
The plumbing is there in Drools Expert, but in Planner there are no decent examples,
supporting code or even complex experiments yet.
It's a minefield, probably best to stay out until I get
it done or you have more Planner experience :/
>
>>4) I have been looking to the equals and hashcode, though found many
examples that implement solutionEquals and solutionHashcode instead.
>> Currently I implemented them like this:
>
>> @Override
>> public int hashCode() {
>> return id.hashCode(); //(*)
>> }
>
>> @Override
>> public boolean equals(Object o) {
>> if (this == o) {
>> return true;
>> }
>> if (id == null || !(o instanceof
MaintenanceTask)) {
> return false;
> } else {
> MaintenanceTask other =
(MaintenanceTask)
o;
>> return id.equals(other.id);
>> }
>> }
>
>
Looks good
>
>>
(*) id is a String property which is passed into the entity object through the
constructor and upon cloning it is passed from the clone source to the clone target:
>> public MaintenanceTask clone() {
>> System.out.println("Cloning task " + id);
>> MaintenanceTask clone = new MaintenanceTask(job, id);
>> clone.period = this.period;
>> clone.technician = this.technician;
>> return clone;
>> }
>
Looks good.
>
>
>
>
>>
I am still confused about:
>
>> - Which ones do I need to implement (equals or
solutionEquals, ...)?
because of this code:
objects (see
drools expert manual on insertLogical)
> - Should an entity and a cloned entity have the same
result for both equals and hashcode? (I guess so)
Yes, definitely.
> - Should only the entity objects have such
implementations? (Planning variables are never cloned, right?)
>
It looks good. Only the entity's are cloned indeed during
cloneSolution(): they are the only instances that change during planning.
>
>
>>
>>-----------------
>>http://www.codessentials.com - Your essential software, for free!
>>Follow us at
http://twitter.com/#!/Codessentials
>
>
>>________________________________
>> From: Geoffrey De Smet <ge0ffrey.spam(a)gmail.com
>>To: Rules Users List <rules-users(a)lists.jboss.org>
>>Sent: Monday, September 3, 2012 10:44 AM
>>Subject: Re: [rules-users] Best model for planning? technicians, airplanes and
shifts => insertLogical problems
>>
>>Op 03-09-12 10:21, Michiel Vermandel schreef:
>>> Hi Geoffrey,
>>
>>> Thanks for the support
so far.
>>> I understand that you do not provide full
support on this level.
>> Though I have the feeling that this is
really
>> - a very basic solution setup
>> - a beginners-mistake and since I'm looking
into it now for about 3 days
>> (since I started with planner) it seems to
be not obvious to find for a
>> beginner.
>> So I was trying my luck in offering the
code.
>> It could be an opportunity to enrich the
documentation ;-) ;-)
>
>>Good point, the score corruption problem is
often a beginner problem and
>>it's a PITA. I 'll write some more docs about.
>
>>Do note that your 3 day implementation should be
able to scale out to
>10000 planes pretty easily, so hang in there :)
>I fear you might have started copying from the
wrong
example nqueens (if
>you did that) :/ Nurse rostering is a far more
similar to this kind of
>problem. I am not sure which example to promote
in the docs: the nqueens
>is simple enough to explain things on, but it's
too simple to copy from
>>for real world stuff :/ Feedback welcome.
>
>>
>>
>>> Ok,
>>
>>> 1) adding the $t2
results in the same sort
of exception, only
>>> planningEntity seems different:
>>
>>> with insertLogical(new
>>
UnweightedConstraintOccurrence("tasksInSameJobMustBeInSamePeriod",
$t1,
>>> $t2));
>>
>>> Exception in thread
"main"
java.lang.IllegalStateException: Score
>> corruption: the workingScore (-2) is not
the uncorruptedScore (0):
>> The workingMemory has 2
ConstraintOccurrence(s) in excess:
>>
tasksInSameJobMustBeInSamePeriod/NEGATIVE_HARD:[Maintenance
of
>> Boeing 737 - PJ23.I#1 73111693, Maintenance
of Boeing 737 - PJ23.I#2
>>> 427578167]
>>
tasksInSameJobMustBeInSamePeriod/NEGATIVE_HARD:[Maintenance
of
>> Boeing 737 - PJ23.I#2 427578167,
Maintenance of Boeing 737 - PJ23.I#1
>> 73111693]
>> Check the score rules who created those
ConstraintOccurrences. Verify
>> that each ConstraintOccurrence's causes and
weight is correct.
>>> at
>>
org.drools.planner.core.score.director.AbstractScoreDirector.assertWorkingScore(AbstractScoreDirector.java:101)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.doMove(DefaultGreedyDecider.java:110)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.decideNextStep(DefaultGreedyDecider.java:78)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:63)
>>> at
>>
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:183)
>>> at
>>
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:151)
>>> at
>>
be.axi.planner.domain.MaintenancePlanning.main(MaintenancePlanning.java:27)
>>
>>> with insertLogical(new
>>
UnweightedConstraintOccurrence("tasksInSameJobMustBeInSamePeriod",
$t1));
>>
>>> Exception in thread
"main"
java.lang.IllegalStateException: Score
>> corruption: the workingScore (-2) is not
the uncorruptedScore (0):
>> The workingMemory has 2
ConstraintOccurrence(s) in excess:
>>
tasksInSameJobMustBeInSamePeriod/NEGATIVE_HARD:[Maintenance
of
>>> Airbus A350 - XJ34.I#2 778813475]
>>
tasksInSameJobMustBeInSamePeriod/NEGATIVE_HARD:[Maintenance
of
>> Airbus A350 - XJ34.I#0 225744121]
>> Check the score rules who created those
ConstraintOccurrences. Verify
>> that each ConstraintOccurrence's causes and
weight is correct.
>>> at
>>
org.drools.planner.core.score.director.AbstractScoreDirector.assertWorkingScore(AbstractScoreDirector.java:101)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.doMove(DefaultGreedyDecider.java:110)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.decider.DefaultGreedyDecider.decideNextStep(DefaultGreedyDecider.java:78)
>>> at
>>
org.drools.planner.core.constructionheuristic.greedyFit.DefaultGreedyFitSolverPhase.solve(DefaultGreedyFitSolverPhase.java:63)
>>> at
>>
org.drools.planner.core.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:183)
>>> at
>>
org.drools.planner.core.solver.DefaultSolver.solve(DefaultSolver.java:151)
>>> at
>>
be.axi.planner.domain.MaintenancePlanning.main(MaintenancePlanning.java:27)
>>
>>
>>> 2) You suggested to replace
UnweightedConstraintOccurrence with
>> IntConstraintOccurrence. I will.
>> UnweightedConstraintOccurrence is used in
the very
basic Queens example
>>> though...
>
>>Yep, my mistake.
>
>>
>>> 3) Where is the best place to read about
what insertLogical and
>> IntConstraintOccurrence really do?
>> What is the purpose of the Cause -objects,
which
should be passed?
>> => where is the best place to find
explanation about this?
>>>
(
http://docs.jboss.org/drools/release/5.4.0.Final/drools-planner-docs/html...
>>> doesn't really enlighten me on that part)
>
>>Look for "insertLogical" in the Drools
Expert
guide:
>
>>http://docs.jboss.org/drools/release/5.4.0.Final/drools-expert-docs/html_single/index.html
>
>>When rules do an insertLogical of an object A,
it's discarded if another
>object B in the WorkingMemory equals object A
(through equals() and
>through hashcode()). Because the
ConstraintOccurrences need to be unique
>so they aren't discarded, they ruleId,
constraintType and causes are
>>used for equals()/hashcode().
>
>>Future work: "compensation action"
>>Recently, drools introduced something called
"compensation action",
>which can probably replace the use
insertLogical(ConstraintOccurrence)
>and make the causes parameter obsolete.
>It's also faster.
>My first experiments look very promising, but I
haven't got time yet to
>experiment with it on all examples and make it
easy for users to use.
>
>>It would allow us to do something like this in
the then part of a rule:
>> hardAndSoftScoreHelper.addHardScore(-5);
>>or
>> hardAndSoftScoreHelper.addSoftScore(- $sum);
>>or
>> simpleScoreHelper.addScore(-7);
>
>>No need for causes, insertLogicals, no
equals/hashcode() worries, much
>>more flexible, ...
>
>
>>4) Does your MaintenanceTask
implement
equals()/hashcode() other than
>>Object's original implementation?
>
>
>>
>>> Thanks in advance.
>>
>
>>yw
>
>>_______________________________________________
>>rules-users mailing list
>>rules-users(a)lists.jboss.org
>>https://lists.jboss.org/mailman/listinfo/rules-users
>
>
>
>
>
>>_______________________________________________
rules-users mailing list rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
>_______________________________________________
rules-users mailing list rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users