There are two interesting responses to the DMCommunity.org Feb-2018 Challenge provided by Mike Parish and Bob Moore. Mike effectively used Corticon to validate and fix incompleteness, redundancy, and ambiguity problems he found in the following, relatively simple decision table:
According to the challenge, this table was provided by a tax business analyst with no additional comments. Mike found the problems, “consulted” with the table’s author regarding uncovered combinations of different attributes, and came up with much smaller decision table. While I like Mike’s solution, my concern is that the resulting decision table is so much different to compare with the initial one. Usually business analysts have some serious reasons to organize their rules in a certain way: what if the new, “optimized” decision table is missing some business knowledge that its author had in his/her mind while creating the initial table? So, I tend to agree with Bob’s analysis that probably the initial table after all was not so bad. These considerations forced me to create an OpenRules-based implementation of this decision table.
As usual, I built a working decision model that we can analyse and execute. First of all, I decided to represent the above table as a regular single-hit decision table. I only made two intuitive changes similarly to those in Bob’s representation:
- Transposed the table, so its columns contain the names of decision variables and the rules are organized in the top-down order
- Instead of the boolean values Y/N, I moved the condition from names to the expressions placed directly into to the decision table cells.
Here is the resulting tax table called “DetermineNextYearDocuments”:
These changes were minimal and hopefully it is easy to recognize the initial table. I put the initial rule numbers in the first column and even did not delete the Rule 5 that is identical with the Rule 2 – what if the business analyst reserved this rule for something else she planed to introduce later on? The only important change is my additional rule at the end of the table, which will be executed when there are no matching rules – it will assign ‘?’ to the resulting variable “Next Year Documents” (the default rule). This table looks like a quite typical DMN first-hit decision table.
Secondary, I wanted to run the OpenRules built-in validation mechanism that uses a constraint solver to find conflicts inside decision models (usually not just inside one decision table but across multiple decision tables). To do this, I needed to run an OpenRules in the execution mode “Solve” that utilizes Rule Solver (to learn more you may look at http://ceur-ws.org/Vol-1620/paper2.pdf).
To make my table executable, I added the following glossary:
and ran the OpenRules validation process. As I already expected, it found no conflicts in this decision table, because it is always possible to find such values for all 8 decision variables which may produce at least one solution. However, when I asked our solver to find up to 100 solutions, it immediately generated me all 100 solutions, and it would generate 10,000 solutions as well if I ask. Obviously, this tax table is incomplete meaning it does not cover all possible combinations of the first 7 decision variables from the above glossary. Mike (after “talking” to a business tax expert) made his decision table complete, but Bob noticed that there is nothing wrong to leave the table “as is” as far as it produces the results expected by its author (a subject matter expert). I decided to do the same as in the real-world decision modeling applications it is rarely possible to cover ALL combinations of decision variables. Besides, I’ve already added a catch in the last rule anyway.
So, to complete the exercise, I just wanted to test the table. Here are my test data tables:
After executing this decision model, I received the expected results in the following default format:
Calculate for Taxpayer(id=0) { id=A age=26 agi=27000 documentCode=7 interestIncome=600 result=? taxableIncome=60000 taxablePension=0 zipCode=OTHER } Assign: Next Year Documents = MFR02 [MFR02] Calculate for Taxpayer(id=0) { id=B age=26 agi=27000 documentCode=30 interestIncome=500 result=? taxableIncome=60000 taxablePension=0 zipCode=OTHER } Assign: Next Year Documents = ? [?] ...
Of course, initially I had several invalid expectations and OpenRules html-reports helped me to fix them pointing exactly which rules were executed. This completes my solution.