Solving Flight Rebooking Challenge With and Without Programming Constructs

DMCommunity.orgFlightRebookingImage announced its Challenge “Rebooking Passengers from Cancelled Flights” in Oct-2016 and until now 4 different solutions have been submitted. It is a relatively complex use case for decision modeling. In this post I will describe different implementation approaches for this challenge and will discuss good and not so good DMN constructs used to support the underlying decisioning logic. I hope this post will initiate more discussions which may lead to the future DMN improvements by replacing the existing programming constructs to more business-friendly representations.

Here is the “business” problem:

A flight was cancelled and we need to re-book passengers to other flights considering their frequent flyer status, miles, and seat availability. How the re-booking logic can be formulated by a subject matter expert?

Probably using plain English similar to this one:

First, order all passengers using their GOLD, SILVER or BRONZE status. If two passengers have the same status use miles as a tiebreaker. Then, choose the first passenger from the sorted list and try to find a suitable flight for this passenger. A “suitable” flight should have the same departure and arrival airports as the cancelled flight and it also should still have an available seat. If there are two suitable flights, choose the one with an earlier departure time. Do the same for the second passenger from the sorted list, then for the third passenger, etc.

While it is sounds like a quite clear description of the “business logic”,  its representation as an executable decision model is not a simple task. Really, you need to sort lists of passengers and flights,  use tiebreakers, iterate through passenger and flight lists while controlling seat availability. No wonder that well-known DMN experts selected this challenge to demonstrate the most complex DMN constructs. Please take a closer look at the complete, working solutions provided by Bruce Silver and Edson Tirelli. Here I will reproduce only a fragment from Bruce’s DMN-based solution:

Edson’s solution is using similar logic and DMN constructs but looks somewhat different:

Whether you like these solutions or not, the important fact is that they both work and produce correct results. Being an experienced software developer myself, I can appreciate how they use typical programming constructs such as:

  • if-then-else statements and for-loops
  • functions with formal parameters
  • filters
  • dynamically built lists
  • elegant sorting facilities and
  • even a hidden recursion.

At the same time, I have to admit that it took me several reads to understand how these DMN FEEL Level 3 constructions might work. Probably most of us would not even dare to show these “not so business friendly” DMN examples to potential business users unless someone wants to discredit the young standard. But what do software developers think about them?

For example, one of OpenRules developers was very upset with both these solutions. I told him: “It is easy to criticize someone’s solution, but your critique should be constructive. Could you offer a better solution in OpenRules?” Instead, he quickly submitted his pure Java solution to the DMCommunity Challenge. I had to admit that it did look simpler to compare with above DMN-based solutions. The business rules approach always has to fight against pure Java solutions, and in this case my defense of the DMN-based solutions sounded like this:

At the very least you don’t want to hard-code in Java such business logic as comparison of passengers. Look how nicely Edson presented the comparison logic in this decision table:

If a customer decides to add more comparison criteria like ‘US Veteran’ or ‘Passenger traveling with a child’, one can naturally extend this decision table but multiple embedded IF-THEN-ELSE statements in your Java code would look ugly.”

He responded: “In this case keep the passenger comparison logic in a decision table but use basic Java instead of this strange programming language to represent above algorithms.”

So, I decided to try my own implementation of this Challenge. Finally, last week I found time to do it using our latest OpenRules DMN-implementation. I started with a pure passengers sorting decision model and then I expanded it to the complete flight re-booking decision model.

My challenge was to avoid using complex DMN programming constructs while trying to stay as close as possible to the commonly used DMN decision tables.

I would not say that I am satisfied with what I managed to do so far. However, I decided to share my current implementation with the readers and let them decide if I am at least moving in the right direction.  So, be patient and follow my explanations below.

=============== OpenRules-based Implementation ==============

My objective was to build a decision model called “DecisionFlightRebooking” which on the top-level can be described using the following Decision Requirement Diagram (DRD):

To deal with this problem, we will need two arrays Passengers and Flights, which I decided to present in the Java class Problem:

Step 1. Sort Passengers

First, I wanted to respond to my colleague’s challenge and to show how passenger comparison decision table can be used to sort an array of passengers.  So, I created a passenger comparison decision table in Excel – as you can see, it is very similar to the Edson’s decision table above:

This table can be used to compare any two passengers: a passenger with the higher score has a preference during sorting. To actually sort the array of our passengers using the decision table “ComparePassengers”, I created a special OpenRules table of the type “DecisionTableSort“:SortPassengers

This table sorts the arrays “Passengers” by comparing every two elements of this array using “ComparePassengers” rules.  I put all decision variables used by these tables in the following Glossary:

Thus, the array “Passengers” is a decision variable defined by the business concept “Problem”. Each element of this array has type “Passenger” and the glossary must include two business concepts “Passenger1” and “Passenger2”, which names are formed by adding “1” and “2” to the type of the array elements. 

To be able to sort an array of objects using the DecisionTableSort,  the elements of the array “Passengers” should have type “Passenger” that extends the standard OpenRules class ComparableDecisionVariable. So, I created the Java class Passenger in Eclipse which automatically generated for me all getters and setters:

public class Passenger extends ComparableDecisionVariable {
	String name;
	String status;
	int miles;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}
	public int getMiles() {
		return miles;
	}
	public void setMiles(int miles) {
		this.miles = miles;
	}
	public String toString() {
		return "Passenger [name=" + name + ", status=" 
                        + status + ", miles=" + miles + "]";
	}
}

Initially my model “DetermineFlightRebooking” only sorted passengers as defined by the following main decision:

To execute this model I used the following Java launcher:

public static void main(String[] args) {
   String fileName = "file:rules/DecisionFlightRebooking.xls";
   String decisionName = "DetermineFlightRebooking";
   Decision decision = new Decision(decisionName,fileName);
   decision.put("FEEL", "On");
 
   Problem problem = new Problem();
   decision.put("Problem", problem);
   decision.execute(); 
 
   for(Passenger p : problem.passengers) {
      System.out.println(p);
   }
}

The produced results:

Passenger [name=Jenny, status=GOLD, miles=500000]
Passenger [name=Harry, status=GOLD, miles=100000]
Passenger [name=Igor, status=GOLD, miles=50000]
Passenger [name=Dick, status=SILVER, miles=100]
Passenger [name=Tom, status=BRONZE, miles=10]

Step 2. Assign New Flights

When the passenger sorting was completed and worked fine, I started to expand it to the complete “DecisionFlightRebooking” model. The expanded main decision looks as follows:

Assuming that all passengers are already sorted, the new sub-decision “RebookAllPassengers” we should try to assign suitable flights to all passengers one by one. I wanted to implement the re-booking logic mainly in Excel-based decision tables. To  iterate through all passengers I can use a special OpenRules table of the type “DecisionTableIterate“:

RebookAllPassengers

This decision table will apply the rules “RebookOnePassenger” to each passenger from the already sorted array of “Passengers”. Now, the actual re-booking logic for one passenger should be described in the decision “RebookOnePassenger”. In plain English it should do the following for each considered passenger:

  1. Evaluate all flights by marking them as suitable or not for this passenger
  2. Sort all flights for this passenger
  3. Select the very first flight from the sorted list of flights
  4. If it is suitable, assign it as a new flight to the considered passenger and decrement the remaining capacity of this flight. If it is not suitable, this passenger cannot be re-booked (a new flight is “?”).

I decided to implement these 4 steps in  the following table:

The first step  iterates over the array “Passenger Flights”:

EvaluateFlightForOnePassenger

For each flight from the array “Passenger Flights” we define its suitability for the current Passenger by executing the following decision table:

The second take step the current object “Passenger” $O{Passenger} and calls its method “sortFlights()“.

After flights are sorted, the step 3 takes the very first flight defined in the Java snippet as $O{Passenger}.flights[0] and sets it as the current business object “Flight”. Then the last step sets “Passenger New Flight” to be equal to the current Flight’s number if it is suitable or to “?” otherwise:

