Method: scheduling.solveShiftGeneration

Solves a shift generation problem from the given SolveShiftGenerationRequest by generating shifts from given shift templates in order to cover the employee demand.

HTTP request

POST https://optimization.googleapis.com/v1/scheduling:solveShiftGeneration

The URL uses gRPC Transcoding syntax.

Request body

The request body contains data with the following structure:

JSON representation
{
  "solverConfig": {
    object (SolverConfig)
  },
  "shiftTemplates": [
    {
      object (ShiftTemplate)
    }
  ],
  "employeeDemands": [
    {
      object (EmployeeDemand)
    }
  ],
  "employees": [
    {
      object (EmployeeInfo)
    }
  ]
}
Fields
solverConfig

object (SolverConfig)

Optional. Parameters for the solver.

shiftTemplates[]

object (ShiftTemplate)

Required. Set of shift templates specifying rules for generating shifts.

employeeDemands[]

object (EmployeeDemand)

Required. Total employee demand that the shifts generated by shiftTemplates need to cover. This field cannot be empty. As a special case, there may be a single EmployeeDemand with employeeCount unset (or 0), in which case the solver will generate the maximum number of shifts per shift template. The planning horizon is defined between the earliest start time and the latest end time across all employeeDemands.

employees[]

object (EmployeeInfo)

Optional. Additional employee information that should be considered when generating shifts.

Response body

Response for the Shift Generation problem. If the solutionStatus returned is SOLVED, then a set of valid shifts generated by the solver are returned in employeeSchedules. For a valid shift schedule, the following properties hold:

  1. Each shift generated in employeeSchedules adheres to the rules specified in the corresponding ShiftTemplate.
  2. Each event selected in each shift adheres to the rules specified in the corresponding ShiftTemplate.Event.
  3. The total number of employees assigned to the set of shifts generated from the same ShiftTemplate does not exceed maximumEmployeeCount of that template.
  4. The set of assigned employees cover the demand at every given time interval, or the uncovered demand is minimal.
  5. The overlap between events and UnwantedEventIntervals is minimal.

If successful, the response body contains data with the following structure:

JSON representation
{
  "solutionStatus": enum (ShiftGenerationSolutionStatus),
  "employeeSchedules": [
    {
      object (EmployeeSchedule)
    }
  ],
  "demandCoverageViolations": [
    {
      object (DemandCoverageViolation)
    }
  ]
}
Fields
solutionStatus

enum (ShiftGenerationSolutionStatus)

Status of the returned solution. If solutionStatus is not SOLVED, employeeSchedules will be empty.

employeeSchedules[]

object (EmployeeSchedule)

Set of shifts generated by the solver along with the number of employees assigned to each schedule.

demandCoverageViolations[]

object (DemandCoverageViolation)

Demand coverage violations based on the assigned employee_counts in the given employeeSchedules. The employeeDemands given in the request are aggregated -- if two employee_demand intervals overlap, the demand is summed over the overlapping portion of the interval.

SolverConfig

Specifies additional parameters for solving the Shift Generation problem.

JSON representation
{
  "timeLimit": string,
  "multiDaySchedule": boolean,
  "shiftEventsCanChange": boolean
}
Fields
timeLimit

string (Duration format)

Maximum time the solver should spend on the problem. If not set, defaults to 1 minute. The choice of a time limit should depend on the size of the problem. To give an example, when solving a 7-day instance with 2 ShiftTemplates, each with ~20 possible start times and holding 2 events with ~30 possible start times, and two days off per week, recommended values are: <10s for fast solutions (and likely suboptimal), (10s, 300s) for good quality solutions, and >300s for an exhaustive search. Larger instances may require longer time limits.

This value is not a hard limit and it does not account for the communication overhead. The expected latency to solve the problem may slightly exceed this value.

A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".

multiDaySchedule

boolean

If true, the solver generates EmployeeSchedules that include several shifts (e.g., to generate a week-long schedule). Otherwise, each EmployeeSchedule includes exactly one shift. Multi-day schedules assume that the start time of the shift is the same across days, and the number of days off in such a schedule is determined by the shift templates. Default is false.

shiftEventsCanChange

boolean

If true, multi-day EmployeeSchedules may include shifts for which the start and end time of their events vary across all days. Otherwise, all shifts of a particular EmployeeSchedule must have the same event's start and end times. In either case, all the shifts of a multi-day schedule have the same start and end time. As such this parameter is ignored if multiDaySchedule is false. Setting this parameter to true may result in longer solve times. Default is false.

ShiftTemplate

Template specifying rules for generating shifts. A shift is a unit of work that specifies a start time, end time, and may contain events (i.e. lunch, breaks, etc). A shift will be assigned to a specific date in the response.

