Keywords

1 Introduction

In the field of business process modelling, there are currently two major modelling paradigms. In declarative notations such as such as DECLARE [2, 23], DCR graphs [8, 15], GSM [17] and CMMN [21] a model comprises the rules governing process execution. In imperative notations such as Petri- and Workflow nets [1, 3] and BPMN [22], a model comprises a more explicit representation of the set of possible executions.

The choice between the two paradigms is in essence a trade-off of conciseness for computational requirements. A declarative model may, via its rules, concisely represent a very large number of possible process executions: A DCR graph or a DECLARE model may represent a space of process executions exponentially larger than the graph itself. Many interesting problems of DCR graphs are consequently computationally hard [10].

In this paper, we explore the problem of determining whether given a model M and an activity a there exists a sequence of activity executions admitted by M which ends with a. We study this problem in the setting of DCR graphs, where activities are typically conflated with events. Here, the problem is called “Event reachability” [7, 10].

Solving this problem is practically important for model development. E.g., suppose we are constructing a DCR model of an insurance process involving an event “Payout reimbursement”, and we are interested in knowing whether it is possible to reach the “Payout reimbursement” event from a given state of the model.

Definition 1

Given a DCR graph G and an event e of G, we say that e is reachable from G if there exists a path \(e_1,\ldots ,e_n\) of event executions admitted by G such that \(e_n = e\). We call the path \(e_1,\ldots ,e_n\) a witness for reachability of e.

Existing solutions to this problem are either brute-force approaches and impractical on all but the smallest models [8, 9, 13] or approximations applicable only in special cases of graph structure [7, 10]. In this paper we investigate an alternative approximation using genetic algorithms [5] to heuristically find such paths, or give up if a time-bound expires. Genetic algorithms are viable because we can quantify how far off a path not reaching G is as a function of the number of constraints relating to G that have been satisfied at the end of the path. Presumably, fewer inhibiting constraints means we are closer to a solution. While genetic algorithms have previously been applied in other BPM subdomains, e.g., to process mining [4] and prediction [14, 19], we are unaware of other applications to reachability problems within the BPM domain.

We make in this paper the following contributions.

  1. 1.

    We provide a Genetic Algorithm for approximating DCR Event Reachability, including an implementation;

  2. 2.

    We report on a comparison with the existing brute-force solver reported in [8, 9] on both artificial and real-world models.

While the genetic algorithm is inferior to the brute-force one on examples constructed specifically to be difficult for it, it is remarkably effective on the real-world examples. It finds paths where the brute-force algorithm times out, and when both succeed, the genetic algorithm does so orders of magnitude faster than the brute-force one. We conclude that the genetic algorithm appears to be a practical approximation to Event Reachability in DCR graphs.

2 Dynamic Condition Response Graphs

DCR Graphs is a declarative notation for modelling processes superficially similar to DECLARE [23, 24] or temporal logics such as LTL [25]. The present paper makes two restrictions on DCR graphs: (1) we consider only finite executions, and (2) we assume each event is labelled by a unique activity. None of these restrictions are controversial, the latter is pervasive in the literature on DCR graphs. Because of the latter assumption we do not distinguish between (DCR) “events” and “activities” in the sequel, speaking only of “events”.

We give an example DCR graph in Fig. 1; formal definitions follow below. This example has five events, ABCD, and \( Goal \). Because there is a condition from A to D, A must be executed before we can execute D, and D must be executed before we can execute \( Goal \). Executing B excludes A, making A not executable and voiding the condition from A to D.

The event \( Goal \) is not initially enabled for execution: it is prevented by the condition from D. D is similarly not enabled, prevented by the condition from A. One way to reach \( Goal \) is thus the sequence \(A,D, Goal \). Alternatively, one may exploit the exclusion from C to void the condition from D, arriving at the sequence \(C, Goal \).

Since an event in a DCR graph can be executed multiple times, there are infinitely many ways to reach the event \( Goal \); e.g., the set of strings characterised by the regular expressions \(A^+D(A|D)^+ Goal \) or \((B|A|C)^*C Goal \).

Fig. 1.
figure 1

Example DCR graph

Previous approaches to event reachability in DCR graphs have simply explored the state space of a DCR model [8, 9]. Since the state of a DCR event is fully characterised by its three boolean attributes (executed, included, pending), an event can be in at most \({2}^3\) different states; a DCR graph with n events therefore maximally has \(2^{3n}\) distinct states. Not all of these will necessarily be reachable, however, experience suggests that for real-life graphs, the state space is large enough to prohibit brute force approaches [9, 13].

