Bruce Silver's blog post - Set Operations in DMN
Bruce Silver
Blog

Set Operations in DMN

By Bruce Silver

Read Time: 5 Minutes

We all learned in junior high school math class about sets and Venn diagrams. Which elements of set A are also members of set B? This concept comes up in decision logic as well, and you would expect DMN to be able handle it. It can, but it’s a little complicated, because technically DMN does not have the notion of a set, an unordered collection of elements without duplicates. Instead it has lists, ordered collections that could include duplicates. Nevertheless, we can still perform set operations on collections in DMN. This post will show you how.

When testing membership of an individual item, there is no difference between a list and a set. Testing whether some individual item is contained in a DMN list occurs often in decision models, and there are multiple ways to do it. For example, suppose we have a static list of Required Attachment Types, and we want to know whether a particular Attachment is in that list. Required Attachment Types is technically a list, but it contains no duplicate values and the order doesn’t matter, so it’s effectively a set. We can test whether input data Attachment is in the required list using the DRD below.

Let’s say Required Attachment Types includes just two of the five possible values of tAttachmentType, as shown below.

Input data Attachment is type tAttachment, a structure shown here:

The Boolean decision is Required can use a literal expression with the list contains() function

list contains(Required Attachment Types, Attachment.type)

or the in operator:

Attachment.type in RequiredAttachmentTypes

You can also use count() on a filter:

count(Required Attachment Types[item=Attachment.type])>0

Set Operations

Testing membership of a single item in a set is straightforward. But what if we have a collection of Attachments? Then it gets more complicated. We might want to know if any of them are in Required Attachment Types, or if all of them are in that set, or which ones are in the set. Those involve set operations. In set operation terms, we talk about the union of two sets, the intersection of two sets, containment of one set in another, and whether two sets are identical. Let’s see how to implement those in DMN.

Remember, a set is an unordered deduplicated list. I will use listA and listB to mean ordered collections including duplicates, as opposed to setA and setB, with duplicates removed and where the order does not matter. The FEEL functions union() and distinct values() remove duplicates but retain an ordering of the items.

Intersection

Lets start with intersection. The intersection of two sets is the collection of items belonging to both. The filter

distinct values(listA[list contains(listB, item)])

returns a list of items in listA that are also contained in listB. So it is an ordered version of the intersection of setA and setB.

To test whether two sets intersect at all, we can apply the count() function to the list above, or we can use the some..in..satisfies operator. The latter is actually more straightforward:

some item in listA satisfies list contains(listB, item)

Let’s apply this to our Required Attachment Types example. It’s slightly different because the datatypes of listA and listB are not the same, and Attachments may contain multiple items with the same type component.

Now input data Attachments is Collection of tAttachment, and decision Intersection finds the set of Attachments whose type component is in the set Required Attachment Types. Here we can omit the distinct values() function because all Attachments have distinct id values. Let’s say Attachments has 3 items, 2 of which are in Required Attachment Types:

Intersection uses a filter with list contains():

Union

The union of two sets is the collection of items belonging to either one. The FEEL function

 union(listA, listB)

removes duplicates but retains an ordering. It is the same as

distinct values(concatenate(listA, listB))

and is as close as we’re going to get.

In our Required Attachment Types example, union(Attachments.type, Required Attachment Types) should return any values which are part of either set.

Containment

We say setB is contained in setA if all elements of setB are members of setA, i.e., setB is a proper subset of setA. For this we can use the every..in..satisfies operator to test containment.

if every item in listB satsifies list contains(listA, item) then...
Sometimes we might want to test if any item in setB is not contained in setA. For that we just negate the logic above:
if not(every item in listB satisfies list contains(listA, item)) then...

In our example, we can ask if Attachments contains at least one example of each type in Required Attachment Types. In our case, this is only Contract and NDA, and both are contained:

Is Identical

SetA and setB are identical if every item in setA is in setB and every item in setB is in setA. We could test if setB contains setA and setA contains setB, but there is a shorter way using the union() function in combination with every..in..satisfies:

every i in union(listA, listB) satisfies (list contains(listA, i) and list contains(listB, i))

In our example, Attachments.type is not identical to the set Required Attachment Types:

Set Operations in Decision Tables

It’s a little known fact that the generalized unary test format for decision table conditions originated from a need to perform set operations similar to the ones described here. One tool vendor complained that in their existing software – not yet DMN – a decision table condition could be a complex expression, not restricted to the basic comparison tests allowed by simple unary tests, and their critical use case was like the one above: Do the Attachments contain all items in the list of Required Attachment Types? This is the Containment set operation. From that requirement, the DMN task force created generalized unary tests, in which any FEEL expression can be used in a condition cell, replacing the column heading variable with a ‘?’ character. I saw little use for it at the time, but it has turned out to be incredibly useful. (Naturally, the vendor demanding it still has not adopted DMN.)

In the decision table below, ? in the condition cell stands for the column heading Required Attachment Types. The decision returns “true” if the Attachments.type include all of the Required Attachment Types.

DMN is an incredibly versatile language, capable of implementing logic that is seemingly outside of its domain. Our DMN Method and Style training is a hands-on deep-dive into its use and best practices. It comes with 60-day use of the Trisotech Decision Modeler and post-class certification. Check it out!

Follow Bruce Silver on Method & Style.

Blog Articles

Bruce Silver

View all

All Blog Articles

Read our experts’ blog

View all

Learn how it works

Request Demo

Confirm your budget

Request Pricing

Discuss your project

Request Meeting
Graph