Method: scheduling.solveShiftScheduling

Solves a fixed shift scheduling problem from the given SolveShiftSchedulingRequest by assigning employees to shifts such that employees' scheduling preferences are maximized and scheduling constraint violations are minimized.

HTTP request

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

The URL uses gRPC Transcoding syntax.

Request body

The request body contains data with the following structure:

JSON representation
{
  "requestId": string,
  "solveParameters": {
    object (SolveParameters)
  },
  "employees": [
    {
      object (Employee)
    }
  ],
  "shifts": [
    {
      object (Shift)
    }
  ],
  "coverageRequirements": [
    {
      object (CoverageRequirement)
    }
  ],
  "roleIds": [
    string
  ],
  "skillIds": [
    string
  ],
  "locationIds": [
    string
  ],
  "budgetRequirements": [
    {
      object (BudgetRequirement)
    }
  ],
  "assignmentsHint": [
    {
      object (ShiftAssignment)
    }
  ]
}
Fields
requestId

string

Problem or request ID.

solveParameters

object (SolveParameters)

Parameters to control a single solve of the problem.

employees[]

object (Employee)

All available employees to be scheduled.

shifts[]

object (Shift)

All shifts to form the schedule.

coverageRequirements[]

object (CoverageRequirement)

Coverage requirements for the entire planning horizon. These specify the number of employees that must perform each role, or possess a skill, during either a time window or a list of shift IDs. All coverage requirements must be specified with either time windows or a list of shift IDs (but not both). Time windows (if given) for the coverage requirements cannot overlap for each given location. The default priority level for each of these constraints is PRIORITY_MANDATORY for the role requirements and PRIORITY_LOW for the skill requirements. See the Priority enum for more details.

roleIds[]

string

List of all possible roles across the workforce. Each employee must have at least one role that they can be assigned to for a shift. A Role refers to a specific job assignment during a shift (i.e. registered nurse, executive chef, waiter, etc). When an employee is assigned to a shift, they are also assigned to a single specific role.

skillIds[]

string

List of all possible skills across the workforce. A Skill refers to any extra qualifications an employee may have that do not pertain to a specific assignable job (i.e. certifications, languages spoken, etc). This list can be empty. When an employee is assigned to a shift, they must fulfill all skills needed for that shift.

locationIds[]

string

List of all possible locations for the set of shifts in the schedule. This list can be empty. Specifying different locations can be useful when, for example, a nurse manager wants to schedule many nurses across different units at a hospital or, for another example, a hotel manager wants to schedule employees across multiple hotels.

budgetRequirements[]

object (BudgetRequirement)

Budget specification for the scheduling problem. The default priority level for each of these requirements is PRIORITY_LOW. See the Priority enum for more details.

assignmentsHint[]

object (ShiftAssignment)

Shift assignments to use as a tentative solution (a.k.a. solution hint) to the scheduling problem. Assignment hints are ignored if the assignment contradicts a nonassignable shift or a scheduling request.

Response body

Response for the workforce scheduling API. For each response, the shiftAssignments will be empty if the solutionStatus returned is NOT_SOLVED_DEADLINE_EXCEEDED or INFEASIBLE. If the solutionStatus returned is OPTIMAL or FEASIBLE, then a valid shift assignment is returned in shiftAssignments. For a valid shift assignment, the following properties hold:

  1. Each employee ID is contained in the set of employees given in the request.
  2. Each role ID assigned to the employee is contained in the set of role IDs for the given employee.
  3. Each shift ID is contained in the set of shifts given in the request.
  4. Each shift ID is not one of the nonassignable shift IDs for the given employee.
  5. An employee will never be assigned to two overlapping shifts.
  6. For the given schedule, none of the constraints or requests with priority level PRIORITY_MANDATORY are violated.

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

JSON representation
{
  "requestId": string,
  "solutionStatus": enum (SolutionStatus),
  "shiftAssignments": [
    {
      object (ShiftAssignment)
    }
  ],
  "statusMessage": string
}
Fields
requestId

string

The ID of the request that this response is associated with.

solutionStatus

enum (SolutionStatus)

Status of the returned solution. If the solution is not FEASIBLE or OPTIMAL, other fields in this proto may be empty. If the status is NOT_SOLVED_DEADLINE_EXCEEDED, the time limit was reached without finding a feasible solution or determining if a feasible solution exists. Requests may be infeasible if the constraints of priority level MANDATORY cannot all be satisfied.

shiftAssignments[]

object (ShiftAssignment)

List of all assignments. Each ShiftAssignment specifies an employee, the shift they are assigned to, and the role they are assigned to perform for that shift.

statusMessage

