Content uploaded by Jacob Feldman

Author content

All content in this area was uploaded by Jacob Feldman on Jan 02, 2019

Content may be subject to copyright.

Model-based Solutions for DM Community Challenge “Flight Rebooking”

Decision Management Community Oct-2016 Challenge “Rebooking Passengers from Cancelled Flights” is

among the most complex challenges. It is used by authors of several decision modeling books to show

the power of different approaches. Here is the problem definition:

A flight was cancelled, and we need to re-book passengers to other flights considering their frequent

flyer status, miles, and seat availability. Here is a sample data and flight assignment rules:

So far, five submitted solutions used different tools and techniques from Java to DMN boxed

expressions. However, they all (including my decision model) were "method-based" meaning they

specify a certain execution algorithm (method) that could be summarized as in Fig. 1.

This is certainly a “greedy” algorithm (or a heuristic) that will produce a feasible decision, but we would

never know if this decision is the optimal one or not. For a larger problem such method-based approach

may leave some passengers very upset unless we implement a smarter decision model. The problem

with the method-based approach is that it expects a human decision modeler to describe exactly how to

do flight assignments while it’s humanly impossible to consider all possible variants. In this post I will

describe a much more powerful, “model-based” approach to this problem that leads to the optimal

solution. You may read more about model-based decisioning here.

1. First, sort all passengers using their GOLD, SILVER or BRONZE status. If two passengers have the

same status use miles as a tiebreaker.

2. Repeat for every passenger from the sorted list:

• Build a list of “suitable flights” for the selected 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

• Sort the flights inside this list by an earlier departure time

• Assign the flight on the top of the list to the current passenger

• Decrement the flight’s capacity

Figure 1. A greedy algorithm for building passenger-flight assignments

The model-based approach is described in Fig. 2:

Given

F set of flights

P set of passengers from the canceled flight

For every passenger p Determine

xpf = 1 if passenger p is assigned to flight f F

= 0 if otherwise

delaypf = number of hours between arrivals of the flight f and

the passenger p’s canceled flight

= 100 if the passenger p is assigned to not scheduled flight f

penaltypf = delaypf* penaltyPerDelayedHourp

Subject to constraints

Each Passenger can be assigned to no more than 1 flight:

xpf1 + xpf2+ … + xpfn <= 1 for each passenger p P

Number of passengers assigned to the same flight cannot exceed the flight’s capacity

xfp1 + xfp2+ … + xfpn <= fcapacity for each flight f

Minimize

pf*xpf)

Figure 2. Flight Rebooking: Model-Based Representation

This model for each passenger introduces a new decision variable penaltyPerDelayedHourp that

represents a passenger’s penalty for one delayed hour. These penalties could be calculated

independently to which flight this passenger is assigned, but the product

penaltypf * xpf

gives us a penalty for the assignment of the passenger p to the flight f. Thus, our objective is to minimize

the total penalties that is presented as a sum of all penalties for all possible combinations p and f.

All passenger-flight assignments are subject to two constraints:

1. Each passenger can be assigned to no more than 1 flight

2. A number of passengers assigned to the same flight cannot exceed the flight capacity.

Below I describe two possible implementations of this model using OpenRules and JSR-331:

• Implementation using Excel and Java

• Implementation using Excel without Java

FIRST IMPLEMENTATION (Excel and Java)

Our decision model will consist of two parts:

1) A pure business part that specifies employee eligibility to all types of vacation days

2) A more technical optimization part that deals with the representations of the constraints and

optimization objective.

Business Problem

We will assume that our Business Problem contains:

- Cancelled flight

- Passengers – a set of passengers from the cancelled flight

- Scheduled Flights – a set of flights.

We will add a special “FAKE” flight to the list of “Scheduled Flights”, assuming every passenger can be

booked to this flight but the penalty for such “fake” booking is huge.

Let’s also assume that our Business Problem includes a list of all possible bookings that are combinations

