Method: scheduling.solveShiftScheduling

通过将员工分配至轮班,使员工的时间安排偏好最大化,并最大限度地减少违反排班限制的情况,解决给定 SolveShiftSchedulingRequest 中的固定排班安排问题。

HTTP 请求

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

网址采用 gRPC 转码语法。

请求正文

请求正文中包含结构如下的数据:

JSON 表示法
{
  "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)
    }
  ]
}
字段
requestId

string

问题或请求 ID。

solveParameters

object (SolveParameters)

用于控制单次求解的参数。

employees[]

object (Employee)

对所有有空的员工进行安排。

shifts[]

object (Shift)

构成时间表的所有班次。

coverageRequirements[]

object (CoverageRequirement)

整个规划范围的覆盖率要求。这些工作规定了在某个时间段或一系列轮班 ID 中,必须履行每项角色或具备某项技能的员工人数。必须通过时间范围或轮班 ID 列表指定所有覆盖范围要求(但不能同时指定两者)。覆盖率要求的时间范围(如果指定)不能与每个指定位置重叠。对于角色要求,这些限制条件的默认优先级为 PRIORITY_MANDATORY;对于技能要求,则默认优先级为 PRIORITY_LOW。如需了解详情,请参阅 Priority 枚举。

roleIds[]

string

员工团队所有可能的角色的列表。每位员工都必须至少有一个可以分配给轮班的角色。角色是指轮班期间的特定工作分配(例如注册护士、行政厨师、服务员等)。当员工分配到轮班时,系统也会为他们分配一种特定的角色。

skillIds[]

string

列出了所有员工可能具备的技能。技能是指员工可能获得的、与具体可分配工作无关的任何额外资格(例如,认证、所讲的语言等)。此列表可以为空。员工被分配到某个轮班后,该员工必须完成该轮班所需的所有技能。

locationIds[]

string

时间表中相应班次的所有可能位置的列表。此列表可以为空。例如,当护士经理想要在一家医院的不同部门之间安排许多护士时,或者,酒店经理想要安排在多个酒店的员工时,可以指定不同的地理位置。

budgetRequirements[]

object (BudgetRequirement)

针对时间安排问题的预算规范。每项要求的默认优先级为 PRIORITY_LOW。如需了解详情,请参阅 Priority 枚举。

assignmentsHint[]

object (ShiftAssignment)

转换分配,用作调度问题的暂定解决方案(也称为解决方案提示)。如果分配与不可分配的班次或时间安排请求冲突,系统会忽略分配提示。

响应正文

对员工调度 API 的响应。对于每个响应,如果返回的 solutionStatusNOT_SOLVED_DEADLINE_EXCEEDEDINFEASIBLE,则 shiftAssignments 将为空。如果返回的 solutionStatusOPTIMALFEASIBLE,则 shiftAssignments 中会返回有效的移位赋值。对于有效的 shift 分配,必须具备以下属性:

  1. 每个员工 ID 都包含在请求中提供的员工集中。
  2. 分配给该员工的每个角色 ID 都包含在相应员工的角色 ID 集中。
  3. 每个班次 ID 都包含在请求中提供的一组班次中。
  4. 每个轮班 ID 都不是指定员工的不可分配的轮班 ID 之一。
  5. 员工绝不会有两轮重叠的轮班。
  6. 对于给定的时间表,没有违反任何优先级为 PRIORITY_MANDATORY 的限制条件或请求。

如果成功,响应正文将包含结构如下的数据:

JSON 表示法
{
  "requestId": string,
  "solutionStatus": enum (SolutionStatus),
  "shiftAssignments": [
    {
      object (ShiftAssignment)
    }
  ],
  "statusMessage": string
}
字段
requestId

string

与此响应关联的请求的 ID。

solutionStatus

enum (SolutionStatus)

所返回解决方案的状态。如果解决方案不可行或不可优化,此 proto 中的其他字段可能为空。如果状态为 NOT_SOLVED_DEADLINE_EXCEEDED,则表示已达到时间限制,而没有找到可行的解决方案或确定是否存在可行的解决方案。如果优先级“MANDATORY”的限制无法全部满足,请求可能会不可行。

