Doctor Planning¶
The Doctor Planning example was submitted by us to the dmcommunity.org as a challenge. The full version, together with other submitted solutions, can be found on this page. Its specification is as follows:
Doctor Planning
In a hospital, there has to be a doctor present at all times. In order to make sure this is the case, a planning is made for the next 7 days, starting on a monday. Each day consists of three shifts: an early shift, a late shift and a night shift.
Every shift needs to be assigned to a doctor. In total there are 5 doctors: every doctor has a list of available days, and some have special requirements. In general, the following rules apply:
- A doctor can only work one shift per day.
- A doctor should always be available for his shift (see table below)
- If a doctor has the night shift, they either get the next day off, or the night shift again.
- A doctor either works both days of the weekend, or none of the days.
A planning should be made in which every requirement is fulfilled.
Name | Available |
---|---|
Fleming | Friday, Saturday, Sunday |
Freud | Every day early or late, never night |
Heimlich | Every day but neven the night shift on weekends |
Eustachi | Every day, every shift |
Golgi | Every day, every shift but at max 2 night shifts |
To create a cDMN model for this challenge, we start by building our glossary. From reading the description, we can see that we will need the following types:
- Doctor
- Day
- Time (early, late or night)
- Nb_shifts, to represent a number of shifts.
Thus, we create a glossary table as such:
Type | ||
---|---|---|
Name | Type | Values |
Doctor | String | Fleming, Freud, Heimlich, Eustachi, Golgi |
Day | String | Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday |
Time | String | Early, Late, Night |
Nb Shift | Int | [0..21] |
Next, we will need a way to assign doctors to days and shifts. Since for every pair of day and shift (e.g. “Monday” and “Early”) we need exactly 1 doctor, we use a function to do so. We also introduce functions to count the number of shifts per doctor and day, and the number of night shifts per doctor. Finally, we create one last function to represent the next day for every day.
Function | |
---|---|
Name | Type |
doctor assigned to Day and Time | Doctor |
nb shifts of Doctor and Day | Nb_Shift |
nb nights of Doctor | Nb_Shift |
day after Day | Day |
The last information to include in our model is the availabilities of every doctor. For this, we implement the relation Doctor is available on Day and Time.
Relation |
---|
Name |
Doctor is available on Day and Time |
Now that our glossary is done, we can move on to implementing the rules. We start by first implementing every rule one by one.
Rule 1
A doctor can only work one shift per day.
This rule can be modeled as a simple constraint table. We evaluate every doctor, on every day, and state that they work at max 1 shift that day.
Rule 1 | |||
---|---|---|---|
E* | Doctor | Day | nb shifts of Doctor and Day |
1 | - | - | ≤ 1 |
Rule 2
A doctor should always be available for his shift.
Once again, a single constraint table suffices. We state that for every doctor, day, and time, IF the doctor is assigned to that day and time, THEN he has to be available. In other words, a doctor can only be assigned to a day and time if he is available.
Rule 2 | |||||
---|---|---|---|---|---|
E* | Doctor | Day | Time | doctor assigned to Day and Time | Doctor is available on Day and Time |
1 | - | - | - | Doctor | Yes |
Rule 3
If a doctor has the night shift, they either get the next day off, or the night shift again.
This rule is by far the most difficult one to implement. We go over every doctor who works the night shift, and then state that they cannot be assigned to the early or late shift on the next day.
Rule 3 | ||||||
---|---|---|---|---|---|---|
E* | Doctor | Day called d1 | doctor assigned to d1 and Night | Day called d2 | Time | doctor assigned to d2 and Time |
1 | - | - | Doctor | Day after d1 | not(Night) | not(Doctor) |
Rule 4
A doctor either works both days of the weekend, or none of the days.
In order to implement this rule, we create a constraint table that says that every doctor who has a shift on Saturday has to work on Sunday, and vice versa.
Rule 4 | |||||
---|---|---|---|---|---|
E* | Doctor | Day called d1 | nb shifts of Doctor and d1 | Day called d2 | nb shifts of Doctor and d2 |
1 | - | Saturday | 1 | Sunday | 1 |
2 | - | Sunday | 1 | Saturday | 1 |
Special preference
Golgi only works a maximum of 2 night shifts every week.
This preference nicely shows of the simplicity of constraints in cDMN. We implement it as follows:
Max Nb of Nights | ||
---|---|---|
E* | Doctor | nb nights of Doctor |
1 | Golgi | ≤ 2 |
Now that every rule has been implemented, we need to create tables for the other concepts which we defined. We start by creating the decision table which defines the next day for every day. Then we create the tables which count the number of shifts per day, and the number of night shifts per week.
Define next day | ||
---|---|---|
U | Day | daf after Day |
1 | Monday | Tuesday |
2 | Tuesday | Wednesday |
3 | Wednesday | Thursday |
4 | Thursday | Friday |
5 | Friday | Saturday |
6 | Saturday | Sunday |
7 | Sunday | Monday |
Count shifts per day | |||||
---|---|---|---|---|---|
C+ | Doctor | Day | Time | doctor assigned to Day and Time | nb shifts of Doctor and Day |
1 | - | - | - | Doctor | 1 |
Count number of night shifts per doctor | ||||
---|---|---|---|---|
C+ | Doctor | Day | doctor assigned to Day and Night | nb nights of Doctor |
1 | - | - | Doctor | 1 |
Now all that rests is implementing the availablities in a data table. This table is quite long, so only the first few lines are shown.
Availabilities | ||||
---|---|---|---|---|
D | Doctor | Day | Time | Doctor is available on Day and Time |
1 | Fleming | Friday | Early | Yes |
2 | Fleming | Friday | Late | Yes |
3 | Fleming | Friday | Night | Yes |
... | ... | ... | ... | ... |
We can now run our model using the cDMN solver. For example, this is one of the solutions found by the solver:
Model 1
==========
doctor_assigned_to_Day_and_Time := {(Monday,Early)->Freud, (Monday,Late)->Golgi, (Monday,Night)->Heimlich, (Tuesday,Early)->Eustachi, (Tuesday,Late)->Freud, (Tuesday,Night)->Golgi, (Wednesday,Early)->Freud, (Wednesday,Late)->Eustachi, (Wednesday,Night)->Heimlich, (Thursday,Early)->Golgi, (Thursday,Late)->Freud, (Thursday,Night)->Heimlich, (Friday,Early)->Fleming, (Friday,Late)->Eustachi, (Friday,Night)->Heimlich, (Saturday,Early)->Golgi, (Saturday,Late)->Eustachi, (Saturday,Night)->Fleming, (Sunday,Early)->Golgi, (Sunday,Late)->Eustachi, (Sunday,Night)->Fleming}.
nb_shifts_of_Doctor_and_Day := {(Fleming,Monday)->0, (Fleming,Tuesday)->0, (Fleming,Wednesday)->0, (Fleming,Thursday)->0, (Fleming,Friday)->1, (Fleming,Saturday)->1, (Fleming,Sunday)->1, (Freud,Monday)->1, (Freud,Tuesday)->1, (Freud,Wednesday)->1, (Freud,Thursday)->1, (Freud,Friday)->0, (Freud,Saturday)->0, (Freud,Sunday)->0, (Heimlich,Monday)->1, (Heimlich,Tuesday)->0, (Heimlich,Wednesday)->1, (Heimlich,Thursday)->1, (Heimlich,Friday)->1, (Heimlich,Saturday)->0, (Heimlich,Sunday)->0, (Eustachi,Monday)->0, (Eustachi,Tuesday)->1, (Eustachi,Wednesday)->1, (Eustachi,Thursday)->0, (Eustachi,Friday)->1, (Eustachi,Saturday)->1, (Eustachi,Sunday)->1, (Golgi,Monday)->1, (Golgi,Tuesday)->1, (Golgi,Wednesday)->0, (Golgi,Thursday)->1, (Golgi,Friday)->0, (Golgi,Saturday)->1, (Golgi,Sunday)->1}.
nb_nights_of_Doctor := {Fleming->2, Freud->0, Heimlich->4, Eustachi->0, Golgi->1}.
day_after_Day := {Monday->Tuesday, Tuesday->Wednesday, Wednesday->Thursday, Thursday->Friday, Friday->Saturday, Saturday->Sunday, Sunday->Monday}.
Doctor_is_available_on_Day_and_Time := {(Fleming,Friday,Early), (Fleming,Friday,Late), (Fleming,Friday,Night), (Fleming,Saturday,Early), (Fleming,Saturday,Late), (Fleming,Saturday,Night), (Fleming,Sunday,Early), (Fleming,Sunday,Late), (Fleming,Sunday,Night), (Freud,Monday,Early), (Freud,Monday,Late), (Freud,Tuesday,Early), (Freud,Tuesday,Late), (Freud,Wednesday,Early), (Freud,Wednesday,Late), (Freud,Thursday,Early), (Freud,Thursday,Late), (Freud,Friday,Early), (Freud,Friday,Late), (Freud,Saturday,Early), (Freud,Saturday,Late), (Freud,Sunday,Early), (Freud,Sunday,Late), (Heimlich,Monday,Early), (Heimlich,Monday,Late), (Heimlich,Monday,Night), (Heimlich,Tuesday,Early), (Heimlich,Tuesday,Late), (Heimlich,Tuesday,Night), (Heimlich,Wednesday,Early), (Heimlich,Wednesday,Late), (Heimlich,Wednesday,Night), (Heimlich,Thursday,Early), (Heimlich,Thursday,Late), (Heimlich,Thursday,Night), (Heimlich,Friday,Early), (Heimlich,Friday,Late), (Heimlich,Friday,Night), (Heimlich,Saturday,Early), (Heimlich,Saturday,Late), (Heimlich,Sunday,Early), (Heimlich,Sunday,Late), (Eustachi,Monday,Early), (Eustachi,Monday,Late), (Eustachi,Monday,Night), (Eustachi,Tuesday,Early), (Eustachi,Tuesday,Late), (Eustachi,Tuesday,Night), (Eustachi,Wednesday,Early), (Eustachi,Wednesday,Late), (Eustachi,Wednesday,Night), (Eustachi,Thursday,Early), (Eustachi,Thursday,Late), (Eustachi,Thursday,Night), (Eustachi,Friday,Early), (Eustachi,Friday,Late), (Eustachi,Friday,Night), (Eustachi,Saturday,Early), (Eustachi,Saturday,Late), (Eustachi,Saturday,Night), (Eustachi,Sunday,Early), (Eustachi,Sunday,Late), (Eustachi,Sunday,Night), (Golgi,Monday,Early), (Golgi,Monday,Late), (Golgi,Monday,Night), (Golgi,Tuesday,Early), (Golgi,Tuesday,Late), (Golgi,Tuesday,Night), (Golgi,Wednesday,Early), (Golgi,Wednesday,Late), (Golgi,Wednesday,Night), (Golgi,Thursday,Early), (Golgi,Thursday,Late), (Golgi,Thursday,Night), (Golgi,Friday,Early), (Golgi,Friday,Late), (Golgi,Friday,Night), (Golgi,Saturday,Early), (Golgi,Saturday,Late), (Golgi,Saturday,Night), (Golgi,Sunday,Early), (Golgi,Sunday,Late), (Golgi,Sunday,Night)}.
Elapsed Time:
2.045
The Assigned_Doctor function maps every day and shift on a doctor, conform to all the requirements!