Reputation: 15
I am trying to solve a scheduling problem, which centers around the following arrangement:
Equipment
<- Task
<- ShiftAssignment
(Planning Variable) -> Shift
Task
s have a problem fact of their equipment usage; each may reference a specific Equipment
instance or instances, with an associated time in minutes. It takes up that time for that equipment in the Shift
it's assigned to.
Should I be able to achieve the constraint with join()
and groupBy()
? I've tried pursuing the following route:
private Constraint doNotOverbookEquipment(ConstraintFactory factory) {
return factory.from(ShiftAssignment.class)
// join shift assignments with the shifts they are assignments of
.join(Shift.class, equal(ShiftAssignment::getShiftId, Shift::getId))
// join with ALL pieces of equipment
.join(Equipment.class)
.groupBy([Shift and Equipment, summing the equipment-usage for each ShiftAssignment])
.filter([equipment usage greater than a constant])
.penalizeConfigurable("do not overbook Equipment");
I think the filter()
should be no problem, but unsure exactly how to get this groupBy()
to achieve what I want. Do I need a TriConstraintCollector
here? Or is there a different, better overall approach?
For reference, the ShiftAssignment class can easily have a method like the following:
public LinkedHashSet<Equipment, Integer> getEquipmentUsage()
Upvotes: 1
Views: 1395
Reputation: 5682
I think that your groupBy()
would look something like this:
.groupBy(
(shiftAssignment, shift, equipment) -> shift,
(shiftAssignment, shift, equipment) -> equipment,
ConstraintCollectors.sum((shiftAssignment, shift, equipment) ->
shiftAssignment.getUsage(shift, equipment)
)
The actual logic of what is to be summed should, in this case, be implemented in shiftAssignment.getUsage(...)
or any other method you choose to use there.
Upvotes: 2