Get notified of new posts
The IHTC 2024 (1)¶
Last year I decided to participate in an Optimization contest about scheduling patients to operation rooms called Integrated Healthcare Timetabling Competition 2024. I didn't do extremely well. This was not a surprise to me: I am aware of how competitive these competitions can be.
That doesn't mean that I did not try hard, though! And since I took it as an opportunity to try engines that I'm not very comfortable using, I actually learn lots.
In this post I will try to go back to the competition and convince myself that I did not do that bad summarize what I did. Hopefully it will be useful for others in the future. I put a (1) in the name because I could not fit everything I did in a single post, I will potentially revisit this topic in the future with my other approaches (see the end of the post for the other approaches / topics).
The problem itself¶
There are probably many scientific articles that explain both the problem and better performing methods than the ones here. A will include some references at the end of the post. But I also leave here, the main site for the contest, the open-access article where they summarize the results and best methods.
The problem is described in the page of the contest, in particular in this document. I will do my best to summarize it here but I do recommend reading the full document as I don't think I will be as exhaustive.
I will split the description in two parts, but the problem, as its name implies, integrates both into a single decision. I will use parts of a solution to help explain it.
The Scheduling / Theater assignment part¶
This one joins the "Patient-to-Room Assignment" and the "Surgical Case Planning" as explained in the organizers article.
A set of Patients require one surgery each. After the surgery (which takes place the day the patient arrives), each patient need to stay at a Room in the hospital for a number of days (how many depends on the patient). Each patient has its own set of relevant attributes: they have an assigned Surgeon, and a given duration (in minutes) for their surgery. They have a window of days when they can have the surgery (some Patientss surgery are optional). Patients also have many other characteristics that make them more or less compatible with Nurses, Rooms, and other Patients (e.g., age group, gender, nurse skill level required, workload for nurse).

Example of patient input data. Taken from the organizers.
Each surgery is carried out in any one of potentially many Operating Theaters. These have a daily capacity, measured by the maximum number of minutes it can be used for surgeries. The surgery requires the patient's Surgeon to be present, of course. Surgeons also have a daily capacity. We want to avoid assigning too many different Operating Theaters to the same Surgeon during the same day.
The Room where the patient stays after the surgery has a maximum number of patients that can fit inside. Also, Rooms are unisex and it's better to put patients of the same age range together.
The scheduling decision is to decide, for each Patient: which day it will start their surgery (if it is carried out), in which Operating Room and in which Room they stay.
The time horizon for the planning consists of a number of weeks (2 to 4 weeks). There are some patients (called Occupants) at the start of the planning horizon that are already in the hospital, taking space in a room and requiring Nurses, but not requiring a surgery.
As example, the following figures show the assignment of patients to rooms and surgeons workload.
Each line represents the stay of a Patient. The number of lines at any given day cannot surpass the capacity and there cannot be two patients of the same gender. E.g., room r4 doesn't exceed the capacity of 3 and the blue and red lines never intersect.

Days in X axis (scale not shown), Rooms in Y axis (r4 and r5). Each line is a patient stay.
The following figure shows the workload of Surgeons.

Days in X axis, Workload in Y axis. On chart per Surgeon.
The following figure shows the workload of Operating Theaters.

Days in X axis, Workload in Y axis. On chart per Operating Theater.
The Timetable part¶
This one covers the "Nurse-to-Patient Assignment" as presented by the organizers.
A set of Nurses is required to attend patients in the Rooms. Nurses work in shifts (3 shifts per day) and they already know which shift of which day they are working (e.g., Nurse A works the morning of day 3 and the afternoon of day 4). Nurses have attributes that make them more or less suitable for Patients (i.e., skills, available workload).
We want to minimize the number of different Nurses that take care of any individual Patient.
The timetable decision consists of assigning a Nurse for each Room and shift.
The Nurses assigned to each room in each day and shift in the planning horizon. In the figure, Room r09 has Nurse n07 assigned during the nights of days 0 and 1.

Nurses assigned to Rooms. Days in X axis, Shift in Y axis. One chart per Room. The content is the assigned Nurse.
The workload of a Patient is not constant during their stay. The chart shows the aggregated workload for each Nurse. It can be seen that Nurse n00 has a three shifts were the Nurse is overloaded.

Nurse workload per shift. Shifts in X axis, Workload in Y axis. One chart per Nurse.
The skill levels of a Patient are not constant during their stay. In dotted lines is the provided skill level by the Nurse that is assigned to the Room of the Patient. In red are the gaps between the Nurse's level and the required one. Patient a0 has three shifts were his required skill level was not met.