shiftAssignments[]

object (ShiftAssignment)

所有分配的列表。每个 ShiftAssignment 均指定一名员工、他们分配到的班次以及为该次班分配的角色。

statusMessage

string

如果 solutionStatus 不是最佳值,则此字段可能包含有关求解器的更多信息。

SolveParameters

用于控制轮班调度问题单次求解的参数。

JSON 表示法
{
  "timeLimit": string
}
字段
timeLimit

string (Duration format)

求解器在问题上花费的时间上限。如果未设置,则默认为 1 分钟。

这个值不是硬性限制,也没有考虑通信开销。解决该问题的预期延迟时间可能会略微超过此值。

此时长以秒为单位,最多包含九个小数位,以“s”结尾。示例:"3.5s"

员工

要安排的一名员工。

JSON 表示法
{
  "id": string,
  "roleIds": [
    string
  ],
  "skillIds": [
    string
  ],
  "shiftPreferences": [
    {
      object (ShiftPreference)
    }
  ],
  "schedulingConstraints": [
    {
      object (SchedulingConstraint)
    }
  ],
  "resourceConstraints": [
    {
      object (ResourceConstraint)
    }
  ],
  "shiftRequests": [
    {
      object (ShiftRequest)
    }
  ],
  "hourlyContract": {
    object (HourlyContract)
  }
}
字段
id

string

分配给此员工的唯一 ID。

roleIds[]

string

此员工可以执行的角色 ID。必须至少指定一个角色。当员工被分配到某个轮班时,他们也会分配到此列表中的单个角色。在时间安排期间,员工可能会被分配不同的角色。

skillIds[]

string

此员工拥有的技能 ID。此列表可以为空。员工分配到某个轮班后,该员工会在分配给该轮班的整个期间使用本文所列的任意技能组合来满足技能要求。

shiftPreferences[]

object (ShiftPreference)

调整此员工的偏好。此处指定的班次表示希望员工在时间安排期间分配到的班次。shiftPreferences 中指定的班次 ID 必须是唯一的。该求解器会尝试尽可能提高所有满足的 shiftPreferencesShiftPreference.preference 值的总和。

schedulingConstraints[]

object (SchedulingConstraint)

此员工的时间安排限制条件列表。其中每个约束条件的默认优先级都是 PRIORITY_MEDIUM。如需了解详情,请参阅 Priority 枚举。

resourceConstraints[]

object (ResourceConstraint)

未在 schedulingConstraints 中指定的任何其他时间安排限制条件可在此处添加到 resourceConstraints 中。ResourceConstraint 是一种更抽象的表示法,用于限制员工的资源。其中每个约束条件的默认优先级都是 PRIORITY_MEDIUM。如需了解详情,请参阅 Priority 枚举。

shiftRequests[]

object (ShiftRequest)

员工的轮班请求列表。申请可以指派某个员工,也可以不为其分配特定班次。员工的任何固定时间安排分配都可以用优先级为 PRIORITY_MANDATORYShiftRequest 表示。一个轮班 ID 最多可出现在此员工的一个日程安排请求中。所有这些请求的默认优先级为 PRIORITY_LOW。如需了解详情,请参阅 Priority 枚举。

hourlyContract

object (HourlyContract)

规定员工按时费率和加班费率计算的合同。

ShiftPreference

特定轮班 ID 的数字偏好设置。

JSON 表示法
{
  "shiftId": string,
  "preference": integer
}
字段
shiftId

string

为其指定偏好设置的 Shift ID。

preference

integer

偏好值越大,表示效果的转变越可取。

SchedulingConstraint

特定员工的特定日程安排限制条件。指定的约束条件仅在给定间隔 [startDateTime, endDateTime) 内应用。

JSON 表示法
{
  "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.
}
字段
priority

enum (Priority)

此时间安排限制条件的优先级。所有时间安排限制条件的默认优先级均为 PRIORITY_MEDIUM

