[2] Do it using drools rules, like the following:
rule "Avoid conflicting activities"
when
Assignment($room1:
room, $act1: activity, $id : activity.id)
Assignment(room
== $room1, room!= null, $act2 : activity, activity.id > $id)
eval(Activity.conflict($act1,
$act2))
Why calculate it every time if you can cache it? [3]
then
insertLogical(new
IntConstraintOccurrence("conflictingActivities",
ConstraintType.NEGATIVE_HARD,
10, null));
end
Here I'm using Assignment as the only planning entity.
There's an assignment for each activity and it may point to a
room or to null in the case the activity is not assigned. In the
case above, I have a static function that checks whether two
activities conflicts. This way, solutions may be infeasible but
with high penalties the best solution found will eventually be
feasible.
[3]
I also thought of a third option, which is to insert a fact
"Conflict" for each pair of conflicting activities in a
preprocessing phase. This way we would end up with:
This is the recommended way. It's called "cached problem facts" in
the manual.
See the TopicConflict use in the examinationScoreRules.drl and
Examination.getProblemFacts() in the examples.
rule "Avoid conflicting activities"
when
Assignment($room1
: room, $act1: activity, $id : activity.id)
Assignment(room==
$room1, room != null, $act2 : activity, activity.id > $id)
Conflict(act1
== $act1, act2 == $act2)
I would put Conflict first. But try it this way too and let me know
which works better ;) I don't know.
Stated differently: Instead of checking every 2 simultaneous
assignments if they are a conflict,
I would check if every 2 conflict assignments are simultaneous (like
in examinationScoreRules.drl).