string

If solutionStatus is not optimal, this field may contain additional information about the solver.

SolveParameters

Parameters that control a single solve of the shift scheduling problem.

JSON representation
{
  "timeLimit": string
}
Fields
timeLimit

string (Duration format)

Maximum time the solver should spend on the problem. If not set, defaults to 1 minute.

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".

Employee

An employee from the workforce to be scheduled.

JSON representation
{
  "id": string,
  "roleIds": [
    string
  ],
  "skillIds": [
    string
  ],
  "shiftPreferences": [
    {
      object (ShiftPreference)
    }
  ],
  "schedulingConstraints": [
    {
      object (SchedulingConstraint)
    }
  ],
  "resourceConstraints": [
    {
      object (ResourceConstraint)
    }
  ],
  "shiftRequests": [
    {
      object (ShiftRequest)
    }
  ],
  "hourlyContract": {
    object (HourlyContract)
  }
}
Fields
id

string

Unique ID assigned to this employee.

roleIds[]

string

Role IDs that this employee can perform. There must be at least one role specified. When an employee is assigned to a shift, they are also assigned to a single role from this list. The employee may be assigned to different roles during the scheduling window.

skillIds[]

string

Skill IDs that this employee possesses. This list can be empty. When an employee is assigned to a shift, they use any subset of the skills listed here to cover skill requirements throughout the duration of the assigned shift.

shiftPreferences[]

object (ShiftPreference)

Shift preferences of this employee. The shifts specified here represent shifts the employee would prefer to be assigned to during the scheduling window. The shift IDs specified in shiftPreferences must be unique. The solver will try to maximize the sum of the ShiftPreference.preference values over all shiftPreferences that are satisfied.

schedulingConstraints[]

object (SchedulingConstraint)

List of scheduling constraints for this employee. The default priority level for each of these constraints is PRIORITY_MEDIUM. See the Priority enum for more details.

resourceConstraints[]

object (ResourceConstraint)

Any additional scheduling constraints not specified in schedulingConstraints can be added here to resourceConstraints. A ResourceConstraint is a more abstract representation for limiting resources for an employee. The default priority level for each of these constraints is PRIORITY_MEDIUM. See the Priority enum for more details.

shiftRequests[]

object (ShiftRequest)

List of shift requests for the employee. The request can be for an employee to be assigned or not assigned to specific shifts. Any fixed scheduling assignments for the employee can be represented with a ShiftRequest with priority PRIORITY_MANDATORY. A shift ID may appear in at most one scheduling request for this employee. The default priority level for each of these requests is PRIORITY_LOW. See the Priority enum for more details.

hourlyContract

object (HourlyContract)

Contract that specifies regular and overtime hourly rates for the employee.

ShiftPreference

A numeric preference for a particular shift ID.

JSON representation
{
  "shiftId": string,
  "preference": integer
}
Fields
shiftId

string

Shift ID for which the preference is specified.

preference

integer

Larger values of preference denote a more desirable shift.

SchedulingConstraint

Specific scheduling constraint for a particular employee. The constraint specified is only applied during the given interval [startDateTime, endDateTime).

JSON representation
{
  "priority": enum (Priority),
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },

  // Union field type can be only one of the following:
  "minimumMinutes": integer,
  "maximumMinutes": integer,
  "minimumConsecutiveWorkDays": integer,
  "maximumConsecutiveWorkDays": integer,
  "minimumShiftCount": integer,
  "maximumShiftCount": integer,
  "minimumRestMinutes": integer
  // End of list of possible types for union field type.
}
Fields
priority

enum (Priority)

Priority level for this scheduling constraint. The default priority for all scheduling constraints is PRIORITY_MEDIUM.

startDateTime

object (DateTime)

The start time for when this scheduling constraint applies (inclusive).

endDateTime

object (DateTime)

The end time for when this scheduling constraint applies (exclusive).

Union field type. The type of constraint being specified. Each constraint is only applied within the time window specified above. type can be only one of the following:
minimumMinutes

integer

Minimum number of minutes the employee can work. If the employee is assigned to a shift that overlaps (fully or partially) the time window, the number of minutes that the shift overlaps the time window is included in this count.

maximumMinutes

integer

Maximum number of minutes the employee can work in the time window. If the employee is assigned to a shift that overlaps (fully or partially) the time window, the number of minutes that the shift overlaps the time window is included in this count.

minimumConsecutiveWorkDays

integer

Minimum number of consecutive days the employee can work. An employee works on a specific day if they are assigned to a shift that starts during that day. Any shift that the employee is assigned to that begins in the time window is included in this count.

maximumConsecutiveWorkDays

integer

