0

I have MasterSchedule and LiveSchedule, TemplateShift, Shift and Employee domain models.

But I'm my timefold code, I'm only using Schedule Shift and Employee. The planning variable here is an employee assigned to an shift.

MasterSchedule and TemplateShifts allow a user to modify shifts for future planning and set a rollout date that will then apply the MasterSchedule to the LiveSchedule. But these TemplateShifts do not have dates but store the values of week, day, start, end. When building an shift from this template shift, it will generate the dates relative to the current week. E.g week 1 day 2 would be Tuesday of the current week. For more context, a shift can also be over 2 days e.g 8pm Monday - 6am Tuesday.

I need to optimize both the TemplateSchedule and the LiveSchedule. I was hoping to keep things simple by building shifts from the templates and sending them to timefold. Just so I don't have to handle the differences of a template shift vs a shift. But I'm not sure how to handle the reoccurrence of the template shifts. The MasterSchedule defines a number of weeks that shifts can be assigned to. Then when applied to the live schedule the shifts will repeat based on the template shifts from the master schedule. If I create 2 weeks worth of shifts from the MasterSchedule, then these 2 weeks would repeat when saved to a LiveSchedule from a rollout date.

The problem I'm facing is handling the reoccurrence. For example for a 1 week Master Schedule, If I have a template shift on day 1 from 1am - 5am, but on day 7 there is an shift from 10pm - 3am there could be conflicts. But I'm not sure how to penalize this in the constraints. I need to somehow set day 8 as day 1 after a solution has been found then apply the constraints and calculate the scores. What would be the best way to handle this?

Heres my Shift and Employee classes:

@PlanningEntity
public class Shift {
  @PlanningId
  Long id;

  Location location;
  LocalDateTime start;
  LocalDateTime end;
  boolean locked;

  @PlanningVariable(nullable = true)
  Employee employee;

  @PlanningPin
  public boolean isLocked() {
    return locked;
  }
}


public class Employee {
  @PlanningId
  Long id;
  String name;
  double rate;
}


kurupt_89
  • 1,542
  • 8
  • 37
  • 65

1 Answers1

0

I suggest you have two different planning problems, and you should not be treating them as one:

  1. Your templates need to be optimized independently of the live schedule; that's your strategic, long-term plan.
  2. Your live schedule is continuously updated; that is your tactical, short-term plan.

Optimizing the templates should be relatively simple, as that is static data. Optimizing the live schedule is an example of continuous planning; Don't bother with any kind of recurrence, instead generate every instance of every shift you need within the given planning window. Maybe even generate shifts past the planning window, to let the solver know that there is a future and that it should not be entirely sacrified for the present.

Lukáš Petrovický
  • 3,945
  • 1
  • 11
  • 20
  • Thanks, most of that makes sense. You mentioned not worrying about recurrence, that would be fine for the live schedule. But for the master schedule the templates are meant to be recurring. A user will make adjustments to the master schedule based on a user-defined weekly rotation (e.g. 1, 2, 4, etc). For a 1 week master schedule, a shift 9-5 on Monday will repeat every Monday. But this will lead to the issue I mentioned when shifts from the beginning and end of the week can potentially overlap and end up assigning the same employee. – kurupt_89 Aug 13 '23 at 10:58
  • If, in the planning window of the master schedule, the past and the future interfere with the present, include the relevant parts of past/future in the data set. For example - if a shift overlaps from Sunday into a new planning window that starts on Monday, add that shift to the data set, but pin it so that the solver can not change it. You may run into the same issue in the live schedule as well, and the solution is the same. (In fact, you could argue that the two problems are really the same problem, but slighty different purposes may require slightly different data models.) – Lukáš Petrovický Aug 13 '23 at 13:09
  • ok great, what you mentioned (add shifts data for the next week) is what I was looking to do. What I can't work out is how to set the employee Monday shift of the next planning window from the results of the solver for the Monday shift in the current planning window. If I could do that, then the overlapping constraint would penalize the Sunday shift when assigned to the same employee from Monday. – kurupt_89 Aug 13 '23 at 13:45
  • For "next Monday" shift you can: 1) mark shift as "pinned', 2) use listener to update "next Monday" shift after assignment of "this Monday" changed 3) constraint will take into account both Mondays – Nikolai Sitnikov Sep 02 '23 at 08:59