通过为员工分配班次,让员工的班次符合要求,解决了给定 SolveShiftSchedulingRequest
的固定轮班调度问题最大限度提高时间安排偏好设置,并最大限度地减少时间安排限制违规。
HTTP 请求
POST https://optimization.googleapis.com/v1/scheduling:solveShiftScheduling
网址采用 gRPC 转码语法。
请求正文
请求正文中包含结构如下的数据:
JSON 表示法 |
---|
{ "requestId": string, "solveParameters": { object ( |
字段 | |
---|---|
requestId |
问题或请求 ID。 |
solveParameters |
用于控制问题求解的参数。 |
employees[] |
安排所有有空的员工。 |
shifts[] |
形成时间表。 |
coverageRequirements[] |
整个规划范围的覆盖范围要求。用于指定在特定时间范围内或一系列轮班 ID 内必须担任每种角色或拥有某项技能的员工人数。所有覆盖范围要求都必须使用时间范围或班次 ID 列表来指定(但不能同时指定两者)。范围要求的时间范围(如果已指定)不能与每个指定地理位置重叠。对于角色要求,每个限制条件的默认优先级为 |
roleIds[] |
员工中所有可能的角色的列表。每位员工必须至少拥有一个可分配其轮班的角色。角色是指轮班期间的具体工作分配(即注册护士、执行厨师、服务员等)。如果为某个员工分配了某个轮班,他们也会分配到一个特定的角色。 |
skillIds[] |
员工可能具备的所有技能的列表。技能是指员工可能拥有的与具体可分配职位无关的任何额外资格(例如认证、所用语言等)。此列表可以为空。某名员工在接受轮班时,必须具备该轮班所需的全部技能。 |
locationIds[] |
包含时间表中一组班次的所有可能位置的列表。此列表可以为空。指定不同的位置会很有用,例如当护士经理想为医院的不同部门安排多位护士,或者酒店经理想为员工安排多个酒店的员工时。 |
budgetRequirements[] |
时间安排问题的预算规范。每项要求的默认优先级均为 |
assignmentsHint[] |
转换分配,用作调度问题的暂定解决方案(即解决方案提示)。如果分配与不可分配的偏移或调度请求冲突,则分配提示会被忽略。 |
响应正文
对员工时间安排 API 的响应。对于每个响应,如果返回的 solutionStatus
为 NOT_SOLVED_DEADLINE_EXCEEDED
或 INFEASIBLE
,则 shiftAssignments
将为空。如果返回的 solutionStatus
为 OPTIMAL
或 FEASIBLE
,则会在 shiftAssignments
中返回有效的偏移分配。对于有效的轮班分配,应具备以下属性:
- 每个员工 ID 都包含在请求中指定的员工集中。
- 分配给员工的每个角色 ID 都包含在给定员工的角色 ID 集中。
- 每个班次 ID 都包含在请求中指定的班次集合中。
- 对于指定员工,每个班次 ID 都不是其中一个不可分配的班次 ID。
- 某位员工绝不会分配到两个重叠的班次。
- 对于指定的时间安排,优先级为
PRIORITY_MANDATORY
的所有限制条件或请求均未违反。
如果成功,响应正文将包含结构如下的数据:
JSON 表示法 |
---|
{ "requestId": string, "solutionStatus": enum ( |
字段 | |
---|---|
requestId |
与此响应关联的请求的 ID。 |
solutionStatus |
所返回解决方案的状态。如果解决方案不可行或不可优化,则此 proto 中的其他字段可能为空。如果状态为 NOT_SOLVED_DEADLINE_EXCEEDED,则表示在未找到可行解决方案或无法确定是否存在可行解决方案的情况下,已达到时间限制。如果优先级 MANDATORY 的限制条件无法全部满足,则请求可能是不可行的。 |
shiftAssignments[] |
所有分配的列表。每个 |
statusMessage |
如果 |
SolveParameters
用于控制轮班调度问题的一次解决的参数。
JSON 表示法 |
---|
{ "timeLimit": string } |
字段 | |
---|---|
timeLimit |
求解器应该在解题上花费的时间上限。如果未设置,则默认为 1 分钟。 该值不是硬性限制,并且不考虑通信开销。解决此问题的预期延迟时间可能会略微超过此值。 该时长以秒为单位,最多包含九个小数位,以“ |
员工
要安排的员工中的员工。
JSON 表示法 |
---|
{ "id": string, "roleIds": [ string ], "skillIds": [ string ], "shiftPreferences": [ { object ( |
字段 | |
---|---|
id |
分配给此员工的唯一 ID。 |
roleIds[] |
此员工可以执行的角色 ID。必须至少指定一个角色。如果为某个员工分配了某个轮班,该员工也会分配到此列表中的一个角色。在时间安排的时间范围内,员工可能会被分配不同的角色。 |
skillIds[] |
此员工拥有的技能 ID。此列表可以为空。为某个员工分配轮班时,该员工会使用此处所列的任意技能来满足在整个轮班期间的技能要求。 |
shiftPreferences[] |
调整此员工的偏好设置。此处指定的班次表示员工希望在预约时限内分配的班次。 |
schedulingConstraints[] |
此员工的时间安排限制列表。其中每个限制条件的默认优先级均为 |
resourceConstraints[] |
可在此处向 |
shiftRequests[] |
员工的排班请求列表。该请求可以是为员工分配或不分配给特定班次的请求。员工的所有固定调度分配都可以用优先级为 |
hourlyContract |
规定员工的常规每小时费率和加班费率的合同。 |
ShiftPreference
特定班次 ID 的数字偏好设置。
JSON 表示法 |
---|
{ "shiftId": string, "preference": integer } |
字段 | |
---|---|
shiftId |
已指定偏好设置的 Shift ID。 |
preference |
偏好值越大,表示变化更可取。 |
SchedulingConstraint
特定员工的特定调度限制条件。指定的限制条件仅在给定的时间间隔 [startDateTime,
endDateTime)
内应用。
JSON 表示法 |
---|
{ "priority": enum ( |
字段 | |
---|---|
priority |
此调度限制条件的优先级。所有调度限制条件的默认优先级为 |
startDateTime |
应用此调度限制条件的开始时间(含此时间)。 |
endDateTime |
应用此调度限制条件的结束时间(不含)。 |
联合字段 type 。要指定的限制条件的类型。每个限制条件仅在上面指定的时间范围内应用。type 只能是下列其中一项: |
|
minimumMinutes |
员工可以工作的最短分钟数。如果为员工分配的班次与时间窗口完全或部分重叠,则此班次与时间窗口重叠的分钟数会计入此计数中。 |
maximumMinutes |
员工在相应时间范围内可以工作的分钟数上限。如果为员工分配的班次与时间窗口完全或部分重叠,则此班次与时间窗口重叠的分钟数会计入此计数中。 |
minimumConsecutiveWorkDays |
员工可以工作的最短连续天数。如果某位员工被分配到的排班从当天开始,则会在特定的某一天工作。该计数包含分配给该员工的任何从该时间窗口开始的班次。 |
maximumConsecutiveWorkDays |
员工可以工作的最长连续天数。如果某位员工被分配到的排班从当天开始,则会在特定的某一天工作。该计数包含分配给该员工的任何从该时间窗口开始的班次。 |
minimumShiftCount |
员工可以轮班的最少班次。分配给该员工的任何班次(与时间范围完全重叠)都包含在此计数中。 |
maximumShiftCount |
员工可以轮班的次数上限。分配给该员工的任何班次(与时间范围完全重叠)都包含在此计数中。 |
minimumRestMinutes |
一个班次结束后,员工必须休息的最短分钟数,才能被分配到另一个班次。此限制条件适用于完全包含在 [ |
优先级
针对员工时间表或覆盖范围要求的任何限制条件的优先级。其中包括 SchedulingConstraint
、ResourceConstraint
、ShiftRequest
和 CoverageRequirement
。由于可能存在有冲突的约束,因此并不总是能够满足每个约束条件。因此,每类约束条件都有一个优先级(由用户指定或默认优先级),用于告知求解器给定完整时间表的所有约束条件的相对重要性。
枚举 | |
---|---|
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 |
轮班使用的资源量。例如,如果此约束条件应用于某员工在特定周的最短和最长工作时间,则此映射将包含该周的班次以及每次班次的时长(以小时为单位)。 包含一系列 |
minimumResourceUsage |
要满足资源限制条件的最低资源使用量。 |
maximumResourceUsage |
要满足资源限制条件的最大资源使用量。 |
ShiftRequest
员工希望被分配或不会被分配到特定班次的请求。
JSON 表示法 |
---|
{ "priority": enum ( |
字段 | |
---|---|
priority |
此安排请求的优先级。所有调度请求的默认优先级为 |
shiftIds[] |
时间安排请求的班次 ID。 |
type |
请求类型,例如是否将请求分配给一组轮班。 |
WorkStatus
员工是否在工作。
枚举 | |
---|---|
WORK_STATUS_UNSPECIFIED |
未知工作状态。 |
STATUS_WORK |
代表在职员工的身份。 |
STATUS_NOT_WORK |
代表非在职员工的身份。 |
HourlyContract
指定基本时薪、差价和加班乘数,以确定员工的薪酬。请注意,不同地区的法规对加班薪酬的计算方式可能有所不同。求解器会估算加班费,以便尽可能降低总费用或满足预算要求(请参阅 BudgetRequirement
)。它不用作计算工资的工具。
JSON 表示法 |
---|
{
"baseHourlyRate": number,
"hourlyRateShiftDifferentials": {
string: number,
...
},
"overtimePeriods": [
{
object ( |
字段 | |
---|---|
baseHourlyRate |
非加班时间的薪酬。如果员工适用多个费率,则会根据此基本小时费率应用差价。此外,如果有多种费率,则基本每小时费率应为这些费率的最小值。 |
hourlyRateShiftDifferentials |
在 包含一系列 |
overtimePeriods[] |
必须计算加时值的所有时间段的列表。这些时段不得重叠。 |
OvertimePeriod
固定和有规律的周期(通常为 168 小时或连续的 24 小时时间段),用于确定加班工资金额。每个时间段都有一个加时乘数(例如,1.5)(相对于baseHourlyRate
)以及对被视为常规(非加班)工作的小时数限制。与 startDateTime
(含)和 endDateTime
(不含)时间范围重叠的任何班次都将计入此时间段内的工作时间总数。如果重叠部分是部分重叠,则仅统计重叠时段。
JSON 表示法 |
---|
{ "overtimeMultiplier": number, "startDateTime": { object ( |
字段 | |
---|---|
overtimeMultiplier |
用于计算加班时间每小时费率的调节系数(必须大于或等于 1.0)。加时型每小时费率通常按 |
startDateTime |
加时时间段内的开始时间。如果此时间偏移时差,则从 |
endDateTime |
加时时间段内的结束时间。如果此时间调整的时间与时间重叠,则此类偏移的小时数最多计为 |
maximumRegularHours |
按常规(非加班)费率支付的最长工作时间。此数量必须为正数。 |
Shift
轮班会指定员工可以工作的固定时间段。
JSON 表示法 |
---|
{ "id": string, "locationId": string, "startDateTime": { object ( |
字段 | |
---|---|
id |
分配给此班次的唯一 ID。 |
locationId |
执行此偏移的地理位置 ID。此字段可以为空。 |
startDateTime |
班次的开始时间(含此时间)。 |
endDateTime |
班次的结束时间(不含)。目前,该求解器仅支持时长不超过 24 小时的移位。 |
breakRules[] |
转移期间发生的违反规则的列表。执行此轮班的员工每 |
BreakRule
用于确定在轮班期间可以开始休息的时间以及休息时长的规则。系统会以 ruleIncrementMinutes
为增量来确定考虑的所有可能的插播时间点。例如,如果一条广告插播规则模拟一个从 10:00 到 11:00 之间开始的 30 分钟的广告插播时间点,并且规则递增单位为 20 分钟,则考虑的广告插播时间点列表包括:[10:00, 10:30]、[10:20, 10:50]、[10:1.0.0.1.40,
JSON 表示法 |
---|
{ "earliestStartTime": { object ( |
字段 | |
---|---|
earliestStartTime |
广告插播的最早开始时间(含此时间)。只能设置 |
latestStartTime |
广告插播的最晚开始时间(含此时间)。只能设置 |
durationMinutes |
广告插播时长(以分钟为单位)。 |
ruleIncrementMinutes |
[可选] 可纳入此广告插播规则中的所有广告插播时间点的时间增量(以分钟为单位)。如果未设置,则默认为 |
CoverageRequirement
保险范围要求规定了在特定时间段和指定地点担任一组角色和/或技能所需的员工人数。特定位置的日期时间间隔不能重叠。或者,您也可以提供班次 ID 列表,而不是时间范围和地点。只有可分配到特定角色(或拥有特定技能)的员工才能满足此要求。
对于给定的角色和/或技能,当时间范围内每个时刻(或shiftIds
的每班班次)至少有 targetEmployeeCount
名员工在工作,即满足保险范围要求。相反,如果在某个时间段的任何时间点(或shiftIds
的任何班次),在这段时间内工作的员工人数少于 targetEmployeeCount
,则不符合保险范围要求。即使员工人数多于 targetEmployeeCount
,仍满足要求,但求解器可以最大限度地减少人手过多。
JSON 表示法 |
---|
{ "startDateTime": { object ( |
字段 | |
---|---|
startDateTime |
覆盖范围要求的开始时间(含此时间)。如果设置, |
endDateTime |
保修要求的结束时间(不含)。如果设置, |
locationId |
需要员工的工作地点。“ |
shiftIds[] |
如果已设置,角色和技能要求会单独应用于此列表中的每个班次 ID。如果 shiftId 为非空,则 |
roleRequirements[] |
在时间范围内分配给指定角色的员工人数要求。对于每个角色 ID,最多只能提供一个 |
skillRequirements[] |
在相应时间范围内轮班的具有指定技能的员工人数要求。每个技能 ID 最多只能提供一个 |
RoleRequirement
在时间范围内分配给指定角色的员工人数要求。
JSON 表示法 |
---|
{
"roleId": string,
"targetEmployeeCount": integer,
"priority": enum ( |
字段 | |
---|---|
roleId |
要求的角色 ID。 |
targetEmployeeCount |
在时间范围内分配给相应角色的员工人数。 |
priority |
此要求限制条件的优先级。所有资源限制条件的默认优先级为 |
SkillRequirement
在这段时间内工作且具备指定技能的员工人数要求。
JSON 表示法 |
---|
{
"skillId": string,
"targetEmployeeCount": integer,
"priority": enum ( |
字段 | |
---|---|
skillId |
要求的技能 ID。 |
targetEmployeeCount |
在指定时间范围内工作且具有指定技能的期望员工人数。 |
priority |
此要求限制条件的优先级。所有资源限制条件的默认优先级为 |
BudgetRequirement
给定时间间隔内的预算要求。
JSON 表示法 |
---|
{ "totalBudget": number, "startDateTime": { object ( |
字段 | |
---|---|
totalBudget |
指定时间间隔内的总预算。如果优先级为 如果未设置 |
startDateTime |
此预算适用的开始时间。如果未指定开始时间,则将其设置为所有给定班次的最早开始时间。 |
endDateTime |
此预算适用的结束时间。如果未指定结束时间,则将其设置为所有给定班次的最晚结束时间。 |
priority |
在指定时间范围内满足预算要求的优先级。默认优先级为 请注意,如果此优先级高于其他限制条件优先级,并且 |
ShiftAssignment
负责轮班的员工。
JSON 表示法 |
---|
{
"employeeId": string,
"shiftId": string,
"roleId": string,
"breaks": [
{
object ( |
字段 | |
---|---|
employeeId |
正在分配的员工 ID。 |
shiftId |
分配给员工的排班 ID。 |
roleId |
轮班为员工分配的角色 ID。 |
breaks[] |
此轮班分配的休息列表。 |
休息时间
员工在换班期间打断工作的时间段。
JSON 表示法 |
---|
{
"startDateTime": {
object ( |
字段 | |
---|---|
startDateTime |
休息的开始时间。 |
durationMinutes |
广告插播时长(以分钟为单位)。 |
SolutionStatus
求解器的响应中提供的求解(即时间表)状态。
枚举 | |
---|---|
SOLUTION_STATUS_UNSPECIFIED |
未指定的响应状态。 |
FEASIBLE |
返回的时间表是可行的,但可能不是最佳。 |
OPTIMAL |
返回的时间表是最佳的。 |
INFEASIBLE |
对于给定的约束条件,不存在可行的时间表。如果无法满足优先级为 PRIORITY_MANDATORY 的约束条件的任何子集,求解器可能会返回此值。 |
NOT_SOLVED |
未找到任何时间表。 |
NOT_SOLVED_DEADLINE_EXCEEDED |
在指定的时限内未找到任何时间表。 |