JSON representation
{
  "id": string,
  "earliestStartTime": {
    object (TimeOfDay)
  },
  "latestStartTime": {
    object (TimeOfDay)
  },
  "durationMinutes": integer,
  "startTimeIncrementMinutes": integer,
  "daysOffCountPerWeek": integer,
  "daysOffDates": [
    {
      object (Date)
    }
  ],
  "eventTemplates": [
    {
      object (EventTemplate)
    }
  ],
  "minimumIntereventGapMinutes": integer,
  "minimumEmployeeCount": integer,
  "maximumEmployeeCount": integer,
  "assignableEmployeeIds": [
    string
  ]
}
Fields
id

string

Unique ID of this template.

earliestStartTime

object (TimeOfDay)

Earliest time in the day that a shift can start. This value is specified with hours and minutes; seconds and nanos are ignored.

latestStartTime

object (TimeOfDay)

Latest time in the day that a shift can start. This value is specified with hours and minutes; seconds and nanos are ignored. If this value is less than the earliestStartTime, then a shift generated by this template may start before or after midnight.

durationMinutes

integer

Fixed duration of a shift generated by this template.

startTimeIncrementMinutes

integer

The time increment (in minutes) used to generate the set of possible start times between earliestStartTime and latestStartTime. For example, if the earliest start time is 8:00, the latest start time is 8:30, and the start time increment is 10 minutes, then all possible start times for this shift template are: 8:00, 8:10, 8:20, and 8:30.

daysOffCountPerWeek

integer

Fixed number of days off per week. An employee has a given day off if they are not assigned to a shift that starts on that day. A week is 7 days and begins on Sunday. If this field is present, daysOffDates must be empty.

daysOffDates[]

object (Date)

A list of distinct dates in which shifts from this template are not generated. If this field is present, daysOffCountPerWeek must no be set.

eventTemplates[]

object (EventTemplate)

Rules for generating events for each shift. Exactly one event will be included in each shift for each Event specified.

minimumIntereventGapMinutes

integer

Minimum minutes between the end of one event and the start of the next.

minimumEmployeeCount

integer

Minimum number of employees that can be assigned to all shifts generated by this template on working days.

maximumEmployeeCount

integer

Maximum number of employees that can be assigned to all shifts generated by this template on working days.

assignableEmployeeIds[]

string

[Optional] A list of specific employee IDs that can be assigned to shifts generated by this template. If this field is present, there will be EmployeeSchedules in the response for which the EmployeeSchedule.employee_id field is set to one of the IDs in this list. The number of employee schedules with an assigned employee ID will be between minimumEmployeeCount and maximumEmployeeCount. If this field is empty, between minimumEmployeeCount and maximumEmployeeCount employees can be assigned to shifts generated by this template and the employee schedules won't have an assigned employee ID. Currently, only one assignable employee ID is supported.

TimeOfDay

Represents a time of day. The date and time zone are either not significant or are specified elsewhere. An API may choose to allow leap seconds. Related types are google.type.Date and google.protobuf.Timestamp.

JSON representation
{
  "hours": integer,
  "minutes": integer,
  "seconds": integer,
  "nanos": integer
}
Fields
hours

integer

Hours of a day in 24 hour format. Must be greater than or equal to 0 and typically must be less than or equal to 23. An API may choose to allow the value "24:00:00" for scenarios like business closing time.

minutes

integer

Minutes of an hour. Must be greater than or equal to 0 and less than or equal to 59.

seconds

integer

Seconds of a minute. Must be greater than or equal to 0 and typically must be less than or equal to 59. An API may allow the value 60 if it allows leap-seconds.

nanos

integer

Fractions of seconds, in nanoseconds. Must be greater than or equal to 0 and less than or equal to 999,999,999.

Date

Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following:

  • A full date, with non-zero year, month, and day values.
  • A month and day, with a zero year (for example, an anniversary).
  • A year on its own, with a zero month and a zero day.
  • A year and month, with a zero day (for example, a credit card expiration date).

Related types:

JSON representation
{
  "year": integer,
  "month": integer,
  "day": integer
}
Fields
year

integer

Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year.

month

integer

Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day.

day

integer

Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.

EventTemplate

Template specifying rules for generating a single event that occurs during a shift. An event may represent a meeting, break, lunch, etc.

JSON representation
{
  "id": string,
  "minimumMinutesAfterShiftStart": integer,
  "maximumMinutesAfterShiftStart": integer,
  "durationMinutes": integer,
  "startTimeIncrementMinutes": integer
}
Fields
id

string

Unique ID of this template.

minimumMinutesAfterShiftStart

integer

Minimum number of minutes after the beginning of a shift that this event can start.

maximumMinutesAfterShiftStart

integer

Maximum number of minutes after the beginning of a shift that this event can start.

durationMinutes

integer

Fixed duration in minutes of this event.

startTimeIncrementMinutes

integer