startDateTime

object (DateTime)

应用此时间安排限制条件的开始时间(含此时间)。

endDateTime

object (DateTime)

应用此投放时间限制条件的结束时间(不含)。

联合字段 type。指定的限制条件的类型。每个限制条件仅在上述指定的时间范围内应用。type 只能是下列其中一项:
minimumMinutes

integer

员工可以工作的最少分钟数。如果分配给员工的轮班与(完全或部分)时间窗口重叠,则这次轮班与时间窗口重叠的分钟数将包含在计数中。

maximumMinutes

integer

员工可以在时间范围内工作的分钟数上限。如果分配给员工的轮班与(完全或部分)时间窗口重叠,则这次轮班与时间窗口重叠的分钟数将包含在计数中。

minimumConsecutiveWorkDays

integer

员工可以连续工作的最短天数。如果员工分配到的班次是在某天开始的,则该员工会在特定日期工作。员工分配到的任何班次在这段时间内开始,都计入此次数中。

maximumConsecutiveWorkDays

integer

员工可以连续工作的最长天数。如果员工分配到的班次是在某天开始的,则该员工会在特定日期工作。员工分配到的任何班次在这段时间内开始,都计入此次数中。

minimumShiftCount

integer

员工可以工作的最小排班次数。员工分配到的任何班次与时间窗口完全重叠,都计入此次数中。

maximumShiftCount

integer

员工可以工作的轮班次数上限。员工分配到的任何班次与时间窗口完全重叠,都计入此次数中。

minimumRestMinutes

integer

一轮班结束后,员工在被分配到另一轮班次之前必须休息的最短分钟数。此约束条件适用于 [startDateTimeendDateTime] 中完全包含的每一对偏移。

优先级

对员工日程表或保险范围要求的任何限制条件的优先级。包括 SchedulingConstraintResourceConstraintShiftRequestCoverageRequirement。由于可能存在相互冲突的约束条件,因此并不总是能满足所有约束条件。因此,每种约束条件类型都有一个优先级(由用户指定或默认),告知求解器给定完整时间表的所有约束的相对重要性。

枚举
PRIORITY_UNSPECIFIED 未知优先级。
PRIORITY_LOW 最低优先级。具有此优先级的限制条件比其他限制条件重要。如果找不到可行的解决方案,该团队会第一个被视为违规。
PRIORITY_MEDIUM 优先级为“中”。具有此优先级的约束条件比优先级为 PRIORITY_LOW 的约束条件更重要,但优先级为 PRIORITY_HIGH 的约束条件不太重要。如果在优先级为 PRIORITY_LOW 放宽所有约束条件后找不到可行的解决方案,则优先级为 PRIORITY_MEDIUM 的约束条件接下来会认为违规。
PRIORITY_HIGH 最高优先级。具有此优先级的限制是最重要的限制。如果在放宽优先级较低的限制条件后仍无法找到可行的解决方案,则此类审核将是最后一项违规内容。
PRIORITY_MANDATORY 表示求解器不能违反的优先级的优先级。如果求解器返回 SolutionStatus.INFEASIBLE,可能是因为 PRIORITY_MANDATORY 约束条件过多。

ResourceConstraint

一种一般限制条件,用于限制员工所使用的特定“资源”的数量。这是更具体的 SchedulingConstraint 的抽象版本,对用户来说更灵活。许多无法在 SchedulingConstraint.type 中指定的时间安排限制条件都可以使用此消息指定。

JSON 表示法
{
  "priority": enum (Priority),
  "resourceUsages": {
    string: number,
    ...
  },
  "minimumResourceUsage": number,
  "maximumResourceUsage": number
}
字段
priority

enum (Priority)

此资源限制条件的优先级。所有资源限制条件的默认优先级均为 PRIORITY_MEDIUM

resourceUsages

map (key: string, value: number)

轮班使用的资源量。例如,如果此限制条件适用于员工在特定一周内的最短和最长工作时数,则此映射将包含当周轮班和每次班次的时长(以小时为单位)。