Definition 2

(DCR Graph [15]). A DCR graph is a tuple \((\mathsf {E}, \mathsf R, \mathsf {M})\) where

  • \(\mathsf {E}\) is a finite set of (activity labelled) events, the nodes of the graph.

  • \(\mathsf R\) is the edges of the graph. Edges are partitioned into five kinds, named and drawn as follows: The condition \((\mathrel {\rightarrow \!\!\bullet })\), response \((\mathrel {\bullet \!\!\rightarrow })\), inclusion \((\mathrel {\rightarrow \!\!+})\), exclusion \((\mathrel {\rightarrow \!\!\%})\) and milestone \({(\mathrel {\rightarrow \!\!\diamond })}\).

  • \(\mathsf {M}\) is the marking of the graph. This is a triple \((\mathsf {Ex},\mathsf {Re},\mathsf {In})\) of sets of events, respectively the previously executed \((\mathsf {Ex})\), the currently pending \((\mathsf {Re})\), and the currently included \((\mathsf {In})\) events.

The marking of a DCR graph is its run-time state: it records which events have been executed \((\mathsf {Ex})\), which are currently included \((\mathsf {In})\) in the graph, and which are required to be executed again in order for the graph to be accepting \((\mathsf {Re})\). We first define when an event is enabled.

Notation. When G is a DCR graph, we write, e.g., \(\mathsf {E}(G)\) for the set of events of G, \(\mathsf {Ex}(G)\) for the executed events in the marking of G, etc. In particular, we write \(\mathsf{M}(e)\) for the triple of boolean values \((e\in \mathsf {Ex},e\in \mathsf {Re},e\in \mathsf {In})\). We write \(\mathord {(\mathrel {\rightarrow \!\!\bullet }\!e)}\) for the set \(\{e'\in \mathsf {E}\mid e'\mathrel {\rightarrow \!\!\bullet }e\}\), write \(\mathord {(e\!\mathrel {\bullet \!\!\rightarrow })}\) for the set \(\{e'\in \mathsf {E}\mid e \mathrel {\bullet \!\!\rightarrow }e'\}\) and similarly for \(\mathord {(e\!\mathrel {\rightarrow \!\!+})}\), \(\mathord {(e\!\mathrel {\rightarrow \!\!\%})}\) and \(\mathord {(\mathrel {\rightarrow \!\!\diamond }\!e)}\).

Definition 3

(Enabled events [15]). Let \(G=(\mathsf {E}, \mathsf R, \mathsf {M})\) be a DCR graph, with marking \(\mathsf {M}= (\mathsf {Ex},\mathsf {Re},\mathsf {In})\). An event \(e \in \mathsf {E}\) is enabled, written \(e\in {\mathsf {enabled}(G)}\), iff (a) \(e \in \mathsf {In}{}\) and (b) \(\mathsf {In}{}\cap \mathord {(\mathrel {\rightarrow \!\!\bullet }\!e)} \subseteq \mathsf {Ex}\) and (c) \((\mathsf {Re}{}\cap \mathsf {In})\cap \mathord {(\mathrel {\rightarrow \!\!\diamond }\!e)} = \emptyset \).

That is, enabled events (a) are included, (b) their included conditions have been executed, and (c) they have no included milestones with an unfulfilled response.

Executing an enabled event e of a DCR Graph results in a new marking where (a) e is added to the set of executed events, (b) e is removed from the set of pending response events, (c) the responses of e are added to the pending responses, (d) the events excluded by e are removed from included events, and (e) the events included by e are added to the included events.

From this we can define the language of a DCR Graph as all finite sequences of events ending in a marking with no event both included and pending.

Definition 4

(Language of a DCR Graph [15]). Let \(G_0=(\mathsf {E}, \mathsf R, \mathsf {M})\) be a DCR graph with marking \(\mathsf {M}_0 = (\mathsf {Ex}_0,\mathsf {Re}_0,\mathsf {In}_0)\). A trace of \(G_0\) is a finite sequence of events \(e_0,\ldots ,e_n\) such that for \(0\le i\le n\), (a) \(e_i\) is enabled in the marking \(M_i=(\mathsf {Ex}_i,\mathsf {Re}_i,\mathsf {In}_i)\) of \(G_i\), and (b) \(G_{i+1}\) is a DCR Graph with the same events and relations as \(G_i\) but with marking \((\mathsf {Ex}_{i+1},\mathsf {Re}_{i+1},\mathsf {In}_{i+1})=(\mathsf {Ex}_{i}\cup \{e_i\},(\mathsf {Re}_{i}\backslash \{e_i\})\cup \mathord {(e_i\!\mathrel {\bullet \!\!\rightarrow })}, (\mathsf {In}_{i}\backslash \mathord {(e_i\!\mathrel {\rightarrow \!\!\%})}) \cup \mathord {(e_i\!\mathrel {\rightarrow \!\!+})})\).