Maximum number of consecutive days the employee can work. An employee works on a specific day if they are assigned to a shift that starts during that day. Any shift that the employee is assigned to that begins in the time window is included in this count.

minimumShiftCount

integer

Minimum number of shifts the employee can work. Any shift that the employee is assigned to that fully overlaps with the time window is included in this count.

maximumShiftCount

integer

Maximum number of shifts the employee can work. Any shift that the employee is assigned to that fully overlaps with the time window is included in this count.

minimumRestMinutes

integer

Minimum number of minutes the employee must rest after the end of one shift before being assigned to another shift. This constraint applies to every pair of shifts that are fully included in [startDateTime, endDateTime].

Priority

The priority level for any constraint on an employee's schedule or the coverage requirements. These include SchedulingConstraint, ResourceConstraint, ShiftRequest, and CoverageRequirement. Because there could be conflicting constraints, it is not always possible to satisfy every constraint. As such, each type of constraint has a priority (given by the user or a default) that informs the solver about the relative importance of all the constraints given to a complete schedule.

Enums
PRIORITY_UNSPECIFIED Unknown priority level.
PRIORITY_LOW The lowest priority level. Constraints with this priority are less important that the other constraints. They are the first to be considered for violation if a feasible solution cannot be found.
PRIORITY_MEDIUM Priority level medium. Constraints with this priority are more important than constraints with PRIORITY_LOW priority but less important than constraints with PRIORITY_HIGH priority. If a feasible solution cannot be found after relaxing all constraints with PRIORITY_LOW priority, then constraints of PRIORITY_MEDIUM priority are considered next for violation.
PRIORITY_HIGH The highest priority level. Constraints with this priority level are the most important. They are the last to be considered for violation if a feasible solution cannot be found after relaxing constraints of the lower priority levels.
PRIORITY_MANDATORY Priority level that represents something that cannot be violated by the solver. If the solver is returning SolutionStatus.INFEASIBLE, it may be due to too many PRIORITY_MANDATORY constraints.

ResourceConstraint

A general constraint that limits the amount of a certain "resource" used by an employee. This is an abstract version of the more specific SchedulingConstraint that is more flexible for the user. Many scheduling constraints that cannot be specified in the SchedulingConstraint.type can be specified using this message instead.

JSON representation
{
  "priority": enum (Priority),
  "resourceUsages": {
    string: number,
    ...
  },
  "minimumResourceUsage": number,
  "maximumResourceUsage": number
}
Fields
priority

enum (Priority)

Priority level of this resource constraint. The default priority for all resource constraints is PRIORITY_MEDIUM.

resourceUsages

map (key: string, value: number)

Amount of resource used by shifts. For example, if this constraint applies to the minimum and maximum hours worked by an employee in a specific week, then this map will contain the shifts that occur in that week and the length of each shift in hours.

An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.

minimumResourceUsage

number

Minimum resource usage for a resource constraint to be satisfied.

maximumResourceUsage

number

Maximum resource usage for a resource constraint to be satisfied.

ShiftRequest

An employee's request to be assigned or not be assigned to specific shifts.

JSON representation
{
  "priority": enum (Priority),
  "shiftIds": [
    string
  ],
  "type": enum (WorkStatus)
}
Fields
priority

enum (Priority)

Priority level of this scheduling request. The default priority for all scheduling requests is PRIORITY_LOW.

shiftIds[]

string

The shift IDs of the scheduling request.

type

enum (WorkStatus)

Request type, e.g., whether the request is be assigned or not be assigned to the set of shifts.

WorkStatus

Whether an employee is working or not.

Enums
WORK_STATUS_UNSPECIFIED Unknown work status.
STATUS_WORK Status representing a working employee.
STATUS_NOT_WORK Status representing a non-working employee.

HourlyContract

Specifies a base hourly rate, rate differentials, and overtime multipliers to determine the compensation for an employee. Note regulations in different places might require a different computation of overtime compensation. The solver approximates the overtime compensation to either minimize a proxy of the total cost or meet a budget (see BudgetRequirement). It is not intended as a tool to compute payroll.

JSON representation
{
  "baseHourlyRate": number,
  "hourlyRateShiftDifferentials": {
    string: number,
    ...
  },
  "overtimePeriods": [
    {
      object (OvertimePeriod)
    }
  ]
}
Fields
baseHourlyRate

number

The compensation for working a non-overtime hour. If multiple rates apply to the employee, rate differentials are applied relative to this base hourly rate. Additionally, if there are multiple rates, the base hourly rate should be the minimum of these rates.

hourlyRateShiftDifferentials

map (key: string, value: number)

