Classify Department Employees

Classify Department Employees, another challenge from dmcommunity.org, has long been an impossible challenge for our cDMN solver. While cDMN is 100% capable of modeling the problem (we already modeled it in 2020), the solver could not handle actually solving the challenge for two reasons: the occurence of large numbers, and the need for division. However, since cDMN version 2.0.0 we have a new internal solver, IDP-Z3, and we can now effectively tackle this challenge!

Classify Department Employees Challenge

A human resource office has information about all employees in every department including: salary, marital status, age, etc. Help the office to create a decision model that for each department calculates minimal, maximal, and average salaries along with a number of high-paid employees using rules like “Salary > 85000”.

Person Marital Status Gender Age Salary
Robinson Married Female 25 20000
Warner Married Male 45 150000
Stevens Single Male 24 35000

We start by creating a glossary for our personnel and their attributes. For each of our string-based attributes, we will introduce a type. For the numerical attiributes, we do not need to set a range of values and instead use the generic type Real.

Note

Before cDMN version 2.0.0, using supertypes int and real directly was not allowed. Note that they still cannot be used everywhere: they can only be used as return arguments of functions or constants.

Type
Name Type Values
Person String Robinson, Warner, Stevens, ...
Marital_Status String Married, Single
Gender String Male, Female

Next, we need a way to represent which attribute values belong to which people. This is a quite straighforward example for functions: every person has exactly one value for each parameter.

Function
Name Type
status of Person Marital_Status
gender of Person Gender
age of Person Real
salary of Person Real
Number of Item Nat

The aim of the challenge is calculate values such as the minimal value, maximum value, … based on our set of employees. To get the result of these calculations, we use constants to represent them.

Constant
Name Type
Minimal Salary Real
Maximal Salary Real
Average Salary Real
Total Salary Real

Finally, we need a way to keep track of which people are rich. For this, a simple relation will work best.

Relation
Name
Person is rich

Now that our glossary is complete, we can start figuring out how to best express our knowledge. Let’s start with the minimal, maximal and total salary. Thanks to cDMN’s aggregates, this is very straightforward: the C<, C> and C+ hit policies respectively calculate the minimum, maximum and total of all rules that fire. For example, for the minimum, this looks as follows:

Minimun
C< Person Minimal Salary
1 - salary of Person

In words, this table is quite simple: “Find the minimal salary of all persons” (or: considering each person, find the minimum salary). For the two other values, the tables are virtually the same.

Maximum
C> Person Maximal Salary
1 - salary of Person Yes

Total
C# Person Total Salary
1 - salary of Person

We can use the total salary to calculate the average salary. Again, this is fairly straightforward: just divide the total salary by the total number of people.

Number of domain elements of a type

In this example, we need to know the number of elements that are in the type Person. cDMN has an easy way of representing this, using the #Type operator. In this example, #Person equals 12 and #Marital_Status equals 2.

Avg
U Average Salary
1 Total Salary/#Person

The final thing that we need to do, is figure out which people are rich. According to the challenge, everyone with a salary over 85000 is considered rich. So, we express in a table that “Each person with a salary over 85000 is rich”.

Rich Employees
U Person salary of Person Person is rich
1 - > 85000 > 85000

Our model is now complete, and we can run it using the cDMN solver. This results in the following output:

Model 1
==========
status_of_Person := {Robinson->Married, Warner->Married, Stevens->Single, White->Married, Smith->Single, Green->Married, Brown->Married, Klaus->Married, Houston->Single, Long->Married, Short->Single, Doe->Single}.
gender_of_Person := {Robinson->Female, Warner->Male, Stevens->Male, White->Female, Smith->Male, Green->Female, Brown->Male, Klaus->Male, Houston->Female, Long->Male, Short->Male, Doe->Female}.
age_of_Person := {Robinson->25, Warner->45, Stevens->24, White->32, Smith->46, Green->28, Brown->32, Klaus->54, Houston->47, Long->29, Short->22, Doe->21}.
salary_of_Person := {Robinson->20000, Warner->150000, Stevens->35000, White->75000, Smith->110000, Green->40000, Brown->65000, Klaus->85000, Houston->35000, Long->40000, Short->20000, Doe->21000}.
Minimal_Salary := 20000.
Maximal_Salary := 150000.
Average_Salary := 58000.
Total_Salary := 696000.
Person_is_Rich := {Warner, Smith}.

Elapsed Time:
0.899