We call such a trace accepting if for all \(0\le i\le n\) we have \(\mathsf {Re}_{i+1}\cap \mathsf {In}_{i+1}=\emptyset \). The language \(\mathop {\mathsf {lang}}({G_0})\) of \(G_0\) is then the set of all such accepting traces.

3 Genetic Algorithms

Genetic algorithms (GA) imitate natural selection. Solutions to a problem are structured as individuals with one or more chromosomes, each consisting of genes. For the present problem, one chromosome per individual will suffice. Initially, in generation 1, the individuals comprise a set of randomly generated chromosomes. Individuals are ranked by their fitness, based on how good the solution encoded in their chromosome is. We then select two or more individuals (parents) and create a child whose chromosome is the crossover of the parents chromosomes. We create children until we reach a specified number of individuals, commonly double the initial population. At this point we proceed to kill off the worst individuals until we reach our initial population size. The remaining individuals constitute generation 2 of individuals.

This process is repeated until a stop condition is met. Common stop conditions are: a solution is found, a timeout is reached or n number of generation have been generated. When it is unknown whether or not a solution is optimal, we can also set an optimisation threshold oT and run the algorithm until the best individual improves less than oT in some amount of generations.

To implement a GA, we will need to implement the main building blocks of any genetic algorithm: a fitness function, a selection function, a crossover function and a mutation function. However, first we have to decide how to encode the problem as genes in a chromosome. If our problem is to construct a bit string of length 6 with the maximum number of 1’sFootnote 1, our genes will be either a 1 or a 0, and our chromosome will be a list or 1’s and 0’s of length 6 as in Fig. 2.

Fig. 2.
figure 2

A possible instantiation of a chromosome

Fitness Function. The fitness function of a GA takes an individual as input and returns a value based on how good the solution in its chromosome is. A good fitness function for a GA that constructs a bit string with the maximum number of 1’s simply returns the number of ones in the string. Such a fitness function would return a score of 2 for the chromosome in Fig. 2.

Selection Function. We select individuals at random, with the probability of selecting a particular individual weighed by its fitness. We have a greater chance of choosing individuals with better fitness score, but occasionally we get a worse individual, which is beneficial for escaping local maximums in optimisation algorithms [5]. Some selection functions always retain the top 5–10% of individuals, the elite. This ensures that the top individuals never get worse.

Crossover Function. A crossover function in most cases takes two individuals (it may take an arbitrary number) as input and returns a new individual that is the child of the two parents. The crossover function depends greatly on which problem we are solving, and is sometimes trial and error. Crossovers are usually performed by splitting both parents’ chromosome at one or more point and gluing the parts from both parents together.

Mutation Function. The last of the main functions used in a GA is the mutation function. This function is called from inside the crossover function before the newly created child is returned. The mutation function changes one or more genes with a certain mutation probability.

4 GA to Solve Reachability in DCR Graphs

To solve reachability in DCR graphs, we must find a sequence of events to execute before the goal event is in an executable state, so a gene will be the id of an event to execute. A chromosome will be a list of these ids.

Fitness Function. Suppose we are trying to execute an event G, the “Goal” event. Looking at Definition 3, we know that an event G can be executed if:

  1. 1.

    G is included.

  2. 2.

    All events that have a condition to G have been executed or excluded.

  3. 3.

    All events that have a milestone to G are excluded or are not pending.

Therefore, we score the execution of an event X when it has:

  1. 1.

    an include to G. This score is only considered if G is excluded.

  2. 2.

    a condition to G. This score is only considered if X has not been executed previously. An event Y that has a condition to X must also be given a score and so on.

  3. 3.

    a milestone to G. This score is only considered if the X is pending. An event Y that has a milestone to X must also be given a score, in the same way as the condition above.

  4. 4.

    an exclude relation to events that would have given some score according to 2 or 3 if executed.

(1) is easy to check. Before we consider (2), (3) and (4) it is helpful to recall the example graph in Fig. 1. Here, it is more beneficial to execute C than B: Executing C instantly enables execution of Goal, while executing B also requires executing D to enable execution of Goal. The fitness function must therefore reflect the distinction that C is better to execute than B.