包含一系列 "key": value 对的对象。示例:{ "name": "wrench", "mass": "1.3kg", "count": "3" }

minimumResourceUsage

number

要满足资源限制条件的最低资源用量。

maximumResourceUsage

number

要满足资源限制条件的最大资源用量。

ShiftRequest

员工提出的分配或不分配到特定班次的请求。

JSON 表示法
{
  "priority": enum (Priority),
  "shiftIds": [
    string
  ],
  "type": enum (WorkStatus)
}
字段
priority

enum (Priority)

此时间安排请求的优先级。所有时间安排请求的默认优先级均为 PRIORITY_LOW

shiftIds[]

string

时间安排请求的轮班 ID。

type

enum (WorkStatus)

请求类型,例如是否将该请求分配给该轮班。

WorkStatus

员工是否在工作。

枚举
WORK_STATUS_UNSPECIFIED 工作状态未知。
STATUS_WORK 代表在职员工的状态。
STATUS_NOT_WORK 代表非职员工的状态。

HourlyContract

指定基本小时费率、差价和加班系数,以确定员工的薪酬。请注意,不同地方的法规对加班薪酬的计算方式可能有所不同。求解器可以估算加班时间的薪酬,以尽可能降低总费用的替代价值或达到预算要求(请参阅 BudgetRequirement)。它不用作计算工资的工具。

JSON 表示法
{
  "baseHourlyRate": number,
  "hourlyRateShiftDifferentials": {
    string: number,
    ...
  },
  "overtimePeriods": [
    {
      object (OvertimePeriod)
    }
  ]
}
字段
baseHourlyRate

number

非加班时间的工资。如果员工适用多个费率,则会根据此基本小时费率应用差价。此外,如果存在多种费率,则基本每小时费率应为这些费率中的最小值。

hourlyRateShiftDifferentials

map (key: string, value: number)

每小时费率差额,在 baseHourlyRate的基础上支付。例如,如果基本每小时费率为 $30/小时,“shift_1”的费率为 $40/小时,“shift_2”的费率为 $45/小时,那么 proto 表示法为:baseHourlyRate: 30 hourlyRateShiftDifferentials {key: "shift_1" value: 10} hourlyRateShiftDifferentials {key: "shift_2" value: 15}

包含一系列 "key": value 对的对象。示例:{ "name": "wrench", "mass": "1.3kg", "count": "3" }

overtimePeriods[]

object (OvertimePeriod)

需要计算加时时间的所有时间段的列表。这些时间段不能重叠。

OvertimePeriod

一个有周期、定期重复的固定期限(通常为 168 小时或连续 7 个 24 小时的时间段),用于确定加班工资的金额。每个时间段都有一个加时系数(例如,1.5) 相对于baseHourlyRate,以及被视为常规(非加班)工作时间的小时数限制。与 startDateTime(含)和 endDateTime(不含)时间范围重叠的任何班次都会计入该时间段内的工作小时数。如果重叠部分是重叠的,则系统只会计算重叠的小时数。

JSON 表示法
{
  "overtimeMultiplier": number,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "maximumRegularHours": number
}
字段
overtimeMultiplier

number

用于计算加班每小时比率的乘数(必须大于或等于 1.0)。每小时加班比率通常计算方式为 baseHourlyRate * overtimeMultiplier。如果通过 hourlyRateShiftDifferentials 给出了多个速率,求解器会使用一段时间内适用的速率的简单平均值来估算该时间内的每小时速率。注意:不同地方的法规对加班薪酬的计算方式可能有所不同。求解器可以估算加班薪酬,以最大限度降低总费用或达到预算要求,但它并不是用于计算工资的工具。

startDateTime

object (DateTime)

加时赛的开始时间。如果这次班次与此次班次重叠,则此次班次调整时间的小时数将从 startDateTime开始计算。

endDateTime

object (DateTime)

加时赛的结束时间。如果这次班次与此次班次重叠,则此次班次班次最多会计入 endDateTime 次。

maximumRegularHours

number

按常规(非加班)费率支付的工作时间上限。此数量必须为正数。

