RAVE in Crew Planning
RAVE in Crew Planning
schedule optimization
Master’s thesis in Computer Science – Algorithms, Languages & Logic
JACOB RIPPE
JACOB RIPPE
Typeset in LATEX
Gothenburg, Sweden 2018
iv
Using semantic analysis to assist schedule optimization
JACOB RIPPE
Department of Computer Science and Engineering
Chalmers University of Technology and University of Gothenburg
Abstract
Airline Crew Planning is a complex task often divided into many steps to reduce
complexity. One approach for finding good solutions is to generate a large set of
solutions and determine which combination of solutions satisfy all constraints at the
lowest cost.
We have analyzed a software system for generating solutions that uses rules stated
in a DSL to determine solution legality. The legality is checked during solution
generation, and the legality of the solution in progress affect the generation strategy.
The question this project sought to answer is whether it is possible to determine
certain properties of the rules at compile-time. The approach has been to analyze
the structure of the rules and assign semantic information in a method inspired by
type inference rules.
In an iterative fashion, theories about the system were formed, and tested by imple-
menting checks inside the DSL compiler. After manual verification of the theories
by looking at the output of the implementation, the theories were expanded upon
or revised.
The implementation has been able to automatically identify a few rules with the de-
sired properties, and more may be identified with continued development. Inference
rules were a general approach to deciding properties, and more interesting findings
might be found using more advanced techniques. However, there is a limit to what
can be decided by static analysis.
Aside from analyzing existing rules, some semantic information may be of assistance
when writing new rules, and might even be of assistance at runtime in future projects.
v
Acknowledgements
I am very grateful to have been given this opportunity to do my thesis work at Jeppe-
sen at their Gothenburg office. Jeppesen has kindly provided me with everything
I’ve needed to make this thesis a possibility.
I want to thank Fredrik Altenstedt and Thomas Johnsson for agreeing to be my
technical advisors and provide insight, technical assistance, feedback and many in-
teresting discussions about the project.
Thanks to everyone at Jeppesen who have shown interest and cheered me on.
Thanks to Andreas Westerlund, who made this project a reality by introducing me
to my advisors.
Thanks to Kristoffer Ptasinski for taking care of the administrative details of my
work at Jeppesen.
Thanks to Tomas Gustafsson for assisting with the thesis writing.
Thanks to Michael Spicar for letting me stay in his office and allowing me to claim
all whiteboard space for the past few months.
vii
Contents
List of Figures xi
Glossary xiii
1 Introduction 1
1.1 Project Aim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Problem Description . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 Crew Planning . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2 The Pairing Generator . . . . . . . . . . . . . . . . . . . . . . 2
1.2.3 The Rule System and Illegal Subchain Rules . . . . . . . . . . 2
1.2.4 Rule Classification . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Theory 5
2.1 Background and Related work . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Rave Language Overview . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.1 About the language . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.2 The components of Rave code . . . . . . . . . . . . . . . . . . 6
2.2.3 Expressions in Rave . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.4 Instances of Levels and Expressions . . . . . . . . . . . . . . . 9
2.2.5 Rules and Legality . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.5.1 Valid case . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Model and Domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 Domain to model . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.2 Some formalisms . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3.3 Consequences of Misclassification . . . . . . . . . . . . . . . . 14
2.3.4 Conditional rule checking . . . . . . . . . . . . . . . . . . . . 15
2.3.4.1 Manual rule classification . . . . . . . . . . . . . . . 15
2.3.4.2 Conditional rule checking example with is_closed . . 16
3 Methods 19
3.1 Classification and Attributes . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.1 Approach and Goals . . . . . . . . . . . . . . . . . . . . . . . 19
3.1.2 Classification using attributes . . . . . . . . . . . . . . . . . . 20
3.1.3 Attribute rules and propagation . . . . . . . . . . . . . . . . . 21
3.2 Attributes by category . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1 Range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
ix
Contents
4 Results 35
4.1 What has been done in this project . . . . . . . . . . . . . . . . . . . 35
4.2 Results of implementation . . . . . . . . . . . . . . . . . . . . . . . . 35
4.3 Example of attribute propagation for rule . . . . . . . . . . . . . . . . 35
5 Conclusion 37
5.1 Findings of this project . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.1.1 Special mention on conditional variables . . . . . . . . . . . . 37
5.1.2 Reflections on expressiveness of classification . . . . . . . . . . 37
5.2 Other applications of semantic analysis . . . . . . . . . . . . . . . . . 38
5.3 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5.3.1 Explore more attributes and rules . . . . . . . . . . . . . . . . 39
5.3.2 Assisting runtime optimization . . . . . . . . . . . . . . . . . 39
5.3.3 Simplify rule writing . . . . . . . . . . . . . . . . . . . . . . . 40
5.4 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Bibliography 44
A Appendix 1 I
A.1 Example code with computed attributes . . . . . . . . . . . . . . . . I
x
List of Figures
xi
List of Figures
xii
Glossary
xiii
Glossary
xiv
1
Introduction
Programming languages and their usage evolve over time. One goal when developing
a language further is to make it easier for a programmer to express what they want
to achieve.
Domain Specific Languages (DSLs) are a sort of programming languages that are
designed to be especially expressive in their own domain but with limited use outside
of that domain, Mernik et al. [24]. This enables a programmer to model problems
without needing to think about the low-level implementation details. Keshishzadeh
and Mooij have discussed semantic analysis of DSLs [19], and DSL design and im-
plementation is described in detail by Voelter et al. [29].
The company Jeppesen supplies Airline Optimization Solutions, one being crew
schedule optimization. To model this domain, they have developed their own DSL,
Rave (Rule And Value Evaluator) [2, 3, 21]. Kasirzadeh et al. describes some chal-
lenges of crew scheduling in general [18], and Goumopoulos & Housos [15] discusses
another DSL and system for trip generation in Crew Pairing.
Rave is used to formally express rules and costs associated with scheduling that can
be used in their optimizing system. To deal with the massive amount of regulations
in Airline - such as government rules, union agreements, company policies, and so
on - these regulations are implemented as Rave code and compiled into rulesets that
can be evaluated when scheduling.
This project will study Rave in an effort to automate the detection of patterns in
the code that can lead to inefficiencies.
This project aims to develop a method for automatically classifying different types
of rules expressed in the DSL Rave, specifically detecting if a rule is a so called Illegal
Subchain rule or not. Currently, it is up to the programmer to manually classify
these rules, which puts an extra burden on them to have a grasp of the scheduling
process. Improper classifications of rules are not always easy to find, and can lead
to performance issues or worse solutions.
The main theory that this project aims to verify is that it is possible to classify these
rules automatically at compile time.
1
1. Introduction
2
1. Introduction
In order to check legality of incomplete trips by the generator, the concept of Illegal
Subchains was created.
An Illegal Subchain Rule is a rule that when given a complete trip may be evaluated
to true, but it may evaluate some, or all, sub-trips to false. Example:
A rule stating that a trip must start and end in the same airport.
When building a trip satisfying this rule, the generator starts with one flight, and
checks if it is legal. Assuming that there are no scheduled flights that start and end
in the same airport, there is no flight that alone can satisfy the rule.
Thus, without some changes in strategy, the generator would find no legal trips
when using this rule. To circumvent this, it is possible to state that a rule should
only be evaluated when certain conditions are met.
For a complete trip to be legal it still has to satisfy all rules in the ruleset, but
conditional rule checking can make sure that Illegal Subchain Rules do not interfere
with the generation of otherwise legal trips.
1.3 Limitations
This project is intended as a proof of concept for possible future development of
optimization of processes using the Rave language. As such it is somewhat experi-
mental, and its main focus is studying the possibility to improve the existing system
with semantic properties to reason about how the evaluation of expressions changes
during Pairing Generation.
Rave is used to model many things in the system, but this project is only interested
in how it is used during the generation phase of Crew Pairing. Therefore, only a
subset of the language is studied, and some of the theories will only apply in this con-
3
1. Introduction
text. The assumptions and simplifications of the system are described in Section 2.3.
The project only implements some static analysis of some existing code, but some
other approaches are considered as well.
4
2
Theory
5
2. Theory
6
2. Theory
%one% = 1 ;
%five% = 4 + %one% ;
Keywords are like a special kind of variable that is used to refer to external data,
such as flight times. This data is supplied by the application running the Rave code;
in this case it is the Pairing Generator. The keywords are not assigned values in the
Rave code, but they can be referenced in Rave expressions.
Rules are defined in terms of boolean expressions that describe the legality of input
data. Rule definitions start with the reserved word rule followed by the rule’s name
and the =-character. There exist more constructs to express more complex rules
but, for the scope of this project, what’s interesting is that rules have a defining
expression. Optionally a valid case can be added before the defining expression, to
decide when a rule should be evaluated. The end of a rule definition is marked by the
reserved word end. Rules and legality are described in more detail in Section 2.2.5.
Example rules:
rule rulename =
%rule_expression% ;
end
rule cond_rule =
valid %rule_condition% ;
%rule_expression% ;
end
Levels are a way to partition the trip in progress into smaller parts.
Using levels it is possible to write expressions that refer to “all legs within a working
day”, “all legs in the current trip”, or “all working days in the current trip”. New
levels can be defined in Rave code, but this project will focus on three standard
types: Trip, Duty, Leg. Leg refers to a single flight, duty refers to the flights of
a working day and trip refers to all legs. Legs are automatically grouped into level
instances according to the level’s definition. More on this in Section 2.2.4
Figure 2.1 shows an example of a trip with 6 legs, partitioned into 2 duties.
An example statement: The total flight time of a duty can be described as the sum
of flight times of all legs in that duty.
7
2. Theory
Trip
Duty
Leg
Figure 2.1: Illustration of some common levels in Rave. A trip consists of duties,
which consist of legs. The underlying datastructure can be regarded as a list of
legs in chronological order (a trip) with indices that denote where the different level
instances start and end.
sidered subexpressions to the operation. The value of the operations follow the
algebraic laws and is usually an integer. Examples:
• 5 + 5 ;
• -1 ;
• 100 * 100 ;
Comparisons are related to the mathematical operations, but they state the re-
lationship of two expressions in relation to an operator. The operators are Equal-
ity(=), Nonequality(<>), Greater than (>), Less than (<), Greater or equal(>=),
and Less or equal(<=). The value of the operations state whether the comparison
is true of false. Examples:
• 1 > 2 ;
• %sum% <= %limit% ;
• True <> False ;
Value constants are expressions that are simply defined to hold some value, which
doesn’t change during runtime. Parameters are related to constants, as they are
defined in terms of a constant value. The difference is that the value of a parameter
may be changed at runtime, before generation. Optionally, parameters can have a
minimum and/or a maximum value limit(s) that limit the possible value range of
the parameter. Examples:
• 50 ;
• True ;
• "Hello" ;
• %bounded_param% = parameter 7 minvalue 5 maxvalue 12 ;
The last example defines the parameter %bounded_param%, with a default value of
7. This may be changed at runtime, but it can only be set to a value within the
range [5,12].
Boolean operations such as and, or, and not are used to combine boolean ex-
pressions into more complex boolean expressions. Examples:
8
2. Theory
• True or False ;
• not True ;
• (5 > 3) and %boolean_variable% ;
Conditionals are the standard if a then b else c constructs as seen in most
programming languages used when the resulting value depends on some condition.
The value of the expression is the evaluation of b or c, if a evaluates to true or false
respectively. Example:
if %condition%
then 20
else 25 ;
This expression evaluates to 20 if %condition% is true, and 25 if it is false.
Traversers are used to evaluate expressions on one or more level instances. They
can be used to refer to multiple level instances at once or to relate to a specific
instance, and there are many kinds that compute different things. Some central
ones are sum, count, next, prev, first, last, any, and all.
The evaluation of a traverser expression may vary depending on what the trip in
progress consist of, so they can be used to express properties of specific level in-
stances.
Traversers make up the functionality that is made possible by loops and recursion
in many other programming languages and as such, Rave has no other concepts of
loops.
• sum(leg(duty), leg.%time%) evaluates the sum of the leg-expression %time%
for all legs in a duty. This is one way to define the total flight time of a duty.
• count(leg(duty)) counts the number of instances of legs in a duty. Equiva-
lent to sum(leg(duty), 1).
• prev(duty(trip), duty.%time%) evaluates the duty-expression %time% of
the duty before the current duty.
• last(leg(duty), leg.%end_utc%) evaluates the leg-expression %end_utc%
for the last leg in the current duty. This is one way to define the time of the
last landing in a duty.
• any(leg(duty), leg.%is_international%) ; evaluates the leg expression
%is_international% for each leg in a duty. The expression is true if any of
the evaluations is true.
9
2. Theory
Which instance of a level that a new leg belongs to is handled by checking the new
leg against each level’s defining expression.
An important distinction should be made to avoid ambiguity when generating trips.
When regarding level instances, such as duty, generation may either result in a
continued instance or a new instance of that level.
Definition 2.2.1. New Instance: When the generator adds a leg that, according
to a level’s definition, can not be a part of an existing level instance, then a new
instance of that level is created. All expressions belonging to that level have a new
expression instance created and evaluated.
Definition 2.2.2. Continued Instance: When the generator adds a leg that can
be part of an existing level instance, the leg is added to the level instance. The
level instance containing the new leg is then considered a continued instance, or
continuation of the previous instance without the leg. All expression instances
which are affected by the added leg get evaluated to a new value.
Example: The generator tries to add a new leg. The starting time of the new leg is
12 hours later than the last leg of the last duty. According to duty’s level definition,
the new leg should be considered part of a new duty, so a new duty instance is
created containing the new leg.
As elaborated on in Section 2.2.5, rules are expressions - they too have levels and
instances. Furthermore, for a rule to be considered valid, then all existing instances
of that rule must be valid. Because of this, any rule describing legality on, for
example, “a duty” will be checked for all duty instances, relieving the rule writer
from thinking about when to apply rules.
Observation 2.2.1. The fact that expressions have multiple instances means that
any property that is proven about the expression is true for all instances of the
expressions. Conversely, in order to prove something about an expression, it has to
be true for all contexts.
Note: Many expressions only affect one instance of a level object, but it is also
possible to depend on other instances of the same level. For example, the rest time
before the beginning of a new duty is a value specific to one duty instance, but it
depends on two duties in direct succession.
This dynamic makes it possible for later instances to trigger a violation of an earlier
rule instance. However, no matter which instance the rule is violated for, it is
the last added leg that is of interest when deciding whether there may exist legal
continuations. This is true because of the order that solutions are found in, which
is elaborated on in Section 2.3.
10
2. Theory
The Pairing Generator wants to find a set of trips that are legal for an anonymous
crew member. As input data it has the flight schedule for aircrafts, which can be
regarded as a list of flights (referred to as “legs”), sorted by departure time. The legs
have many properties, some which are data that get supplied at runtime, and some
that are expressions computed from this data. This project and its implementation
will put special emphasis on starting time (departure) and ending time (arrival) of
flights, properties which affect the legality of many rules. Other important properties
of a flight include starting and ending airport.
To illustrate the set of possible solutions (trips), the search space is introduced.
Definition 2.3.1. Search Space: The search space of the Generator is a tree
structure whose nodes represent all possible trips of a flight schedule.
11
2. Theory
Rule Writer
Generator
Compiled Rules
The root is an empty node which represents an empty trip starting in some airport.
For each leg in the flight schedule starting in that airport, a child node is created.
In this step, these child nodes each represent a potential trip of length 1. Each of
these nodes has a child node created for every future compatible flight in the flight
schedule. Two flights are compatible if the upcoming flight starts in the same airport
that the previous flight ended, and the start of the upcoming flight is later than the
end of the previous flight.
Following this procedure for each node, the entire search space of a flight schedule
can be constructed. Figure 2.3 is an illustration of a small search space example.
Traversing down the search tree from the root, each child node represents adding a
leg to the trip in progress, so each node represents a unique trip in progress.
Note that in practice, there is a limit on how many child nodes are explored for
each node, as the number of nodes grows exponentially with each level in the tree
structure.
Proposition 2.3.1. All possible legal trips are represented by a node in the search
space.
Proof. Consider a trip t. Every trip is a sequence of legs which are compatible with
each other. Starting at the root of the search space, visit the child nodes representing
adding all the legs of t. The search space contain all legal leg-sequences, so either
the node representing t exists, or t is not legal.
Somewhat simplified, the Generator traverses the search space to find legal trips in
what can be described as depth first search with some heuristics. Interfacing with
12
2. Theory
a b c
d e f g h i j k l
Figure 2.3: An illustration of a search space. This example shows three potential
legs in each node, and has a search depth of 2.
The trip represented by node i consist of the two legs added in node b and i.
the rule system, the generator uses the Final Rules to prune the search tree, and
the Illegal Subchain Rules to decide if a trip is complete.
For a trip to be complete and legal, it has to evaluate all rules to true.
Definition 2.3.4. Subnodes: The subnodes of a node n is the set of all nodes
that are reachable by traversing downwards from n. This represents the set of all
possible continuations of the trip represented by node n. This is denoted as s(n).
Here are the formal definitions for the rule classes used in this project:
Definition 2.3.5. Final Rule: A rule r is a Final Rule if, when the rule is violated
for a node n, there exist no legal continuation of n. The following is true for a Final
Rule r:
∀n.¬r(n) → ¬∃ns ∈ s(n).r(ns )
13
2. Theory
if, when the rule is violated for a node n, there may exist a legal continuation of n.
The following is true for an Illegal Subchain Rule r.
∃n.¬r(n) ∧ ∃ns ∈ s(n).r(ns )
This proposition means that if it is proven that a rule is not a Final Rule then it
must be an Illegal Subchain Rule, and vice versa. Note however, that failing to find
proof of a property is not the same as proving that it is false.
In order to classify rules in this project, rules are categorized after the structure
of their defining expression. The intuition is that some patterns can be used to
categorize rules into subsets of Final Rules and Illegal Subchain Rules.
14
2. Theory
exhaustive search. Since the amount of possible trips grows exponentially with trip
length, this is extremely inefficient.
On the other hand, if an Illegal Subchain rule is erroneously classified as a Final
Rule and gets to prune the search space when there may exist legal continuations,
then many possible solutions are never found. Omitting solutions carries the risk of
omitting optimal solutions, leading to overall worse results.
The rules in Rave can be said to have two requirements in order to be useful. They
should be validated by all intended legal trips, and they must be written so that the
generator can find the legal trips by traversing the search space.
When translating regulations into Rave code, the first requirement is probably the
most straightforward. The rule should be able to decide whether a trip is legal.
The second requirement demands that the rule writer understands how the generator
works in order to write efficient rules, which is an additional mental overload.
The is_closed is sometimes misused or misunderstood, which can lead to faulty
classification. The consequences of misclassification may be severe, and furthermore
there is no obvious way to actually know that an error has been made.
The valid condition ev can be formulated in many ways, but if it is “dominated” by
is_closed then the rule will never prune search space.
15
2. Theory
%valid_condition% = %valid_condition% =
any(leg(duty), %is_deadhead%) ; any(leg(duty), %is_deadhead%) and
duty.is_closed ;
1 leg 2 legs 3 legs 1 leg 2 legs 3 legs
er F F _ er F F T
egv F T _ egv F F F
ecv F T _ evc
F T T
gen T F _ gen T T T
complete T F _ complete T F T
Figure 2.4: Truth tables visualizing the different implications on rule completeness
and generation on rule violation.
This rule should be able to allow the following example duty, d: Three legs, where the
second leg is deadhead. This can be modeled by the leg expression %is_deadhead%,
which is true for the second leg and false for the other two.
This rule needs a valid case in order to avoid being violated by every duty with
fewer than 3 legs.
Figure 2.4 illustrates the relation between rule expression legality, generation and
rule completeness. The rows show the boolean values of the evaluation of er , ev ,
whether generation should continue, and whether the trip is considered complete
according to the rule. For clarity, ev is split up into egv and ecv to illustrate the
different values that ev holds during generation and completeness checking. Notice
that in the left case egv and ecv are equal, since ev does not depend on is_closed.
The columns represent the sub-trips of duty d.
The difference between the two cases in column 2 effectively show the importance
of using is_closed correctly. In the left case, ev becomes valid when the second leg
is added, but er is violated, which means that the trip in progress violates this rule,
and the Generator will not look for continuations of this trip. As such, the solution
acquired by adding the third leg is never found.
In the right case, the trip containing the first two legs is not a legal (complete) trip,
16
2. Theory
but since the valid case depends on is_closed, the generator continues looking for
legal continuations anyway and can find the solution with three legs.
17
2. Theory
18
3
Methods
In this chapter, the approach and methods used to fulfill the project goals are de-
scribed. The Rave language with its compiler has been studied as well as parts of the
Pairing Generation system in order to formulate the model and theory discussed in
earlier chapters. This chapter will describe the formalia and implementation details
that were developed during this project, along with some of the reasoning behind
the decisions.
19
3. Methods
were implemented they were tested against some code examples, and the output was
examined and compared against the desired outcome. This helped identify where
rules were not strict enough, or when rules contained logic faults.
In the case that the current attributes were lacking to describe a pattern, the intro-
duction of newer attributes and attribute rules were considered.
One goal that was set early was to find rules that compared growing numerical
expressions against some limit, with defining expressions such as:
%time_sum% <= %limit% ;
20
3. Methods
%one% = 1 ;
%two% = 2 ;
When checking %one_plus_two% against the attribute rules, the structure of the
analyzed expression is considered to have the following shape:
%one_plus_two%
1 2
instead of the three separate trees:
%one_plus_two%
%one% %two%
%one% %two%
1 2
This makes expressions much easier to check against the attribute rules, and to
reason about.
21
3. Methods
Another simplification done in order to not write as many rules has been to consider
some attributes subsets of other attributes, and the proofs of subsets to also act as
proof of the superset. This can be compared to how polymorphism and inheritance
is handled in many programming languages. For example: Positive numbers is a
subset of Nonnegative numbers, so any proof that a number is positive also implies
that the number is nonnegative. The same reasoning is done for “value direction”
and “direction in legality” attributes which are described in Sections 3.2.3 and 3.2.4:
If something is proven to be increasing, that also implies that it is nondecreasing.
In general, attributes that describe what is not true have been more versatile than
those that guarantee something to be true, such as NonNegative in contrast to
Positive and NonDecreasing in contrast to Increasing. This is in part related
to the definition of Final rules, as what’s interesting to prove is that an expression
can not become legal again after being violated. Then it is enough to prove what
direction in legality is not possible, as explored in Section 3.2.4.
3.2.1 Range
These attributes describe the value range of expressions in very general terms. A
basic but important expression property is knowing whether its evaluation is positive
or negative. These properties are referred to as range attributes. Two central ones
are NonPositive and NonNegative.
Two other related attributes considered are IsZero and NonZero, but there were
no interesting findings relating to rule classification using these attributes in this
project.
Expression-types of interest
Some of the central expression-types to this attribute category are constant values,
arithmetic operations and sums.
• Constant values are simple. The value is clearly stated in code, so the range
of the expression is the range of the value.
• Sums are nonnegative if their subexpression is positive or nonnegative, and
they are nonpositive if their subexpression is negative or nonpositive.
• The range of arithmetic operations depend on both the operator and the
operands. This is discussed in the following section.
22
3. Methods
pp np pn nn
* p n n p
+ p ? ? n
- ? n p ?
< ? True False ?
Figure 3.1: The attributes of some arithmetic expressions knowing only the range
of the operands. The rows tell which operator is used and the columns show the
range of the operands, pp meaning two positive numbers, np meaning a negative
value as left operand and positive value as right operand, and so on. The cells
tell the range of the result of the operation. The bottom row also includes less
than-comparison with cells telling whether the comparison holds.
in the figure is the simple case of unary negation, which simply changes sign of the
value. Negation of a nonnegative value is nonpositive and vice versa.
This kind of reasoning about the value range of operations in code by looking at the
range of the operands has been discussed by Cousot and Cousot [11,12], and Chin et
al. describe their experiences with extending existing programming languages with
features such as this [8, 9].
Some results are uncertain as they may differ depending on if one of the operands is
larger than the other, such as subtraction of two positive numbers. This is unfortu-
nate since time durations, an important concept to trip legality, are typically com-
puted as end time − start time. Rave, like systems such as UNIX’s time stamp [28],
represent a moment in time to be a positive duration since some starting time.
Even though the range of the subtraction of two positive numbers is generally un-
known, if one of the operands is known to be larger than the other, the resulting
range can be known:
∀a, b ∈ R : a > b → (a − b) > 0
∀a, b ∈ R : a < b → (a − b) < 0
Using knowledge of the generation process and traversers in Rave, it is in many
cases possible to be certain of which of the times is largest without having direct
access to the data.
23
3. Methods
current
index keyword departure arrival
first departure ≤ <
first arrival ? ≤
prev departure < <
prev arrival < <
current departure = <
current arrival > =
next departure > >
next arrival > >
last departure ≥ ?
last arrival > ≥
Figure 3.2: Relations between arrival and departure keywords in combination with
traversers. Rows represent traverser and keyword combination, columns represent
the keyword that is compared against. The topmost left cell describes that the first
departure is always ≤ current departure.
first leg in that instance. Then departure ≯ f irst(arrival). This is not the case for
prev and next traversers, since when prev is evaluated where there exist no earlier
instance, that result is ignored.
Informally, this can be said to be true because sums are a sequence of additions,
and if the range is proven for the subexpression, then that range is true for all in-
stances of that expression. The count expression is a special case of sum with the
subexpression 1, so it is trivially considered nonnegative:
24
3. Methods
ConstVal Tells that an expression is defined by constant value in the Rave code
DepOnlyConst Tells that an expression only has constant subexpressions, and
can be considered constant
LevelConstant Tells that the value of an expression instance does not change in
continued instances
LevelDependent Tells that an expression instance may change in continued in-
stances
RefKeyw Tells if the expression is a keyword or reference to a keyword
ConstBranch For conditionals, tells if all outcomes are defined in terms of con-
stants
Expression-types of interest
Definitions, Constant values, Arithmetics, Traversers, Conditionals
25
3. Methods
e1 :a DepOnlyConst e2 :a DepOnlyConst
e1 + e2 :a DepOnlyConst
All expressions defined by a constant value are considered constant, and all constants
have constant dependencies. If all subexpressions of an arithmetic operation only
26
3. Methods
e1 :a LevelDependent
if e1 then e2 else e3 :a LevelDependent
27
3. Methods
A very central concept that these attributes were intended to apply to are how time
durations and accumulated time grows with generation.
Two ways to model this is to either:
• Take the ending time minus the starting time of a level instance
• Take the sum of time durations
The first case is handled using the same chronological reasoning about traversers
in 3.2.1.2. In this project’s model, this is simple, since starting times are considered
constant, and ending times are considered nondecreasing.
This can be captured by a rule such as:
e1 :a Ref KeywT ime e2 :a Ref KeywT ime
last(e1 ) − f irst(e2 ) :a N onDecreasing
Where Ref KeywT ime is a reference to a keyword describing a time. This is cur-
rently done with just Ref Keyw in the implementation, with some additional filter-
ing of which keywords are considered times.
The second case is referred to as Monotonic Sum, and that is described in the
following section.
e :a N onP ositive
sum(e) :a N onIncreasing
28
3. Methods
29
3. Methods
Of the mentioned rule patterns above, 1 and 3 are NiL, and 2 and 4 are NdL.
Important to note is that the attribute only describes one expression instance at a
time, while the legality of a rule depends on the truth value for all instances of the
rule. For example, consider a duty-level expression being nondecreasing in legality.
When generating trips and the expression eventually becomes true, then all instance
continuations will be true. When a new duty instance is created, the new instance
may be false. This highlights the ambiguity of referring to an expression without
specifying which instance of the expression is mentioned.
30
3. Methods
Looking at the pattern of the conjunction of all rule instances during generation, if
the rule is NiL the pattern of the trip is NiL. If the rule is NdL, the pattern of the
trip is potentially nonlinear.
Any expression with legality pattern that is not strictly “linear” has the attribute
NonFinal.
31
3. Methods
all(e) :a N onIncreasingInLegality
This is because as long as one of the operands in a sequence of disjunction is true, the
outcome will be true. The opposite holds for conjunction; a series of conjunctions
is false as long as one of the operands is false.
As is true for some other rules, with creative use of traversers it is possible to find
cases where these rules may be too general and as a consequence they might match
some expressions that should not hold these properties. This may be revised in
future iterations.
Similarly to (numerical) negation of a direction in value, (logical) negation of direc-
tion in legality implies the opposite direction of the negated expression.
e :a N onIncreasingInLegality
not e :a N onDecreasingInLegality
e :a N onDecreasingInLegality
not e :a N onIncreasingInLegality
Some patterns emerge when considering direction in legality and boolean connec-
tives. For the same direction, the rules are quite straightforward.
e1 :a N onIncreasingInLegality e2 :a N onIncreasingInLegality
e1 and e2 :a N onIncreasingInLegality
e1 :a N onIncreasingInLegality e2 :a N onIncreasingInLegality
e1 or e2 :a N onIncreasingInLegality
e1 :a N onDecreasingInLegality e2 :a N onDecreasingInLegality
e1 and e2 :a N onDecreasingInLegality
e1 :a N onDecreasingInLegality e2 :a N onDecreasingInLegality
e1 or e2 :a N onIncreasingInLegality
However, two different directions combined result in NonFinal behaviour. Two
examples that explain why “linearity” in legality can no longer be guaranteed are
illustrated in Figure 3.3. Consider the patterns that may emerge in continuations
of boolean expressions ψ and ϕ. In this example, ψ :a N onIncreasingInLegality
and ϕ :a N onDecreasingInLegality. As can be seen, the result of conjunction or
disjunction of two expressions with differing direction in legality can not always be
considered linear. However, an interesting observation is that for conjunction, after
ψ turns false there is no possible continuation that is true. The same can be said
in opposite direction for conjunction after ϕ turns true. Although the resulting
expression is nonlinear, some linear properties remain and the expression has a
“turning point”, after which the pattern is linear.
32
3. Methods
ψ T T F ψ T F F
ϕ F T T ϕ F F T
ψ∧ϕ F T F ψ∨ϕ T F T
Figure 3.3: NonFinal pattern from boolean connectives and direction in legality.
The rows represent different expressions and the columns represent instances, where
the column to the left is the first instance and the ones to the right are continuations.
e1 :a N onDecreasingInLegality e2 :a N onIncreasingInLegality
e1 and e2 :a N onF inal
e1 :a N onDecreasingInLegality e2 :a N onIncreasingInLegality
e1 or e2 :a N onF inal
Proof. A false NiL expression instance can have no continued instance that is true.
If no continuation can be true, then all subnodes in the search space are illegal. This
property matches the definition of a Final Rule.
Proof. A false NdL expression instance may have a continued instance that is true.
This can be true for no Final Rule so the rule must be an Illegal Subchain Rule.
33
3. Methods
34
4
Results
35
4. Results
The rule in question and the expressions it depends on looks like this in Rave:
/* The rule */
rule final_monotonic_sum =
%sum_duty_legtime% <= 10:00 ;
end
/* The sum */
%sum_duty_legtime% = sum(leg(duty), leg.%time%) ;
/* The legtime */
leg.%time% = leg.%arrival% - leg.%departure% ;
The AST of final_monotonic_sum as seen during attribute checking is illustrated
in Figure 4.1.
<=
sum 10 : 00
leg.%arrival% leg.%departure%
When checking this rule, the keyword nodes that define leg.%time% get checked
first. These are keywords known to represent times, and they have the attributes
NonNegative and RefKeyw. The subtraction is checked next, and the operands
are keywords with known relations. The result of the subtraction is NonNegative,
which means that the sum-traverser has the attribute NonDecreasing. The right
operand of the comparison is defined in terms of a constant, so that expression has
the attribute ConstVal. Finally, the comparison <= with subexpression attributes
NonDecreasing and ConstVal matches the rule for NonIncreasingInLegality.
Because the defining rule expression has this attribute, the rule is a Final Rule.
36
5
Conclusion
This chapter reflects on some of the findings of this project and lists some suggestions
for future work.
37
5. Conclusion
Can the semantic information developed during this project be of use for more than
rule classification, and what is interesting to continue developing?
Cire et al. [10] mention that semantic information of the computations in a domain
model is a good source for further optimizations.
The system in use at Jeppesen is very resource intensive and performance is impor-
tant. The semantic information provided by this project might not affect runtime
calculations directly, but it can be used in order to assure that the input has certain
properties, or behaves predictably. The more information that can be known about
a problem, the more opportunities for further developments are possible. Further-
more, since the semantic information is gathered before runtime, static analyses
does not impact performance.
Attributes and classification may be somewhat limited in what they can convey, but
they describe an important part of the studied system. Rule class and attributes
are static properties, but the existence of legal continuations is a dynamic property.
The point of Final Rules is to safely discard computations that can not result in a
better solution.
38
5. Conclusion
39
5. Conclusion
order to gather more specific type information that might not be possible to gather
at compile-time.
Since the attributes in this project have much in common with type systems, it
could be interesting to explore the possibilities of “hybrid” or “dynamic” attributes
that are affected by runtime conditions. It is noted that hybrid techniques such as
these do add some computational overhead, which is undesirable in such a resource
intensive task such as Pairing Generation. However, in some cases this trade-off
may be worth considering.
One interesting approach that was discussed during the developments of the project
is the possibility to filter the search space after a rule violation for potential valid
nodes without having to check every node against the rules. If one can pinpoint the
exact property or expression that caused the rule violation, it may be possible to
formulate exactly what properties that a valid continuation must satisfy. If this can
be expressed in a simple formula that can quickly decide if a leg holds this property,
perhaps this could save time when pruning the search space.
40
5. Conclusion
A very basic approach is “Illegal Subchain Rules should never prune search space”.
This is simply modeled by having ev defined as is_closed or some other form where
is_closed dominates the truth value during generation. However, a more complex
valid case may result in a rule that doesn’t break generation, but is still able to prune
search space. As mentioned in Section 3.2.4.2, some NonFinal expression have a
turning point where all continuations are linear in legality. Finding these patterns
to allow NonFinal rules to prune search space could be an interesting project.
5.4 Conclusion
This project has developed a model to describe semantic information about expres-
sions in Rave code. The information describes properties that the expressions hold
at runtime - during Pairing Generation.
This model has been implemented as part of Rave’s compilation process, and as a
result it has successfully been able to detect a set of rules with properties that can
be used to reason about the patterns in legality during generation. Some rules are
identified as Illegal Subchain Rules, and some as Final Rules that are guaranteed
not to be Illegal Subchain Rules.
The method of analyzing the code can be compared to type checking, using infer-
ence rules to propagate semantic information in the ASTs of the expressions in the
code. The inference rules look at expressions and the computed properties of its
subexpressions, if available. New rules and properties are easy to implement, and
more coverage is probably possible with continued work. However, inference rules
are somewhat simple and more advanced techniques may be interesting to utilize
when looking at future developments.
Revisiting the question: Is it possible to detect Illegal Subchain Rules at compile
time?
In order to answer this question, some reasoning was done in order to approximate
what would be needed to detect these rules. Some patterns were developed that
have successfully categorized a few rules to have certain properties. Some of these
properties, it has been reasoned, are only true for certain subsets of each of the rule
classes.
A few rules have been classified at compile time, and more can probably be found
by continued development of the methods. Though there is a limit to how much
can be deduced statically, some interesting future work with semantic analysis can
probably lead to interesting findings.
41
5. Conclusion
42
Bibliography
[1] Alfred V Aho, Ravi Sethi, and Jeffrey D Ullman. Compilers: principles, tech-
niques, and tools, volume 2. Addison-wesley Reading, 2007.
[2] Erik Andersson, Anders Forsman, Stefan E. Karisch, Niklas Kohl, and Allan
Sørensen. Problem solving in airline operations. OR/MS Today, April 2005.
[3] Erik Andersson, Efthymios Housos, Niklas Kohl, and Dag Wedelin. Crew pair-
ing optimization. Operations Research in the Airline Industry, pages 228–258,
1998.
[4] Bernhard Beckert and Reiner Hähnle. Reasoning and verification: State of the
art and current trends. IEEE Intelligent Systems, 29(1):20–29, 2014.
[5] Ana Bove, Peter Dybjer, and Ulf Norell. A brief overview of agda–a functional
language with dependent types. In International Conference on Theorem Prov-
ing in Higher Order Logics, pages 73–78. Springer, 2009.
[6] Maurice Bruynooghe. A practical framework for theabstract interpretation of
logic programs. The Journal of Logic Programming, 10(2):91–124, 1991.
[7] Cristian Cadar and Koushik Sen. Symbolic execution for software testing: three
decades later. Communications of the ACM, 56(2):82–90, 2013.
[8] Brian Chin, Shane Markstrum, and Todd Millstein. Semantic type qualifiers.
SIGPLAN Not., 40(6):85–95, June 2005.
[9] Brian Chin, Shane Markstrum, Todd Millstein, and Jens Palsberg. Inference
of user-defined type qualifiers and qualifier rules. In ESOP, volume 6, pages
264–278. Springer, 2006.
[10] Andre A Cire, John N Hooker, and Tallys Yunes. Modeling with metacon-
straints and semantic typing of variables. INFORMS Journal on Computing,
28(1):1–13, 2016.
[11] Patrick Cousot and Radhia Cousot. Abstract interpretation: a unified lat-
tice model for static analysis of programs by construction or approximation of
fixpoints. In Proceedings of the 4th ACM SIGACT-SIGPLAN symposium on
Principles of programming languages, pages 238–252. ACM, 1977.
[12] Patrick Cousot and Radhia Cousot. Abstract interpretation and application to
logic programs. The Journal of Logic Programming, 13(2-3):103–179, 1992.
[13] Patrick Cousot and Radhia Cousot. Abstract interpretation: past, present and
future. In Proceedings of the Joint Meeting of the Twenty-Third EACSL Annual
Conference on Computer Science Logic (CSL) and the Twenty-Ninth Annual
ACM/IEEE Symposium on Logic in Computer Science (LICS), page 2. ACM,
2014.
43
Bibliography
[14] Cormac Flanagan, K Rustan M Leino, Mark Lillibridge, Greg Nelson, James B
Saxe, and Raymie Stata. Extended static checking for java. SIGPLAN Not.,
37(5):234–245, May 2002.
[15] Christos Goumopoulos and Efthymios Housos. Efficient trip generation with
a rule modeling system for crew scheduling problems. Journal of Systems and
Software, 69(1):43–56, 2004.
[16] Curt A Hjorring and Jesper Hansen. Column generation with a rule modelling
language for airline crew pairing. In Proceedings of the 34th Annual Conference
of the Operational Research Society of New Zealand, pages 133–142, 1999.
[17] David Hovemeyer and William Pugh. Finding bugs is easy. ACM Sigplan
Notices, 39(12):92–106, 2004.
[18] Atoosa Kasirzadeh, Mohammed Saddoune, and François Soumis. Airline crew
scheduling: models, algorithms, and data sets. EURO Journal on Transporta-
tion and Logistics, 6(2):111–137, 2017.
[19] Sarmen Keshishzadeh and Arjan J. Mooij. Formalizing DSL semantics for
reasoning and conformance testing. In International Conference on Software
Engineering and Formal Methods, pages 81–95. Springer, 2014.
[20] Kenneth Knowles and Cormac Flanagan. Hybrid type checking. ACM Trans-
actions on Programming Languages and Systems (TOPLAS), 32(2):6, 2010.
[21] Niklas Kohl and Stefan E. Karisch. Airline crew rostering: Problem types,
modeling, and optimization. Annals of Operations Research, 127(1):223–257,
2004.
[22] Chris Lattner. LLVM. In The Architecture Of Open Source Applications. Cre-
ative Commons, 2011.
[23] Francesco Logozzo, Michael Barnett, Manuel A Fähndrich, Patrick Cousot, and
Radhia Cousot. A semantic integrated development environment. In Proceed-
ings of the 3rd annual conference on Systems, programming, and applications:
software for humanity, pages 15–16. ACM, 2012.
[24] Marjan Mernik, Jan Heering, and Anthony M Sloane. When and how to develop
domain-specific languages. ACM computing surveys (CSUR), 37(4):316–344,
2005.
[25] Benjamin C Pierce. Types and programming languages. MIT press, 2002.
[26] Aarne Ranta. Implementing programming languages. An introduction to com-
pilers and interpreters. College Publications, 2012.
[27] Yuriy Solodkyy, Jaakko Järvi, and Esam Mlaih. Extending type systems in a
library. In Second International Workshop on Library-Centric Software Design
(LCSD’06), page 55, 2006.
[28] Ken Thompson and Dennis M Ritchie. UNIX Programmer’s Manual. Bell
Telephone Laboratories, 1975.
[29] Markus Voelter. DSL Engineering: Designing, Implementing and Using
Domain-specific Languages. CreateSpace Independent Publishing Platform,
2013.
[30] Reinhard Wilhelm, Helmut Seidl, and Sebastian Hack. Compiler design: Syn-
tactic and semantic analysis. Springer Science & Business Media, 2013.
44
A
Appendix 1
This document contain some examples of Rave expressions and their computed
attributes.
%minus_one% = -1 ; /* NonPositive */
I
A. Appendix 1
Here are examples of the traversers sum and count. Both range and direction at-
tributes are inferred.
%max_time_duty% = /* NonNegative */
if %some_condition%
then 5:00
else 8:00 ;
%max_time2% = /* NonNegative */
if %condition%
then 12:00
else 8:00 ;
Depending on the variability of %condition%, it may be possible that max_time_duty2
is either a Final or Illegal Subchain Rule.
It may not always be obvious how %condition% is defined either, so it’s not safe to
assume too much. In this project, unless %condition% can be considered constant,
II
A. Appendix 1
%not_variable% = /* NonNegative */
if %unknown_condition%
then 20
else 20 ;
Even though %not_decreasing% always returns a nondecreasing expression, this is
not checked in the current implementation.
Also, because its not sure which expression is returned in %not_variable%, it’s
assumed that the expression is not constant even if the result is always the same.
III