On 16-07-13 16:24, pvandenbrink wrote:
Hi,
I've been using Drools Planner with success for a while for our Conversation
planning tool. It's used by schools to plan conversations between teachers
and parents of schoolgoing children.
Great to hear :)
Sounds like an interesting use case story.
Recently I checked on the new developments on Drools (the current
version
we're using in production is 5.4.0.FINAL) and started to upgrade to
OptaPlanner 6.0.0.Beta5.
Everything looked fine, and seeing how it's now easier to check which
constraints are broken in a given solution, I decided to have a look at that
as well.
And that's where I noticed that we actually had an issue with score
corruption in one of our rules...
Do you have this issue in 5.4 too? E.g.: the 5.4
equivalent of full
assert (TRACE) does not detect score corruption?
The goal of the rule in case is to minimize the amount of timeslots between
the first and last Conversation of a family (they can have conversations for
multiple children.)
The rule uses custom helper objects, like in the NurseRostering example,
which are added with insertLogical.
Conversation is the planning entity, which has the planning variable:
timeslot. FamilyStart and FamilyEnd are custom helper objects to register
the timeslot of the first and last conversation for a family.
The relevant rules are as follows:
rule "familyStart"
salience 1
when
Conversation(
family != null, $family: family,
timeslot != null, $timeslot: timeslot);
not Conversation(
family == $family,
timeslot < $timeslot);
then
insertLogical(new FamilyStart($family, $timeslot));
end
rule "familyEnd"
salience 1
when
Conversation(
family != null, $family: family,
timeslot != null, $timeslot: timeslot);
not Conversation(
family == $family,
timeslot > $timeslot);
then
insertLogical(new FamilyEnd($family, $timeslot));
end
rule "familyCompact"
when
$start: FamilyStart(
family != null, $family: family,
timeslot != null, $timeslotBegin: timeslot);
$end: FamilyEnd(
family == $family,
(timeslot.id - $timeslotBegin.id > family.minimumTimeslotsRequired),
timeslot != null, $timeslotEnd: timeslot);
then
scoreHolder.addSoftConstraintMatch(kcontext, -(($timeslotEnd.getId() -
$timeslotBegin.getId()) - $family.getMinimumTimeslotsRequired()));
end
When running one of my example schedules in FULL_ASSERT mode, the following
error appears during the LocalSearch phase:
Exception in thread "main" java.lang.IllegalStateException: Score
corruption: the workingScore (-2hard/-119soft) is not the uncorruptedScore
(-2hard/-118soft) after completedAction (Teacher 3 family 11 timeslot 2 =>
12):
The corrupted scoreDirector has 1 ConstraintMatch(s) which are in excess
(and should not be there):
defaultpkg/familyCompact/level1/[FamilyEnd Family 11, Timeslot 12,
FamilyStart Family 11, Timeslot 7]=-1
Maybe that "[FamilyEnd Family 11,
Timeslot 12, FamilyStart Family 11,
Timeslot 7]" exists twice?
Once way to find out is to put a debug breakpoint at the throw of the
exception
and compare the ConstraintMatchTotal's ConstraintMatch's justificationList.
The corrupted scoreDirector has no ConstraintMatch(s) which are
missing.
Check your score constraints.
I use a custom ChangeMove and SwapMove implementation. I've also tried using
the new generic Moves, these have the same problem.
Interesting: that proves
it's not a custom move problem.
It seems like when a move happens that should update an inserted
FamilyStart
or FamilyEnd because of a change in timeslot, this change isn't properly
reflected in the scoreDirector.
Do you have any idea what could cause this corruption? The moves do call
beforeVariableChanged and afterVariableChanged on the scoreDirector,
Your test
above proves that's ok. Use generic moves for further tests
first pls.
and the
FamilyStart and FamilyEnd classes implement an equals and hashcode based on
the Family and Timeslot fields.
1) But how do Family and Timeslot implement their
equals/hashcode?
My first guess would be to start looking at this.
2) There's also the remote probability there's a bug in drools - in
which case we'd want a reproducer attached on a jira so we can fix it.
(Actually, I've also tried using the default equals and hashcode
of Object
for these 2 classes, which causes corruption much faster and with more
ConstraintOccurrences.)
Thanks for any insights,
Pieter
HTH :)
--
View this message in context:
http://drools.46999.n3.nabble.com/OptaPlanner-score-corruption-when-using...
Sent from the Drools: User forum mailing list archive at
Nabble.com.
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users