Vacation Days Advanced
This example is an advanced version of a previous example, Vacation Days. The full specification can be found here: Vacation Days Advanced. In this challenge, we need to calculate vacation days for employees, based on their age and years of service and some more information. In total, there are seven rules:
Vacation Days
Every employee receives at least 22 vacation days.
Employees younger than 18 or at least 60 years, or employees with at least 30 years of service can receive extra 5 days.
Employees with at least 30 years of service and also employees of age 60 or more, can receive extra 3 days, on top of possible additional days already given.
If an employee has at least 15 but less than 30 years of service, extra 2 days can be given. These 2 days can also be provided for employees of age 45 or more.
A college student is eligible to 1 extra vacation day.
If an employee is a veteran, 2 extra days can be given.
The total number of vacation days cannot exceed 29.
The seventh rule of the specification is what makes this challenge so interesting. At first, it would seem intuitive to place a soft maximum on the vacation days: if an employee exceeds 29 days, give them 29 days. However, in Jacob Feldman’s OpenRules implementation he points out that this would mean we can simply subtract days from some types and only give partial number of eligible days. If we assume that this is not allowed, an employee would not want to make use of every type of vacation days for which they are eligible, but only the ones that get their total closest to 29. In this small example this does not matter too much, but in bigger systems with more mutually exclusive rules this could make a difference.
In this implementation, we will deal with two types of vacation rules: the ones for which an employee is eligible, and the ones that they ‘apply’, e.g. actually use. In other words, they will not have to use all vacation days for which they are eligible. We will try to pick the used days in such a way that a maximum number is achieved for every employee.
To fill out our glossary, we start by adding types for the string-based domains, i.e., the employees and the different rules. For the example, we create three dummy employees: Huey, Dewey and Louie.
Type | ||
---|---|---|
Name | Type | Values |
Employee | String | Huey, Dewey, Louie |
Rule | String | r2, r3, r4, r5, r6 |
Next, we create functions to map every employee to their age, service years and total vacation days.
Function | |
---|---|
Name | Type |
age of Employee | Int |
service years of Employee | Age |
vacation days of Employee | Int |
In order to express whether an employee is a veteran or student, we add 2 relations. We also add a relation which keeps track of the eligible rules, and the ‘applied’ rules.
Relation |
---|
Name |
Employee is Student |
Employee is Veteran |
Employee is eligible for Rule |
Employee applies Rule |
Now that our glossary is complete, we can start creating decision and constraint tables. We start by implementing a table for every rule, to express when an exmployee is eligible.
Define the eligibility for rule 2 | ||||
---|---|---|---|---|
A | Employee | age of Employee | service years of Employee | Employee is eligible for r2 |
1 | - | < 18 | - | Yes |
2 | - | ≥ 60 | - | Yes |
3 | - | [18, 60) | ≥ 30 | Yes |
Define the eligibility for rule 3 | ||||
---|---|---|---|---|
A | Employee | age of Employee | service years of Employee | Employee is eligible for r3 |
1 | - | - | ≥ 30 | Yes |
2 | - | < 60 | < 30 | Yes |
Define the eligibility for rule 4 | ||||
---|---|---|---|---|
A | Employee | age of Employee | service years of Employee | Employee is eligible for r4 |
1 | - | - | [15, 30) | Yes |
2 | - | ≥ 45 | - | Yes |
Define the eligibility for rule 5 | |||
---|---|---|---|
A | Employee | Employee is Student | Employee is eligible for r5 |
1 | - | Yes | Yes |
Define the eligibility for rule 6 | |||
---|---|---|---|
A | Employee | Employee is Veteran | Employee is eligible for r6 |
1 | - | Yes | Yes |
Now that we can decide which employee is eligible for what rules, we need a way to calculate the number of days.
We do this by creating a C+
table, in which we sum the number of days per rule based on which rules are applied.
Calculate vacation days based on which rules are applied. | |||||||
---|---|---|---|---|---|---|---|
C+ | Employee | Employee applies r2 | Employee applies r3 | Employee applies r4 | Employee applies r5 | Employee applies r6 | vacation days of Employee |
1 | - | - | - | - | - | - | 22 |
2 | - | Yes | - | - | - | - | 5 |
3 | - | - | - | - | - | - | 3 |
4 | - | No | - | Yes | - | - | 2 |
5 | - | - | - | - | Yes | - | 1 |
6 | - | - | - | - | - | Yes | 1 |
Just stating that rules can be applied is of course not enough. We need to make sure that only rules for which an employee is eligible can be applied. In order to do this, we create a constraint table. Note how it states that a rule can only be applied if the employee is eligible, but that it does not state the opposite. In other words, not every eligible rule needs to be applied.
Only apply rule if eligible. | ||||
---|---|---|---|---|
E* | Employee | Rule | Employee applies Rule | Employee is eligible for Rule |
1 | - | - | Yes | Yes |
Of course, we also need to add a constraint that no employee can have more than 29 vacation days.
Max days. | ||
---|---|---|
E* | Employee | vacation days of Employee |
1 | - | ≤ 29 |
There we have it! We are now able to calculate vacation days for employees. However, just this calculation alone does not do much yet. We need to be able to look for the solution in which the employees have a maximum number of vacation days. To do this, we sum all the vacation days of employees and maximize it. This is a bit unfortunate, but because we added quantification we have to maximize for all employees. If we did not use quantification, we could run the model once for every employee. In this case the employees do not affect each other, so solving the problem for all of them at the same time creates no implications.
Total days. | ||
---|---|---|
C+ | Employee | Total Days |
1 | - | vacation days of Employee |
Goal |
---|
Maximize Total Days |
To now check the amount of vacation days our employees get, we can insert a data table containing their information, and run the solver.
Employee Info | |||||
---|---|---|---|---|---|
D | Employee | age of Employee | service years of Employee | Employee is Veteran | Employee is Student |
1 | Huey | 17 | 1 | Yes | No |
2 | Dewey | 70 | 31 | No | Yes |
3 | Louie | 35 | 16 | No | No |
This gives us the following solution:
Model 1
==========
vacation_days_of_Employee := {Huey->31, Dewey->30, Louie->27, Donald->26}.
age_of_Employee := {Huey->17, Dewey->70, Louie->35, Donald->46}.
service_years_of_Employee := {Huey->1, Dewey->31, Louie->16, Donald->10}.
Employee_eligible_for_Rule := {(Huey,r2), (Huey,r3), (Huey,r5), (Dewey,r2), (Dewey,r3), (Dewey,r4), (Louie,r3), (Louie,r4), (Donald,r3), (Donald,r4), (Donald,r6)}.
Employee_is_Student := {Huey}.
Employee_is_Veteran := {Donald}.
Employee_applies_Rule := {(Huey,r2), (Huey,r3), (Huey,r5), (Dewey,r2), (Dewey,r3), (Louie,r3), (Louie,r4), (Donald,r3), (Donald,r6)}.
Elapsed Time:
0.955