Patient skill level requirements per shift. Shifts in X axis, Skill level in Y axis. One chart per Patient.
CPSAT model for the Scheduling / Theater assignment¶
While writing the model, I realized that it would be completely unreadable to put everything here. So I will only show the parameters, variables and constraints of the first part: the room scheduling and operating room assignment (no Nurses here, then).
I will also refrain from being very very precise on the sets and possible combinations, edge cases, etc. The problem is explained in many places and my intention is to provide a feeling the modelling approach rather than a full reproducible model. I will skip occupants, too. In practice, they imply small modifications to the room usage constraints during the first periods of the planning horizon: capacity, gender and age constraints.
The repository with the code has everything that's needed to test, run, reproduce the model. Go to this file, specifically to check the CP-SAT formulation.
Main parameters¶
Variables¶
As expected, there are variables relating to the room, operating room and admission assigned for each patient \(p\). And many other secondary variables to count the capacity use of Surgeons, Operating Theaters and Rooms.
Constraints¶
Both the binary \(a_{p,d} \in \{0,1\}\) and the integer \(ai_{p} \in \mathcal{D}\) represent the same decision. So we link them: if the former is true, then the latter needs to have a day assigned accordingly:
We now create an optional interval for each patient and each room that defines the time the patient is staying in the room, if assigned to that room (i.e., if \(r_{p,r}=1\)).
We use the Cumulative constraint in CP-SAT to limit the patient intervals, such that the room capacity is never surpassed.
We use this constraint too to limit that no two patients with different gender can be in the same room at the same time. We do this second part by creating the constraint for each room, each gender and each member of the opposite gender. Each member of the opposite gender will use the whole capacity.
Then, we need to link all variables that relate rooms, theaters and surgeons assignments.
- If and only if patient \(p\) is assigned to operating theater \(o\) in day \(d\) (\(at_{o,p,d} = 1\)), then the admission for that day (\(a_{p,d}\)) and the operating theater assignment (\(t_{p,o}\)) need to be true.
- If patient \(p\)'s admission is in day \(d\) (\(a_{p,d}=1\)) and is assigned to operation theater \(o\) (\(t_{p,o}=1\)), then:
- Surgeon \(S_p\) is assigned to theater \(o\) in day \(d\) (\(st_{S_{p},o,d} = 1\)) and
- Theater \(o\) opens in day \(d\) (\(to_{o,d}=1\)).
I'm omitting the =1 part for these boolean variables, but is should be assumed.
Most of the previous clauses were actually implemented as a Boolean OR clauses. For example,
becomes:
The sum of the surgery duration \(SD_p\) of each of the surgeon's patients \(p \in \mathcal{P}_s\) in any given day \(d\), cannot be greater then their daily capacity \(SC_{s,d}\).
The sum of the surgery durations \(SD_p\) of all the operating theater's patients in any given day \(d\), cannot be greater then their daily capacity \(OC_{o,d}\).
All mandatory patients need to be scheduled, with a room and an operating theater.
Each optional patient can be scheduled at most once, and they get a theater and a room if and only if they are scheduled.
Then, we need to declare the min/max/diff age for each room and day. This is a bit tricky since we need to first know which patient is where (which room) and when (which day). Ideally, I would have loved to use CPSAT Intervals here, since they seem to be a lot more efficient at this scheduling constraints. But I did not find a way to (ab)use the functionality in the right way.
If patient \(p\) has admission in day \(d\) and is assigned to room \(r\), then during his whole stay (\(d' \in \{\, d, d+1, \dots, d+\ell_p-1 \,\}\)): (a) the max age group (\(y^{max}_{r,d'}\)) will be at least his age group (\(Y_p\)), and (b) the min age group (\(y^{min}_{r,d'}\)) will be at most his age group (\(Y_p\)). Otherwise, we do not enforce the constraint.
Once we have the max and min age groups per room and day, we just calculate the difference:
Objective function¶
In this simplified model, we have five parts for our objective function, that are explained by the weights table below:
So we just need to sum all of the components into one single value:
How I used the CP model¶
I used the complete version of the CP model inside several decompositions. Below I put the different ways I used it.
Two-stage solving¶
This approach can be used to produce an initial solution or to improve an existing solution (with the help of the next approach, see below). As its name says, there are two stages:
- the scheduling + assignment part (i.e., the model describe above) was the first pass.
- the nurse timetable part (not described in this post) was the second pass, taking into account the (now fixed) decisions for (1).
The assumption behind it is that there is enough of a solution space even while fixing the patients information to correctly plan the nurses.
Time-window approach¶
This approach requires having a complete feasible solution already. It goes as follows:
- select a time window ("from day X to day X+20").
- select a sample of unplanned optional patients.
- Fix everything that happens outside the time window. I.e., all patients that have an admission prior to day X and after day X+20. Likewise for nurse assignments.
- (re)solve this new, smaller problem until a small time limit is reached. This can be done using the two-stage approach described above, or with the complete model. Use the the current solution as warm start.
- Integrate the obtained solution into the fixed part.
The figure below shows an example of a time window. Patients p02, p23, p10 and p30 are fixed. All other are free.

Days in X axis (scale not shown), Rooms in Y axis (r4 and r5). Each line is a patient stay. In yellow a candidate time window.
The rational behind this approach is that, especially in large problems, decisions that are very far in time are not very relevant to each other, and thus local changes inside a big enough time window should lead to good solutions.
For another time¶
This post is already a bit too long so I will leave it there. Things that I wanted to include: (1) me trying timefold for python for the first time to solve this problem, (2) the interactive quarto report that I made (and used for the figures above), (3) a graph-based shortest-path move using graph-tool, (4) the interactive GUI that I built to use the problem, (5) the rest of the CPSAT model that dealt with the Nurse assignments.
If you reached this far in this post, congratulations. Also, if any of these remaining topics is of interest to you, feel free to leave a comment with the request below.
I'm also very interested in knowing if this CPSAT implementation was the good one. So do reach out if you think of better alternative formulations. Or if something doesn't make sense.