“Passenger-Flight” for all Passengers and Flight (including the fake one).

First, for every passenger we can define the decision variable “Passenger Penalty For Delayed Hour”

(called penaltyPerDelayedHourp in the model in Fig.2). These penalties could be calculated

independently to which flight this passenger will be assigned using the following decision tables:

Figure 3. Flight Rebooking: Calculate Passenger Penalty for Delayed Hour

Second, for every possible booking (a combination “Passenger-Flight”) we can define the booking

properties using the decision table “DecisionTableIterate” in Fig. 4:

Figure 4. Flight Rebooking: Defining Booking Properties

It will define booking suitability, booking delay, and booking penalty using the following decision tables:

Figure 5. Flight Rebooking: Defining Booking Properties

I put all above tables in the file “FlightRebooking.xls”. To complete this decision model, I added the table

“Glossary” to the same file:

Figure 6. Flight Rebooking: Business Glossary

To define the corresponding datatypes I created three Java classes “BusinesProblem”, “Passenger” and

“Flight”. They are simple Java beans (a data structure) that include attributes from the glossary plus

several more attributes. Here they are:

BusinessProblem:

Flight cancelledFlight;

Flight [] flights;

Passenger [] passengers;

ArrayList<Booking> bookings;

Flight:

String number;

String departureAirport;

String arrivalAirport;

Date departureTime;

Date arrivaTime;

int capacity;

boolean fake;

Passenger:

String name;

String status;

int miles;

String departureAirport;

String arrivalAirport;

Flight cancelledFlight;

Date oldArrivalTime;

String newFlight;

int penaltyForDelayedHour;

To test our decision model, I defined two Data tables in the file “Test.xls”:

Figure 7. Flight Rebooking: Test Data

The first table contains all flights starting with the cancelled one. The second table contains a list of

passengers to be assigned to a scheduled flight (if possible).

I used the following Java launcher to run this decision model:

Figure 8. Flight Rebooking: Java Launcher for Business Problem

When I ran this model, it produced the following results:

==== Rebooked Passengers

Passenger [name=Tom, status=BRONZE, miles=10000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=15, newFlight=?]

Passenger [name=Igor, status=GOLD, miles=50000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=26, newFlight=?]

Passenger [name=Jenny, status=GOLD, miles=500000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=25, newFlight=?]

Passenger [name=Harry, status=GOLD, miles=100000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=27, newFlight=?]

Passenger [name=Dick, status=SILVER, miles=2500, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=18, newFlight=?]

==== Possible Bookings

Assignment: Tom=>FAKE, suitable=true, delay=1000, penalty=15000

Assignment: Tom=>UA456, suitable=true, delay=1, penalty=15

Assignment: Tom=>UA789, suitable=true, delay=4, penalty=60

Assignment: Tom=>UA1001, suitable=false, delay=22, penalty=330

Assignment: Tom=>UA1111, suitable=false, delay=22, penalty=330

Assignment: Igor=>FAKE, suitable=true, delay=1000, penalty=26000

Assignment: Igor=>UA456, suitable=true, delay=1, penalty=26

Assignment: Igor=>UA789, suitable=true, delay=4, penalty=104

Assignment: Igor=>UA1001, suitable=false, delay=22, penalty=572

Assignment: Igor=>UA1111, suitable=false, delay=22, penalty=572

Assignment: Jenny=>FAKE, suitable=true, delay=1000, penalty=25000

Assignment: Jenny=>UA456, suitable=true, delay=1, penalty=25

Assignment: Jenny=>UA789, suitable=true, delay=4, penalty=100

Assignment: Jenny=>UA1001, suitable=false, delay=22, penalty=550

Assignment: Jenny=>UA1111, suitable=false, delay=22, penalty=550

Assignment: Harry=>FAKE, suitable=true, delay=1000, penalty=27000

Assignment: Harry=>UA456, suitable=true, delay=1, penalty=27