Note that the latest decision table may also decrement Flight Capacity by removing an assigned seat.

To make it all work, I needed to add more business concepts and decision variables to my Glossary:

First, I added a new Java class Flight using the above Flight attributes. I implemented the class Flight as a subclass of the standard Java class Comparable that allowed me to use the following method to compare two flights:

Here the Data comparison is done by the standard Java Date’s method “before” that takes care about both date and time comparison. The method “iSuitable()” returns true if this flight is a suitable replacement for the cancelled flight of the considered passenger.

I added more attributes from the expanded Glossary to the class Passenger as well. Note that now each passenger contains its own array of flights. To sort flights for each passenger, I used the standard Java Array’s method sort(), which I call inside the method “sortFlights” of the class Passenger :

I used the same Java launcher to execute the expanded decision model “DetermineFlightRebooking”. Here are the expected results:

==== Rebooked Passengers
Passenger [name=Jenny, status=GOLD, miles=500000, flight=UA123] - rebooked to UA456
Passenger [name=Harry, status=GOLD, miles=100000, flight=UA123] - rebooked to UA456
Passenger [name=Igor, status=GOLD, miles=50000, flight=UA123] - rebooked to UA789
Passenger [name=Dick, status=SILVER, miles=100, flight=UA123] - rebooked to UA789
Passenger [name=Tom, status=BRONZE, miles=10, flight=UA123] - rebooked to ?

A curious user may look at the complete decision model in this Excel file.

Conclusion. I believe that the described implementation demonstrates that it is possible to implement even quite complex decision logic using the basic DMN-like decision tables and to avoid complex programming constructs currently included in the DMN FEEL. Hopefully, future DMN releases will find better solutions while avoiding programming.

P.S. For people who want to compare this solution with a pure Java solution, here is a working Java code:

Unfortunately, I have to admit that this Java code looks quite straightforward and probably many people will find this code to be more attractive to compare with all 3 DMN-based solutions provided by Bruce, Edson, or myself.

Advertisements

About jacobfeldman

CTO at www.openrules.com http://www.linkedin.com/in/jacobfeldmanopenrules
This entry was posted in Decision Management, DMN, Tools and Technologies, Use Cases. Bookmark the permalink.

2 Responses to Solving Flight Rebooking Challenge With and Without Programming Constructs

  1. Jacob,

    While I value the discussion you are raising, I think there are a few misconceptions in your article. Here are my thoughts:

    * the perceived complexity you mention does not come from the language itself, but from the problem. Real world problems are not trivial. The alternative solutions presented in the article are not “removing” what you call “programming constructs”, they are just moving them from the decision model to Java or OpenRules API. The same constructs are still there, but now instead of being in single model, they are spread between decision tables, java code and product APIs.

    * the solutions are not mutually exclusive. The choice of using one tool or another should be driven by requirements (functional or not). If this decision needs to be implemented into a java program one is free to use a java solution. But if one is delivering this decision as a service into a Decision Management platform, that is self-contained and dynamic, the ability to do so all in DMN is a great benefit.

    * DMN defines several compliance levels as you know. If OpenRules is happy to provide compliance level 2 and direct customers to use java whenever they need to go beyond DMN level 2 capabilities, there is nothing wrong about it. It is a perfectly valid choice. Having said that, the additional language expressiveness that compliance level 3 brings is important for those that want to take a different approach, sticking to a known standard. We should not scrap one in favour of another. Both level 2 and level 3 have their place.

    * You said: “Probably most of us would not even dare to show these “not so business friendly” DMN examples to potential business users unless someone wants to discredit the young standard”. Isn’t this a bit of FUD? 🙂 Customer/user’s skill is a continuum, not a binary attribute: some users might be comfortable with diagrams only, while others might be comfortable with excel macros, and everything in between. Some might be happy to stick with compliance level 1-2, while others will appreciate level 3. Nothing wrong with that either.

    Anyway, just wanted to share a different perspective here.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s