Closed AybukeAk closed 1 year ago
min
is an annoying one to implement, because unlike max, you also need to handle the 0 case. However, if an employee have 0 shifts, it will not appear as a group key in the group_by. This means to correctly implement min
, you need two separate constraints:
def constraint_for_employee_min_working_day_in_week_no_shifts(constraint_factory: ConstraintFactory):
return constraint_factory \
.for_each(Employee) \
.if_not_exists(Shift, Joiners.equal(lambda employee: employee, lambda shift: shift.employee)) \
.filter(lambda employee: ((0 < employee.min_working_day_in_week)))\
.penalize('Constraint for employee min working day in week, no shifts', HardSoftScore.ONE_HARD,
lambda employee: employee.min_working_day_in_week)
Hello! Thank you so much for your reply. When I implemented the two functions as you specified, I could not understand the error score of the constraint_for_employee_min_working_day_in_week_no_shifts constraint. Normally I expect non-assignables (0 case ) to produce as errors as min_working_days . But regardless of the number of non-assigned employees, it produces a score like (number of agents * min_working_day of the employee) . For example, when I want to assign 18 agents to 27 shifts, when min_working_day is 1 and max_working_day is 2, if all other constraints are met without error, 4 agents are not assigned and it generates -18 scores. So I thought constraint_for_employee_min_working_day_in_week constraint also generates error for unassigned workers. Do you think is it possible? Could you help me to fix this error?
When I tried to use “if_exist” function in constraint_for_employee_min_working_day_in_week, I got following error :
TypeError: Unable to cast 'org.optaplanner.constraint.streams.common.bi.DefaultBiJoiner' to java type 'org.optaplanner.core.api.score.stream.tri.TriJoiner'
Other cases I have observed are as follows:
-- | -- | -- | -- | -- | -- 18 | 27 | 2 | 2 | 4 | -36 18 | 27 | 5 | 7 | 13 | -90 18 | 27 | 6 | 7 | 13 | -108
Thank you in advance
@AybukeAk the TypeError
is because you used a joiner the joins on a UniStream (BiJoiner) at a place that joins on a BiStream (as the groupby transformed it from a uni to a bi).
You can verify constraints using constraint verifier; see https://github.com/optapy/optapy-quickstarts/blob/stable/employee-scheduling/tests.py for examples.
When tested using constraint verifier, constraint_for_employee_min_working_day_in_week_no_shifts
works as expected (only penalizes employees with no shifts).
You can use ScoreManager
to explain the score of a given solution; see https://www.optapy.org/docs/latest/score-calculation/score-calculation.html#explainingTheScore .
Thank you so much for your reply. If_not_exists did not work correctly because we were using the old version of optapy. After the update, both constraints worked correctly. But now we got an error in a previously working constrait. I opened another issue regarding this: https://github.com/optapy/optapy-quickstarts/issues/28
Hello!
I am using constraints no_overlapping_shifts, at_least_10_hours_between_two_shifts, one_shift_per_day, tag_constraint_for_employee in your constraint.py file. In addition to these, I wanted to add the max_working _day constraint that the employee should not exceed the maximum number of days a week can work. The code is like this:
This code is working correctly and I wanted to add min working day constraint too, and updated domain.py , constraint.py according to the function. It didn't work when the two were together. Although it produces results that do not meet the min_working_day constraint, it did not show in the error score. Do you have any idea why it is not working? Any ideas on how I can add these constraints?
Thank you in advance