Assignment: Harry=>UA789, suitable=true, delay=4, penalty=108

Assignment: Harry=>UA1001, suitable=false, delay=22, penalty=594

Assignment: Harry=>UA1111, suitable=false, delay=22, penalty=594

Assignment: Dick=>FAKE, suitable=true, delay=1000, penalty=18000

Assignment: Dick=>UA456, suitable=true, delay=1, penalty=18

Assignment: Dick=>UA789, suitable=true, delay=4, penalty=72

Assignment: Dick=>UA1001, suitable=false, delay=22, penalty=396

Assignment: Dick=>UA1111, suitable=false, delay=22, penalty=396

As you can see, so far, our decision model only calculated attribute “penaltyForDelayedHour” for

every passenger (but not “newFlight”) and evaluated attribute suitable, delay, and penalty for every

possible booking.

To define actual passenger-flight assignments (bookings) we need to implement the second part of our

decision model.

2. Optimization Problem

Now we will implement the second (optimization) part. First we will introduce unknowns xpf and

penaltypf defined in Fig. 2, then we will define an optimization objective

pf*xpf)

Which should be minimized. The first major constraint “Each Passenger can be assigned to no more than

1 flight” now, when we added a FAKE-flight, can be expressed as

xpf1 + xpf2+ … + xpfn = 1 for each passenger p P

The second constraint “Number of passengers assigned to the same flight cannot exceed the flight’s

capacity” remains the same:

xfp1 + xfp2+ … + xfpn <= fcapacity for each flight f

In my initial implementation I decided to do it directly in Java using JSR-331 (a constraint programming

standard). First, I added the Java class “Booking” with the following attributes:

BusinessProblem problem;

Passenger passenger;

Flight flight;

boolean suitable;

int delay;

int penalty;

Var var;

If flight is “FAKE” it uses MAX_DELAY_HOURS = 1000 to define the delay.

Then I defined a Java class “Optimization” as a subclass of the standard class “OptimizationProblem” –

see Fig. 9.

Figure 9. Flight Rebooking: Optimization Problem in Java with JSR-331

The method “define()” first defines a constrained variables “x” for every possible passenger-flight

assignment (booking):

Var x = csp.variable(booking.getName(), 0, 1);

This variable could take only values 0 or 1. The name of each variable ”x” is composed as

passenger.name + “=>” + flight.number

If the booking is not suitable, we make this variable to be equal to 0:

csp.post(x, "=", 0);

Then we define a booking’s penalty:

penalties[n] = x.multiply(booking.getPenalty());

The optimization objective “TotalPenalty” is defined as a sum of all booking penalties:

Var objective = csp.sum(penalties);

To define the constraint “Each Passenger can be assigned to no more than 1 flight”, we create an array

“passengerBookingVars”, that contains all booking variables “x” related to the selected passenger, and

then post the constraint

csp.post(sumPassengerBookingVars, "=", 1);

Here we used the operator “=” instead of “<=” because our list of flights contains the FAKE-flight, to

which any passenger can be assigned (meaning this passenger will have no booking).

To define the constraint “Number of passengers assigned to the same flight cannot exceed the flight’s

capacity”, we create an array “flightBookingVars”, that contains all booking variables “x” related to the

selected flight, and then post the constraint

csp.post(sumFlightBookingVars, "<=", flight.getCapacity());

This completes the problem definition. As we want to minimize the “TotalPenalty” we may rely on the

default method “solve()”. We only need to define the method “saveSolution()” that will be called when

the optimal solution is found to setup business attribute “newFlight” for every passenger.

And finally we should add these 3 lines to our Java launcher in Fig.8 before printing Rebooked

Passengers:

Optimization optimization = new Optimization(businessProblem);

optimization.define();

optimization.solve();

Here is the optimal solution produced by our decision model:

=== SOLVE:

Found a solution with TotalPenalty[18216]. Fri Dec 14 17:27:10 EST 2018