We achieve (2) and (3) by performing a Breadth-First Search (BFS) in the graph of events and relations from G following only condition and milestone relations and store a score on the events we encounter and return that score in the fitness function when the event is executed. We decrease the score the further we are from G. The score stored on events that should be scored according to (2) or (3) is \(1\over \text {depth of BFS}\). This ensures that the execution of an events that is closer to G returns a higher fitness score than an event further away.

We achieve (4) by giving events that exclude other events the score of the event that they exclude, if the excluded event has a score according to (2) or (3). To be eligible for a score the event that becomes excluded must fulfil the requirements e.g. for condition score that the event has never been executed and for milestone score that the event is pending.

The events in the graph in Fig. 1 would be scored the following way. D has a condition to Goal and will get a score of 1. Executing C will exclude D, so C will also get a score of 1. A however, is two conditions away from Goal, and will only get a score of \(1\over {2}\). B excludes A and will therefore also get a score of \(1\over {2}\).

The selection function simply distributes probabilities according to fitness, then selects a parent randomly.

The crossover function is implemented by choosing alternating genes from the two selected parents. If we reach the end of one parents chromosome, we just append the rest of the genes of the second parent to the child’s chromosome. This is equivalent to having a crossover point after every geneFootnote 2.

The mutation function has three equiprobable mutations:

  1. 1.

    Change a gene (execution) to another random execution value.

  2. 2.

    Append a gene with a random value to the end of the chromosome.

  3. 3.

    Remove a gene at a random position in the chromosome.

These mutations allow chromosomes to contain genes that represent executions of events that are not executable.

The last parameters of the genetic algorithm are the mutation probability, which is set to \(10\%\) (we tried \(5\%\) with slightly worse results), the initial population size which is set to 50 and the starting length the individuals’ chromosomes which is set to 2. The rather high mutation probability is necessary, as difficult to find paths require more than 2 preceding executions, so we must force the chromosomes to grow rather often.

The low initial population size allows us to generate new generations quicker. Higher initial population sizes were tried, but generally performed worse. The starting length the individuals’ chromosomes is set low, as the algorithm provides better solutions faster for events where few preceding executions are necessary.

Post-processing. The mutation function above allows paths that actually cannot execute under DCR semantics. We remove such events before returning a solution, and they do not contribute to the fitness score; however, they are important because they may become legal after crossover or mutation.

5 Experiments

We evaluated the genetic algorithm on six real-world models and three artificial ones, comparing results with those of the brute-force state exploration tool dcri [8, 9].

Table 1. Overview of graphs used in experiments

We list the 9 models in Table 1. The real-world models were kindly provided by Exformatics A/S and DCR Solutions A/S, except for BigBelt, which was the result of a case study [11]. We note that the BigBelt model is the largest publicly DCR model available, and that the Dreyer model is known to be unfeasible for the dcri tool [13]. The artificial models “hard” and “harder” were constructed by dcri authors and pre-date the present study. Finally, we are grateful to Tijs Slaats for suggesting the model “milestones” as a model that has minimal paths exponentially larger than the model itself.

The tests were run on a machine equipped with an Intel Core i7-6700 processor. The genetic algorithm used the same amount of memory around 18–20 MB on all models whereas the dcri tools memory footprint depends on the state-space of a model (\(\sim \)5 GB for the model “harder”). Because the GA is non-deterministic, reported timings are the average over 100 queries; because dcri is deterministic, reported timings are the result of a single run.

Table 2. Comparison of results, Real-world models

Real-world model timing results are reported in Table 2. For both algorithms, on each model, we ran the algorithm on each event of the modelFootnote 3, with a timeout of 10 s per event. For those graphs where one or more event was not reached, we reran all searches with a timeout of 60 s per event.

Each row in the table reports the aggregate time consumption of consecutively searching for each event in the model. The columns in the table are:

  1. 1.

    “Total”, the total time spent searching for paths for each event in the graph.

  2. 2.

    “Max”, the maximum time spent on a single event (i.e., on the most difficult event); or DNF (Did Not Finish) in case of timeouts.

  3. 3.

    “Avg.”, the average time spent per event.

  4. 4.

    “Misses”, the percentage of queries failing to find a path.

When the 10-s timeout search succeeded on all events, we did not repeat the search with a 60-s timeout, hence the cells containing “–”.

