通过将员工分配至轮班,使员工的时间安排偏好最大化,并最大限度地减少违反排班限制的情况,解决给定 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
中会返回有效的移位赋值。对于有效的 shift 分配,必须具备以下属性:
- 每个员工 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 小时或连续 7 个 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:10, 0.1]、11
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 |
在指定时间限制内找不到时间表。 |