I'm trying to schedule 30 teaching assistants to cover about 118 hours of office hours. Office hours at different times of day need different coverage (0, 1, 2, or 3 asssistants). People are scheduled on the half hour.
I've made an integer linear program such that I have a 0/1 variable indexed by worker and shift: 0 if not working then, 1 if working then. Coverage is easy, but it leads to some workers being scheduled for only a half-hour shift, which is not fair to them.
My second attempt was to have a richer set of indexed variables, by (worker, start time, length of shift). This is where the snags begin:
If I limit the number of shifts per worker to one shift per day, the IP solver grinds away for hours with no solution.
If I allow two shifts per worker per day, things work pretty well, except sometimes the solver schedules a single worker for two shifts that overlap. Which means the solver thinks I have 3 people on duty but I really only have 2.
My final attempt was to introduce constraints such that no worker can ever be scheduled for two shifts that overlap. At this point my tools grind for a while and then blow up with an out-of-memory error.
I'm using the RIMA optimization package with the COIN CPB solver. (Have also tried lpsolve
.)
I feel like 30 workers into circa 150 slots should not be that difficult! So I think I must be formulating the problem in a stupid way. Thus my question: how can I learn how to formulate my scheduling problem in a way that solvers will do well with it?
(If it matters, the objective function I am trying to maximize is the total utility to all the workers of all the shifts they have been assigned. It's just a number indexed by worker and shift.)