Note that whereas dcri deterministically either always finds a path or never does, the GA randomly finds or fails to find certain paths. Also note that for GA, “Total” is the average over all runs, whereas “Max” is maximum, so it is possible for “Max” to be larger than “Total”. Finally, we note that the GA does not consistently miss: Every event was reached in the majority of runs.

Artificial model timing results are reported in Table 3. We ran both tools with timeouts of 50 min, searching only for a designated goal event.

Table 3. Comparison of results, Artificial models (50 m timeout)

6 Discussion

Real-World Models. For all of these, the GA finds solutions more often than dcri.

  1. 1.

    With the 10-s timeout, of the 6 models, the GA fails on 2, missing 6% and 0.2%; whereas dcri fails 4, missing 16%, 35%, 41%, and 48%.

  2. 2.

    With the 60-s timeout, GA fails on 1 model, missing only 0.06% on Dreyer; whereas dcri fails on 2 models, missing ca. 25% of events on Dreyer and BigBelt.

On all but the “Union” model, the GA is also faster:

  1. 1.

    Total time for the GA is between 4 and 12 times smaller than dcri at the 10-s timeout. It is always an order magnitude smaller than dcri.

  2. 2.

    Average time for the GA is between 4 and 594 times smaller than dcri at the 10-s timeout.

Timing results differ on Union likely because the model is small enough to be in the “sweet spot” for a brute force solution. We see in Table 1 that Union is indeed the smallest model, both in terms of number of events and number of relations. In particular, it has an order of magnitude fewer relations than other models, and so likely has a much smaller state-space.

In summary, our data indicates that for real-world models, the GA is universally better on all but very small models.

Artificial Models. As expected, dcri performed very poorly on the models “hard” and “harder” designed to have large state spaces, solving “hard” after ca. 16 min and failing to terminate on “harder”. Perhaps surprisingly, the GA performs excellently on both, solving either in substantially less than a second.

The “milestones” model consists of 8 events \(\{A_1\dots A_8\}\). Each event has a milestone to all events with a higher number and a response to all events with a lower number. This results in an execution pattern where the executions necessary to execute \(A_{n-1}\) must be repeated to execute \(A_n\); it easy to prove by induction that in a graph of this shape, the shortest path to executing \(A_k\) has length \(2^{k-1}\), so executing \(A_8\) requires a path of length 128.

However, the state-space of this model is tiny: Each event in the graph can be in only 3 distinct states, namely “not executed and pending”, “executed and not pending” or “executed and pending”; with 8 events, it follows that the state-space contains at most a tiny \(3^8=6461\) possible states, making it easy to solve for dcri. The GA struggles with this model, only finding a path in ca. 4.2 min. To see why, note that the longer the shortest path, the more often the GA has to randomly find a good execution. Moreover, the infinite execution pattern \((A_1 A_2)^+ \) will return a higher fitness score the more times it is run.

The paths discovered by the GA in the real-world graphs is generally in the single digits for BigBelt and around 20 for Dreyer. However, these graphs contain many more events and relations—cf. Table 1—and therefore presumably exponentially more states to explore, making them more challenging for dcri.

GAs are not an exact science: a small change to the fitness, mutation or crossover function might substantially change results. We have found suitable parameters for these functions by trial and error, and it is likely that a more efficient implementation can be found. Furthermore smaller optimisations can possibly make the performance of the algorithm better. One example is to implement the events as bit vectors as done in other DCR engines [18].

Shortest Paths. We note that our GA algorithm does not necessarily find the shortest path; not even typically. For example, refer to the graph in Fig. 1: The current fitness function would give executions \(\langle B,\;D\rangle \) the combined condition scores of A and D while executing C only would give the condition score of D. Therefore in the eyes of the GA, the path \(\langle B,\;D,\;Goal\rangle \) is better than \(\langle C,\;Goal\rangle \).

7 Conclusion

We have implemented event reachability for DCR graphs using a Genetic Algorithm, and evaluated the resulting algorithm against an existing brute-force solutions. On medium-sized real-world models and up, the Genetic Algorithm both finds a solution more often, and does so more quickly.

Future Work. The event reachability problem can be captured directly in DECLARE by the constraint \(\mathsf {Existence}(1,G)\), however, it is unclear that a computationally feasible means of checking consistency of a model with that constraint exists. As such, it seems promising to apply the ideas of the present paper also to DECLARE.

For practical applications, an even stronger algorithm may be obtained by combining a brute-force algorithm with the genetic approach, in an effort to find shortest paths, and to discover the major variations of possible paths.

Finally, there is room to improve existing brute-force solutions by employing traditional model checking techniques [6], e.g., symbolic verification techniques.