0

I'm going to use OptaPlanner to lay out time tables for a school.

We're laying out the time tables for a full semester and every week could, if necessary, be slightly different.

There are some tricky constraints to take into account:

1. Weekly schedules

  • The lectures in one subject should be spread out somewhat evenly over the semester.
    • We can't for example put 20 math lectures the first week and "be done" with math for this semester.
  • In fact, it's nice to have some weekly predictibility
    • "Science year 2 have biology on Tuesday mornings"
    • This constraint must not be carved in stone however. Some weeks have to include work experience sessions, PE excursions, etc, in which case they must deviate from other weeks.

Problem

If I create a constraint that say, gives -1soft for not scheduling a subject the same time as the previous week, then OptaPlanner will waste a lot of time before it "accidentally" finds a good placement for a lecture, and even if it manages to converge so that each subject is scheduled the same time every week, it will never ever manage to move the entire series of lectures by moving them one by one. (That local optimum will never be escaped.)

2. Cross student group subjects

  • There's a large correlation between student groups and courses; For example, all students in Science year 2 mostly reads the same courses: Chemistry for Science year 2, Biology for Sience year 2, ...
  • The exception being language courses.
  • Each student can choose to study French, German or Spanish. So Spanish for year 2 is studied by a cross section of Science year 2 students, and Social Studies year 2 students, etc.
  • From the experience of previous (manual) scheduling, the optimal solution it's almost guaranteed to schedule all language classes in the same time slots. (If French is scheduled at 9 on Thursdays, then German and Spanish can be scheduled "for free" at 9 on Thursdays.)

Problem

There are many time slots in one semester, and the chances that OptaPlanner will discover a solution where all language lectures are scheduled at the same time by randomly moving individual lectures is small.

Also, similarly to problem 1: If OptaPlanner does manage to schedule French, German and Spanish at the same time, these "blocks" will never be moved elsewhere, since they are individual lectures, and the chances that all lectures will "randomly" move to the same new slot is tiny. Even with a large Tabu history length and so on.

My thoughts so far

As for problem 1 ("Weekly predictability") I'm thinking of doing the following:

In the construction phase for the full-semester-schedule I create a reduced version of the problem, that schedules (a reduced set of lectures) into a single "template week". Let's call it a "single-week-pre-scheduling". This template week is then repeated in the construction of the initial solution of the full semester which is the "real" planning entity.

The local search steps will then only focus on inserting PE excursions etc, and adjusting the schedule for the affected weeks.

As for problem 2 I'm thinking that the solution to problem 1 might solve this. In a 1 week schedule, it seems reasonable to assume that OptaPlaner will realize that language classes should be scheduled at the same time.

Regarding the local optimum settled by the single-week-pre-scheduling ("Biology is scheduled on Tuesday mornings"), I imagine that I could create a custom move operation that "bundles" these lectures into a single move. I have no idea how simple this is. I would really like to keep the code as simple as possible.

Questions

Are my thoughts reasonable? Is there a more clever way to approach these problems? If I have to create custom moves anyways, perhaps I don't need to construct a template-week?

Is there a way to assign hints or weights to moves? If so, I could perhaps generate moves with slightly larger weight that adjusts scheduling to adhere to predictable weeks and language scheduled in the same time slots.

aioobe
  • 413,195
  • 112
  • 811
  • 826

1 Answers1

0

A question well asked!

With regards to your first problem, I suggest you take a look at OptaWeb Employee Rostering and the concept of rotations. A rotation is "how things generally are" and then Planner has the freedom to diverge from the rotation at a penalty. Once you understand the concept of the rotation from the UI, take a look at the planning entity Shift and how the rotation is implemented with the use of employee and rotationEmployee variables. Note that only the employee is an actual @PlanningVariable, with the rotationEmployee being fixed.

That means that you have to define your rotations manually, therefore doing the work of the solver yourself. However, since this operation is only done once a semester I assume, maybe the solution could be to have a simpler solver generate a reasonable general rotation first, and then a second solver would take it and figure out the specific necessary adjustments?

With regards to your second problem, rotations could help there too. But I'm thinking maybe some move filtering and custom moves to help OptaPlanner to either move all language classes, or none? Writing efficient custom moves is not easy, and filtering stock moves is cumbersome. So I would only do it when the potential of other options is exhausted. If you end up doing this, look for MoveIteratorFactory.

My answer is a little vague, as we do not get into the specifics of the domain model, but for the purposes of designing the overall solution, it hopefully gives enough clues.

Lukáš Petrovický
  • 3,945
  • 1
  • 11
  • 20
  • Thank you. I will definitely look into the employee rostering example and the concept of rotations. Judging from your description it sounds similat to what I call a template week. – aioobe Aug 09 '21 at 08:23
  • Wow, that's a large project to give a pointer to. Do you have any hint to which classes to look closer at? Another approach came to mind, perhaps too complicated to describe in a comment, but I'll try. What do you think of having a domain model that has, in addition to `Lecture`, a `LectureSeries`? The `Lecture`s would represent "one off" events in the semester such as PE excursions, and `LectureSeries` would represent a collection of repeated lectures. More complicated model obviously, but an order of magnitude fewer fact objects for OptaPlanner to juggle with. – aioobe Aug 09 '21 at 11:12
  • Good point on OptaWeb complexity, I updated my answer to give further pointers. I think the approach you propose in your comment could work, albeit the impact on complexity of constraints remains to be seen - when you make distinction between a lecture and a series, you run the risk of having to write each constraint twice or, worse yet, having to somehow figure out how to mix both in the same constraint. – Lukáš Petrovický Aug 09 '21 at 11:35