Shift

轮班指定了员工可以工作的固定时间范围。

JSON 表示法
{
  "id": string,
  "locationId": string,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "breakRules": [
    {
      object (BreakRule)
    }
  ]
}
字段
id

string

为此班次分配的唯一 ID。

locationId

string

进行此班次调整的地理位置 ID。此字段可以为空。

startDateTime

object (DateTime)

班次的开始时间(含此时间)。

endDateTime

object (DateTime)

轮班的结束时间(不含班次)。目前,该求解器仅支持时长少于 24 小时的偏移。

breakRules[]

object (BreakRule)

在轮班期间出现的换行规则列表。执行这种轮班的员工会按照break_rule安排一次休息时间,在此期间,员工无法满足其履行的角色的需求。每个 BreakRule 的时间范围必须完全包含在此偏移的时间范围内。

BreakRule

一条规则,用于确定何时可以在轮班和轮班中开始广告插播。所有被视为可能的广告插播时间点的列表是以 ruleIncrementMinutes 为增量确定的。例如,如果广告插播规则建模为从 10:00 到 11:00 之间开始的 30 分钟插播时间点,且规则增量为 20 分钟,则系统考虑的插播时间点列表为:[10:00, 10:30]、[10:20, 10:50]、[10:10, 0.1]、11

JSON 表示法
{
  "earliestStartTime": {
    object (DateTime)
  },
  "latestStartTime": {
    object (DateTime)
  },
  "durationMinutes": integer,
  "ruleIncrementMinutes": integer
}
字段
earliestStartTime

object (DateTime)

广告插播的最早开始时间(含此时间)。只能设置 hoursminutes

latestStartTime

object (DateTime)

广告插播时间点的最晚开始时间(含此时间)。只能设置 hoursminutes

durationMinutes

integer

广告插播时长(分钟)。

ruleIncrementMinutes

integer

[可选] 此广告插播规则可考虑的所有广告插播时间点的时间增量(以分钟为单位)。如果未设置,则默认为 durationMinutes

CoverageRequirement

覆盖范围要求规定了在特定的时间范围内和/或地点在特定地点,担任一组角色和/或技能所需的员工人数。特定位置的日期时间间隔不能重叠。或者,也可以提供轮班 ID 列表,而不是时段和位置。只有可以分配给特定角色(或具备特定技能)的员工才能满足此要求。

对于给定的职位和/或技能,如果相应时间范围内每个时刻(或shiftIds的每次班次)都至少有 targetEmployeeCount 名员工在工作,则满足覆盖率要求。相反,如果在时间范围内的任何时间点(或shiftIds的任何班次)在该时间范围内工作的员工数少于 targetEmployeeCount,则不符合覆盖率要求。比 targetEmployeeCount 中的在职员工数多出仍然符合要求,但求解器可以最大限度地减少员工过多。

JSON 表示法
{
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "locationId": string,
  "shiftIds": [
    string
  ],
  "roleRequirements": [
    {
      object (RoleRequirement)
    }
  ],
  "skillRequirements": [
    {
      object (SkillRequirement)
    }
  ]
}
字段
startDateTime

object (DateTime)

覆盖率要求的开始时间(含此时间)。如果设置了此字段,则 shiftIds 必须为空。

endDateTime

object (DateTime)

覆盖率要求的结束时间(不含边界值)。如果设置了此字段,则 shiftIds 必须为空。

locationId

string

员工工作地点。“shiftIds”不为空,此字段必须为空。

shiftIds[]

string

如果已设置,角色和技能要求会分别应用于此列表中的每个轮班 ID。如果 shiftId 不为空,则 startDateTimeendDateTimelocationId 必须为空。

roleRequirements[]

object (RoleRequirement)

在时间范围内要分配给指定角色的所需员工人数。最多只能为每个角色 ID 指定一个 role_requirement。每项要求的默认优先级均为 PRIORITY_MANDATORY。如果在该时间范围内任何时间点为指定角色分配的员工少于 targetEmployeeCount 人,则违反这些限制条件。

