Thanks for your opinion. I will try to implement what I
call a HardAndSoftPriorityScoreDefinition
and give it back to the community. Where is the best place
to post a 'patch' ?
Design wise, I recommend:
It's basically about allowing a dynamic number of levels, instead
of just 2 (hard and soft).
it should not extend AbstractHardAndSoftScore, just extend
AbstractScore
Because it cannot correctly implement
HardAndSoftScore.getSoftScore();
I should just have a Map<Integer, Integer> levelToScoreMap;
(no int hardScore or int softScore)
hardScore is like level 0.
softScore is like level -1.
This allows for:
softerScore at level -2
harderScore at level 1
Higher level is more important then lower level.
The class name should probably contain the word "Level".
I'm still in process to model my
planning problem and I have some
difficulties in defining the correct
weight of soft constraints. I have soft
constraints with different priorities :
C1, C2, C3, ..., Cn where C1 are higher
then C2. Currently, I've tried to set
different weight for each of them : C1 get
higher weight. But it's not sufficient
since multiple C2 may balance one C1. What
I really need is to set the priority to
every soft constraints.
Solution #1 :
My first thought it to implement a new
score definition
(HardAndSoftPriorityScoreDefinition)
having separate soft score for each
priority. The rule may insert
ConstraintOccurence by defining the weight
and the priority. This solution seems
elegant but require effort to implement
the score definition, the score
calculation, and other things I don't even
know about.
That is the perfect solution to your problem. Start by
copy pasting DefaultHardAndSoftScoreDefinition
and work your way from there.
You'll need to create at least a ScoreDefinition,
ScoreCalculator and Score.
I've been thinking about adding such a "dynamic"
score definition to planner's build-in scores,
but so far every use case where the developers said
they needed this, it turned out end-users meant it
differently:
when you break a 100 C2's, then it's better to break
1 C1 instead...
Solution #2 :
The other solution is stated in the
Drools Planner User Guide :
"Most use cases will also weigh their
constraints differently, by multiplying
the count of each score rule with its
weight. For example in freight routing,
you can make 5 broken "avoid crossroads"
soft constraints count as much as 1
broken "avoid highways at rush hour"
soft constraint. This allows your
business analysts to easily tweak the
score function as they see fit."
Even tough I don't know how to
implement this, it's seems much easier to
achieve since it's only a rule. Compare to
solution #1, it's lack the support of soft
constraints with same priority but
different weights.
That text describes plain-old weighting. Say C1 weights
100 and C2 weights 2, then you can break 50 C2's for
every 1 broken C1.
This is far easier and most of the time end-users
actually mean this.
Make exaggerated examples (1000 C2's broken vs 1 C1
broken) and make your end-users decide what they prefer.
If they still prefer 1000 C2's broken, then you need #1.
Tip: Sometimes, taking the square of a weight is a neat
trick.
In bin packing, say you got
Solution A with 3 CPU and 3 CPU too little = 3² + 3² =
18
and Solution B with 4 CPU and 2 CPU too little = 4² + 2²
= 20
So the second is worse even though they both miss 6 CPU.