The hourly rate differential, paid on top of the baseHourlyRate. For example, if the base hourly rate is $30/hr, "shift_1" is paid at a rate of $40/hr and, "shift_2" is paid at a rate of $45/hr, then the proto representation is: baseHourlyRate: 30 hourlyRateShiftDifferentials {key: "shift_1" value: 10} hourlyRateShiftDifferentials {key: "shift_2" value: 15}.

An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.

overtimePeriods[]

object (OvertimePeriod)

A list of all periods for which overtime has to be computed. These periods must not overlap.

OvertimePeriod

A fixed and regularly recurring period (typically 168 hours or seven consecutive 24-hour periods) that is used to determine the amount of overtime compensation. Each period has an overtime multiplier (e.g., 1.5) relative to the baseHourlyRate and a limit on the number of hours that are considered regular (non-overtime) work. Any shift that overlaps with the startDateTime (inclusive) and endDateTime (exclusive) time window is counted towards the total number hours worked in the period. If the overlap is partial, only the overlapping hours are counted.

JSON representation
{
  "overtimeMultiplier": number,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "maximumRegularHours": number
}
Fields
overtimeMultiplier

number

Multiplier to compute the overtime hourly rate (must be greater or equal to 1.0). The overtime hourly rate will typically be computed as baseHourlyRate * overtimeMultiplier. If there are multiple rates given through hourlyRateShiftDifferentials, the solver approximates the overtime hourly rate with a simple average of the rates that are applicable during the overtime period. Note: regulations in different places might require a different computation of overtime compensation. The solver approximates the overtime compensation to either minimize a proxy of the total cost or meet a budget, but it is not intended as a tool to compute payroll.

startDateTime

object (DateTime)

Start time for the overtime period. If a shift overlaps this time, the hours of such a shift are counted from startDateTime.

endDateTime

object (DateTime)

End time for the overtime period. If a shift overlaps this time, the hours of such a shift are counted up to endDateTime.

maximumRegularHours

number

Maximum number of working hours that are paid at a regular (non-overtime) rate. This quantity must be positive.

Shift

A shift specifies a fixed time window in which employees can work.

JSON representation
{
  "id": string,
  "locationId": string,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "breakRules": [
    {
      object (BreakRule)
    }
  ]
}
Fields
id

string

Unique ID assigned to this shift.

locationId

string

Location ID in which this shift is worked. This can be empty.

startDateTime

object (DateTime)

The start time of the shift (inclusive).

endDateTime

object (DateTime)

The end time of the shift (exclusive). Currently, the solver only allows for shifts that are less than 24hrs in length.

breakRules[]

object (BreakRule)

A list of break rules that occur during the shift. Employees doing this shift are assigned a break per break_rule, during which they do not cover the demand for the role they are fulfilling. Each BreakRule time window must be fully included within this shift's time window.

BreakRule

A rule that determines when a break can start within a shift and its duration. The list of all possible breaks that are considered is determined in increments of ruleIncrementMinutes. For example, if a break rule is modeling a 30-minute break that can start between 10:00 and 11:00, and the rule increment is of 20 minutes, the list of breaks that are considered are: [10:00, 10:30], [10:20, 10:50], [10:40, 11:10], [11:00, 11:30].

JSON representation
{
  "earliestStartTime": {
    object (DateTime)
  },
  "latestStartTime": {
    object (DateTime)
  },
  "durationMinutes": integer,
  "ruleIncrementMinutes": integer
}
Fields
earliestStartTime

object (DateTime)

The earliest start time of the break (inclusive). Only hours and minutes can be set.

latestStartTime

object (DateTime)

The latest start time of the break (inclusive). Only hours and minutes can be set.

durationMinutes

integer

Duration of the break in minutes.

ruleIncrementMinutes

integer

[Optional] Time increment in minutes for all the breaks that can be considered in this break rule. If not set, defaults to durationMinutes.

CoverageRequirement

A coverage requirement specifies the number of employees required for a set of roles and/or skills during a particular time window and at a given location. DateTime intervals at a particular location cannot overlap. Alternatively, a list of shift IDs can be provided instead of a time window and a location. Only employees which can be assigned to the specific role (or that possess the specific skill) can meet this requirement.

For a given role and/or skill, the coverage requirement is fulfilled when at least targetEmployeeCount number of employees are working at every moment in the time window (or for every shift in shiftIds). In contrast, the coverage requirement is violated if at any point in the time window (or for any of the shifts in shiftIds), there are fewer than targetEmployeeCount number of employees working during the time window. More working employees than the targetEmployeeCount still fulfills the requirement, but excessive staffing is minimized by the solver.

