Period Distribution Constraint
Define rules to improve the distribution of inconvenient periods among employees.
Explanation
Within the context of this constraint, a period is considered 'worked' for an employee if they work any shift during that period, and 'free' if they do not. The constraint allows you to set rules for how many periods an employee can work, how many they can work in succession, and how many free periods they must have surrounding a working period.
Often seen use cases are the distribution of weekends, holidays, or other inconvenient periods among employees.
Period Distribution Constraint in the request payload
id required | string (constraintId) The id of the constraint should be UNIQUE in the context of constraint type. |
weight | integer (constraintWeightPositive) [ 0 .. 100 ] Describes how much the constraint is taken into account when solving the schedule. The higher the value, the more solver will penalize the constraint violation. None of the weight values make it a hard constraint - even when weight is set to 100 it is not guaranteed that the constraint will be satisfied. The weight value is relative to other constraints. |
isStrict | boolean If true, the constraint must be strictly followed and the solver will never consider solutions that would violate the constraint. |
object (constraintFilters) Filters to determine the scope of the constraint. Used to decide which employees and which shifts the constraint should be applied to. Filters use logical OR filtering - an employee or shift is included as long as it is targeted by any of the filters. | |
object (constraintFairness) Describes how much fairness is taken into account for the constraint. | |
maxWorkedPeriods | integer >= 0 Defines the maximum amount of periods in which the employee can work in the planning horizon. |
maxConsecutiveWorkedPeriods | integer >= 1 Defines the maximum amount of consecutive periods in which the employee can work. |
minSurroundingFreePeriods | integer >= 0 Defines the minimum amount of non-worked periods surrounding a worked period. |
object (overlapRules) Specify when a shift should count as working a period. | |
object (periods) = 1 properties List of periods in the schedule. Periods can either be defined explicitly using custom definitions, or through a recurrent definition. A recurrent definition can be used to easily generate a list of similar periods (such as weeks, months, etc.). | |
employeeIds | Array of strings (constraintEmployeeIds) unique Deprecated DEPRECATED - Use filters instead. |
workTypeIds | Array of strings (constraintWorkTypeIds) unique Deprecated DEPRECATED - Use filters instead. |
label | string Deprecated DEPRECATED - Use periods instead. The label the constraint period applies to. |
maxCount | integer >= 0 Deprecated DEPRECATED - Use maxWorkedPeriods instead. Defines the maximum amount of periods in which the employee can work in the planning horizon. |
minSurroundingFreeLabels | integer >= 0 Deprecated Default: 0 DEPRECATED - Use minSurroundingFreePeriods instead. Defines the smallest number of free daygroups with labelthat employee should have before and after working on a labelled day group. 0 means that employee(s) can work on, for example, a weekend even when the previous and/or the next weekend is not free, if using labels for weekends. |
{- "id": "string",
- "weight": {
- "example_1": {
- "value": 0,
- "summary": "The constraint is not taken into account when solving the schedule as it has weight 0."
}, - "example_2": {
- "value": 100,
- "summary": "Solver will try its best to satisfy the constraint as it has weight 100."
}
}, - "isStrict": true,
- "filters": {
- "employeeIds": {
- "example_ints": {
- "value": [
- 1,
- 5,
- 3
], - "summary": "The constraint will be applied only to employees with id 1, 5 and 3."
}, - "example_all_employees": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined employees."
}, - "example_string": {
- "value": [
- "Lars Petersen",
- "123qwerty"
], - "summary": "The constraint will be applied to listed employees."
}
}, - "shiftIds": {
- "example_1": {
- "value": [
- "shift_1",
- "shift_2"
], - "summary": "The constraint will be applied only to shifts with id \"shift_1\" or \"shift_2\"."
}, - "example_2": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined shifts."
}
}, - "shiftTypeIds": {
- "example_ids": {
- "value": [
- "shift_type_1",
- "shift_type_2"
], - "summary": "The constraint will be applied only to shift types with id \"shift_type_1\" and \"shift_type_2\"."
}, - "example_all_shift_types": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined shift types."
}
}, - "workTypeIds": {
- "example_1": {
- "value": [
- 0,
- 3
], - "summary": "The constraint will be applied only to work type with id 0 and 3."
}, - "example_2": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined work types."
}
}
}, - "fairness": {
- "fairnessWeight": {
- "example_1": {
- "value": 0,
- "summary": "The fairness is not taken into account when solving the schedule."
}, - "example_2": {
- "value": 100,
- "summary": "Solver will try its best to make the constraint as fair as possible."
}
}, - "fteAdjustedFairness": false
}, - "maxWorkedPeriods": 0,
- "maxConsecutiveWorkedPeriods": 1,
- "minSurroundingFreePeriods": 0,
- "overlapRules": {
- "minOverlapHours": 1,
- "minOverlapPercentage": 1
}, - "periods": {
- "days": {
- "dates": [
- {
- "example_1": {
- "value": "2023-12-24",
- "summary": "The 24th of December 2023."
}
}
]
}
}, - "employeeIds": {
- "example_ints": {
- "value": [
- 1,
- 5,
- 3
], - "summary": "The constraint will be applied only to employees with id 1, 5 and 3."
}, - "example_all_employees": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined employees."
}, - "example_string": {
- "value": [
- "Lars Petersen",
- "123qwerty"
], - "summary": "The constraint will be applied to listed employees."
}
}, - "workTypeIds": {
- "example_1": {
- "value": [
- 0,
- 3
], - "summary": "The constraint will be applied only to work type with id 0 and 3."
}, - "example_2": {
- "value": [ ],
- "summary": "The constraint will be applied to all defined work types."
}
}, - "label": "string",
- "maxCount": 0,
- "minSurroundingFreeLabels": 0
}
Maximum worked periods
An easy use case is to limit how many worked periods an employee can have.
The constraint specified below makes it undesirable for employees to work more than 2 weekends. Notice that working a shift is only considered
as working a period if it overlaps for at least 6 hours with the period, as configured in the overlapRules
.
To work with labels
on periods, make sure you have set a definition for the period label in the configuration
part of the payload.
{
"id": "pd-max-weekends",
"weight": 50,
"maxWorkedPeriods": 2,
"overlapRules": {
"minOverlapHours": 6
}
"periods": {
"labels": ["WEEKENDS"]
}
}
Maximum consecutive worked periods
Alternitavely, the constraint can be used to limit how many undesirable periods an employee can work in succession.
The constraint specified below makes it strictly forbidden for an employee to work 3 holidays in a row. Notice that with the way periods are defined, working both days of Christmas still only counts as working one period. If the days of Christmas should count as working separate holidays, you would need to define them as separate periods.
{
"id": "pd-max-consecutive-holidays",
"isStrict": true,
"maxConsecutiveWorkedPeriods": 2,
"periods": {
"customDefinitions": [
// Christmas
{
"startDay": {
"date": "2024-12-25"
},
"endDay": {
"date": "2024-12-26"
}
},
// New Year
{
"startDay": {
"date": "2024-12-31"
},
"endDay": {
"date": "2024-12-31"
}
},
// ... more holiday periods
]
}
}
Minimum surrounding free periods
The constraint can also be used to enforce a minimum number of free periods surrounding a worked period.
Note that it is currently not supported to use the minSurroundingFreePeriods
property in combination with the maxConsecutiveWorkedPeriods
property.
The constraint specified below makes it strictly required for an employee to have at least 1 free weekend surrounding each worked weekend.
{
"id": "pd-min-surrounding-free-weekends",
"isStrict": true,
"minSurroundingFreePeriods": 1,
"periods": {
"labels": ["WEEKENDS"]
}
}