The time increment (in minutes) used to generate the set of possible event start times between minimumMinutesAfterShiftStart and maximumMinutesAfterShiftStart. For example, if the minimum minutes after shift start are 30, maximum minutes after shift start are 45, and the start time increment is 5 minutes, the event can take place 30, 35, 40, or 45 minutes after the start of the shift.

EmployeeDemand

Specifies the number of employees required to cover the demand in the given DateTime interval. The length of the interval must be strictly positive.

JSON representation
{
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "employeeCount": integer
}
Fields
startDateTime

object (DateTime)

Start of the time interval for the given demand (inclusive). These values are read down to the minute; seconds and all smaller units are ignored.

endDateTime

object (DateTime)

End of the time interval for the given demand (exclusive). These values are read down to the minute; seconds and all smaller units are ignored.

employeeCount

integer

Number of employees needed to cover the demand for this interval.

EmployeeInfo

Information for a particular employee regarding unwanted event intervals.

JSON representation
{
  "id": string,
  "unwantedEventIntervals": [
    {
      object (UnwantedEventInterval)
    }
  ]
}
Fields
id

string

Unique ID of this employee.

unwantedEventIntervals[]

object (UnwantedEventInterval)

A list of unwanted event intervals for this employee. The start time of the interval must be in the planning horizon.

UnwantedEventInterval

Specifies a time interval during which the overlap with events (generated from event templates) should be minimal.

JSON representation
{
  "startDateTime": {
    object (DateTime)
  },
  "durationMinutes": integer
}
Fields
startDateTime

object (DateTime)

Start time of the event.

durationMinutes

integer

Duration of the event.

ShiftGenerationSolutionStatus

Solution status provided in the response of a solver.

Enums
SHIFT_GENERATION_SOLUTION_STATUS_UNSPECIFIED Unspecified status for the response.
SHIFT_GENERATION_SOLVED The solver found a solution in the time limit provided.
SHIFT_GENERATION_NOT_SOLVED An issue prevented the solver from generating shifts.
SHIFT_GENERATION_NOT_SOLVED_DEADLINE_EXCEEDED Shifts could not be generated to cover the demand within the time limit given.

EmployeeSchedule

An ordered list of shifts corresponding to a single ShiftTemplate. If the shift template used to generate this schedule has assignableEmployeeIds, then this schedule has a specific employee ID (see employeeId). Otherwise (assignableEmployeeIds is empty), the schedule needs to be assigned to employeeCount employees and no specific employee ID is given.

JSON representation
{
  "shiftTemplateId": string,
  "shifts": [
    {
      object (ShiftWithEvents)
    }
  ],
  "employeeCount": integer,
  "employeeId": string
}
Fields
shiftTemplateId

string

ID of the template that was used to generate this set of shifts.

shifts[]

object (ShiftWithEvents)

List of shifts to which employeeCount number of employees are assigned. Shifts and events selected for the schedule were generated from a single template. Shifts are sorted chronologically and do not overlap. If the SolverConfig.multi_day_schedule is true, a day off is represented implicitly by the absence of a shift starting on that day.

employeeCount

integer

Number of employees that should be assigned to this set of shifts to cover the demand.

employeeId

string

ID of the employee to which this schedule is assigned. This field is present if and only if the ShiftTemplate had assignableEmployeeIds.

ShiftWithEvents

Specifies the start and end date along with a list of fixed events of a shift generated by the solver.

JSON representation
{
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "events": [
    {
      object (Event)
    }
  ]
}
Fields
startDateTime

object (DateTime)

Start date and time of the shift. This value is specified down to the minute; seconds and smaller units are not given.

endDateTime

object (DateTime)

End date and time of the shift. This value is specified down to the minute; seconds and smaller units are not given.

events[]

object (Event)

List of events included in this shift, mapped exactly to, and in the same order as, the ShiftTemplate.Events. If SolverConfig.shift_events_can_change is true, the start and end times of the events may vary across all the ShiftWithEvents of this schedule.

Event

Specifies the start and end DateTime of a specific event in a shift generated by the solver.

JSON representation
{
  "eventTemplateId": string,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  }
}
Fields
eventTemplateId

string

ID of the template that was used to generate this event.

startDateTime

object (DateTime)

Start date and time of the event. This value is specified down to the minute; seconds and smaller units are not given.

endDateTime

object (DateTime)

End date and time of the event. This value is specified down to the minute; seconds and smaller units are not given.

DemandCoverageViolation

Specifies the demand coverage violation for the given interval. The employee demand is the same throughout the entire specified interval.

JSON representation
{
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "coverageViolation": integer
}
Fields
startDateTime

object (DateTime)

Start date and time of the demand interval (inclusive). This value is specified down to the minute.

endDateTime

object (DateTime)

End date and time of the demand interval (exclusive). This value is specified down to the minute.

coverageViolation

integer

Coverage violation during the specified interval. A positive value indicates that the demand is overcovered, and a negative value indicates that the demand is undercovered.