Found a solution with TotalPenalty[18213]. Fri Dec 14 17:27:10 EST 2018

Found a solution with TotalPenalty[15249]. Fri Dec 14 17:27:10 EST 2018

Found a solution with TotalPenalty[15228]. Fri Dec 14 17:27:10 EST 2018

Found a solution with TotalPenalty[15225]. Fri Dec 14 17:27:10 EST 2018

Solution #1:

Tom=>FAKE[1] Tom=>UA456[0] Tom=>UA789[0] Tom=>UA1001[0] Tom=>UA1111[0]

Igor=>FAKE[0] Igor=>UA456[1] Igor=>UA789[0] Igor=>UA1001[0] Igor=>UA1111[0]

Jenny=>FAKE[0] Jenny=>UA456[0] Jenny=>UA789[1] Jenny=>UA1001[0] Jenny=>UA1111[0]

Harry=>FAKE[0] Harry=>UA456[1] Harry=>UA789[0] Harry=>UA1001[0] Harry=>UA1111[0]

Dick=>FAKE[0] Dick=>UA456[0] Dick=>UA789[1] Dick=>UA1001[0] Dick=>UA1111[0]

TotalPenalty[15225]

==== Rebooked Passengers

Passenger [name=Tom, status=BRONZE, miles=10000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=15, newFlight=FAKE]

Passenger [name=Igor, status=GOLD, miles=50000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=26, newFlight=UA456]

Passenger [name=Jenny, status=GOLD, miles=500000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=25, newFlight=UA789]

Passenger [name=Harry, status=GOLD, miles=100000, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=27, newFlight=UA456]

Passenger [name=Dick, status=SILVER, miles=2500, departureAirport=SFO,

arrivalAirport=SNA, penaltyForDelayedHour=18, newFlight=UA789]

As you can see, the optimal solution with TotalPenalty=15225 was found after 4 previous solutions

with larger total penalties were determined. The optimal Solution shows the automatically selected

values (0 or 1) all our variables “x”. The newFlight for the passenger Tom is “FAKE” meaning our decision

model was not able to find a flight for Tom, while all other passengers were assigned to the scheduled

flights in accordance with the problem requirements.

The execution time for finding an optimal solution for this small problem was only 17 milliseconds. It’s

important to notice that the same model will handle much larger numbers of passengers and flights and

can be reused in real-world systems.

This completes my first implementation. While this implementation demonstrates the power of the

model-based approach to decision modeling, it used Java code for the optimization part. In the next

section I will try to move this code to more user-friendly decision tables in Excel with minimal Java

involvement.

SECOND IMPLEMENTATION (Excel without Java)

In my second implementation I tried to move Java code to Excel-based tables. I consider this as work in

progress, and I am far from being satisfied with what I got so far. However, I’ve managed to move the

optimization piece from Java to Excel, and it works now producing the same optimal results. So, I

decided to share this preliminary representation of the same model hoping to get a constructive

feedback from the readers. The generic (problem-independent) implementation logic is now hidden

inside a special decision table template “DecisionTableCSPTemplate”. So, here are my Excel-based tables

(sorry, without comments as I hope they are self-explanatory).

The list of major sub-decisions:

The input data comes through an instance of the decision object “BusinessProblem”:

All used decision variables are defined in the following glossary:

Booking Business Rules:

Booking Optimization Constraints:

Passenger Booking Constraints:

Flight Booking Constraints:

The above tables utilized the following convenience methods defined in Excel:

The objective is defined as a sum of All Booking Penalty Variables:

This table is used to minimize the objective

and this table to save the found optimal solution:

This implementation produces the same solution as the first one.

Conclusion

Both implementations of our decision model have the following advantages:

• Instead of one possible decision, this model will find an optimal decision

• A business analyst will be able to adjust penalties in the decision table in Fig. 3 and the same

model will produce different optimal decisions

• This model can be used to address real-world flight rebooking problems with much larger

numbers of passengers and flights