JSON representation
{
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "locationId": string,
  "shiftIds": [
    string
  ],
  "roleRequirements": [
    {
      object (RoleRequirement)
    }
  ],
  "skillRequirements": [
    {
      object (SkillRequirement)
    }
  ]
}
Fields
startDateTime

object (DateTime)

The start time for the coverage requirement (inclusive). If set, shiftIds must be empty.

endDateTime

object (DateTime)

The end time for the coverage requirement (exclusive). If set, shiftIds must be empty.

locationId

string

Location in which the employees are needed. shiftIds is not empty, this field must be empty.

shiftIds[]

string

If set, the role and skill requirements are applied individually to every shift ID in this list. If shiftIds are nonempty, then startDateTime, endDateTime, and locationId must be empty.

roleRequirements[]

object (RoleRequirement)

Required number of employees to be assigned to the specified roles during the time window. At most one role_requirement must be given for each role ID. The default priority level for each of the requirements is PRIORITY_MANDATORY. These constraints are violated if fewer than targetEmployeeCount number of employees are assigned to the specified roles at any point during the time window.

skillRequirements[]

object (SkillRequirement)

Required number of employees with the specified skills that are assigned to shifts during the time window. At most one skill_requirement must be given for each skill ID. The default priority level for each of the requirements is PRIORITY_LOW. These constraints are violated if fewer than targetEmployeeCount number of employees possess the given skills at any point during the time window.

RoleRequirement

Required number of employees to be assigned to the specified role during the time window.

JSON representation
{
  "roleId": string,
  "targetEmployeeCount": integer,
  "priority": enum (Priority)
}
Fields
roleId

string

Role ID for the requirement.

targetEmployeeCount

integer

Desired number of employees assigned to the role during the time window.

priority

enum (Priority)

Priority level for this requirement constraint. The default priority for all resource constraints is PRIORITY_MANDATORY.

SkillRequirement

Required number of employees that are working during the time window and possess the specified skill.

JSON representation
{
  "skillId": string,
  "targetEmployeeCount": integer,
  "priority": enum (Priority)
}
Fields
skillId

string

Skill ID for the requirement.

targetEmployeeCount

integer

Desired number of employees with the given skill that are working during the time window.

priority

enum (Priority)

Priority level for this requirement constraint. The default priority for all resource constraints is PRIORITY_LOW.

BudgetRequirement

Budget requirements for a given interval.

JSON representation
{
  "totalBudget": number,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "priority": enum (Priority)
}
Fields
totalBudget

number

Total budget for the given interval. A total budget must be given if the priority is PRIORITY_MANDATORY.

If totalBudget is not set, then the total cost of the schedule is minimized according to the specified priority. For example, if the priority for the budget is PRIORITY_MEDIUM, then the solver will minimize the cost before reducing any constraint violation with priority PRIORITY_LOW.

startDateTime

object (DateTime)

Start time for when this budget applies. If a start time is not specified, it is set to be the earliest start time of all given shifts.

endDateTime

object (DateTime)

End time for when this budget applies. If an end time is not specified, it is set to be the latest end time of all given shifts.

priority

enum (Priority)

Priority level for meeting the budget requirement during the specified time window. The default priority is PRIORITY_LOW. If the priority is set to PRIORITY_MANDATORY, then totalBudget must be set.

Note that if this priority is higher than other constraint priorities and if totalBudget is tight, then the resulting schedule could significantly violate both employee constraints or coverage requirements.

ShiftAssignment

An employee to shift-role assignment.

JSON representation
{
  "employeeId": string,
  "shiftId": string,
  "roleId": string,
  "breaks": [
    {
      object (Break)
    }
  ]
}
Fields
employeeId

string

The employee ID being assigned.

shiftId

string

Shift ID assigned to the employee.

roleId

string

Role ID the employee is assigned to for the shift.

breaks[]

object (Break)

List of breaks for this shift assignment.

Break

A time period in which an employee interrupts their work during a shift.

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

object (DateTime)

The start time of a break.

durationMinutes

integer

Duration of the break in minutes.

SolutionStatus

Solution (i.e., a schedule) status provided in the response of a solver.

Enums
SOLUTION_STATUS_UNSPECIFIED Unspecified status for the response.
FEASIBLE The returned schedule is feasible, but might not be optimal.
OPTIMAL The returned schedule is optimal.
INFEASIBLE No feasible schedule exists for the given constraints. The solver may return this value if any subset of the constraints with priority level PRIORITY_MANDATORY cannot be satisfied.
NOT_SOLVED No schedule was found.
NOT_SOLVED_DEADLINE_EXCEEDED No schedule was found within the time limit given.