skillRequirements[]

object (SkillRequirement)

在相应时间范围内分配到轮班的必需员工人数。每个技能 ID 最多只能提供一个 skill_requirement。每项要求的默认优先级均为 PRIORITY_LOW。如果在这段时间内拥有指定技能的员工数少于 targetEmployeeCount,则违反这些约束条件。

RoleRequirement

在时间范围内要分配给指定角色的所需员工人数。

JSON 表示法
{
  "roleId": string,
  "targetEmployeeCount": integer,
  "priority": enum (Priority)
}
字段
roleId

string

要求的角色 ID。

targetEmployeeCount

integer

在时间范围内分配给该角色的预期员工数量。

priority

enum (Priority)

此要求限制条件的优先级。所有资源限制条件的默认优先级均为 PRIORITY_MANDATORY

SkillRequirement

在指定时间范围内工作并具备指定技能的必要员工人数。

JSON 表示法
{
  "skillId": string,
  "targetEmployeeCount": integer,
  "priority": enum (Priority)
}
字段
skillId

string

要求的技能 ID。

targetEmployeeCount

integer

符合指定技能的在一定时间范围内工作的理想员工数。

priority

enum (Priority)

此要求限制条件的优先级。所有资源限制条件的默认优先级均为 PRIORITY_LOW

BudgetRequirement

给定时间间隔内的预算要求。

JSON 表示法
{
  "totalBudget": number,
  "startDateTime": {
    object (DateTime)
  },
  "endDateTime": {
    object (DateTime)
  },
  "priority": enum (Priority)
}
字段
totalBudget

number

指定时间间隔内的总预算。如果优先级为 PRIORITY_MANDATORY,则必须提供总预算。

如果未设置 totalBudget,则系统会根据指定的 priority 最大限度地降低时间表的总费用。例如,如果预算的 priorityPRIORITY_MEDIUM,则求解器会在减少任何优先级为 PRIORITY_LOW 的限制条件违规之前降低费用。

startDateTime

object (DateTime)

此预算适用的开始时间。如果未指定开始时间,则系统会将其设置为所有指定班次的最早开始时间。

endDateTime

object (DateTime)

此预算应用的结束时间。如果未指定结束时间,则系统会将其设置为所有指定班次的最晚结束时间。

priority

enum (Priority)

在指定时间范围内满足预算要求的优先级。默认优先级为 PRIORITY_LOW。如果优先级设置为 PRIORITY_MANDATORY,则必须设置 totalBudget

请注意,如果此优先级高于其他限制条件优先级,并且 totalBudget 很紧,则生成的时间表可能会严重违反员工限制或覆盖范围要求。

ShiftAssignment

一名员工负责转换角色。

JSON 表示法
{
  "employeeId": string,
  "shiftId": string,
  "roleId": string,
  "breaks": [
    {
      object (Break)
    }
  ]
}
字段
employeeId

string

要分配的员工 ID。

shiftId

string

分配给员工的轮班 ID。

roleId

string

分配给员工的角色 ID。

breaks[]

object (Break)

此轮班分配任务的插播时间点列表。

休息时间

员工在轮班期间打断其工作的时间段。

JSON 表示法
{
  "startDateTime": {
    object (DateTime)
  },
  "durationMinutes": integer
}
字段
startDateTime

object (DateTime)

广告插播开始时间。

durationMinutes

integer

广告插播时长(分钟)。

SolutionStatus

求解器响应中提供的解(即时间表)状态。

枚举
SOLUTION_STATUS_UNSPECIFIED 未指定的响应状态。
FEASIBLE 返回的时间表可行,但可能不是最佳选择。
OPTIMAL 返回的时间表是最佳的。
INFEASIBLE 对于给定的约束条件,不存在可行的时间表。如果无法满足优先级为 PRIORITY_MANDATORY 的限制条件的任何子集,求解器可能会返回此值。
NOT_SOLVED 未找到任何时间表。
NOT_SOLVED_DEADLINE_EXCEEDED 在指定时间限制内找不到时间表。