# Celonis Product Documentation

##### CONFORMANCE
###### Description

CONFORMANCE flags activities whether they are conformant with the given model. READABLE returns violation descriptions in English. To use the model from the conformance checker sheet, the CONFORMANCE query can be written to a variable.

This operator matches cases against a Petri net. It flags activities which are violating the Petri net defined behavior. This is achieved with a Petri net based token replay with backtracking and error repair. This allows to use the same activity multiple times as places in the Petri net.

If the READABLE function is invoked, the flags are translated into violation descriptions in English.

A common use case is to generate the Petri net from a BPMN model and use it as input for the conformance checker.

### Warning

Computation Times In some settings, this operator may require excessive CPU time. If the execution time exceeds 10 minutes, the execution is stopped and an according error is reported.

###### Syntax
 CONFORMANCE ( activity_table.string_column, [ places ], [ transitions ], [ edges ], [ mapping ], [ start_places ], [ end_places ] )

• activity_table.string_column: A string column of an activity table. Usually, the activity column of an activity table is used.

• places: List of places in the Petri net.

• transitions: List of transitions in the Petri net.

• edges: List of edges from places to transitions and transitions to places.

• mapping: Mapping of activity names to transitions.

• start_places: List of start places of the Petri net.

• end_places: List of end places of the Petri net.

CONFORMANCE accepts an activity column and a description of a process model, as a Petri net, as input. The first part of the model description is a list containing all places of the Petri net, each specified by a unique string ID. It is followed by a similar list of all transitions. The third part of the model description is a list of flow relations, where each flow relation is specified as a pair of the source place and the target transition or a pair of the source transition and the target place, respectively. After that, a list of value pairs defines the mapping of activity names to the related transitions. The first value in such a pair is an activity name as a string while the second value is the ID of a transition which must be defined in the list of transitions. The last two parts of the model description are the lists of start and end places, respectively. Both lists consist of place IDs which must be specified in the first part of the model description.

 READABLE ( conformance_query )

• conformance_query: The CONFORMANCE query (see above). Can also be retrieved from the model in the conformance checker sheet using a variable.

###### CONFORMANCE

The CONFORMANCE operator replays the activities' names from the input column on the process model. As a result, it adds a temporary column of type INT to the activity table. The value of a row in this temporary column indicates if there is a conformance issue or not. Also, the type of violation and the related activities in the process model are encoded in this value, in the following way:

• R = 0: Activity matches the Petri net.

• R < 0: Activity is not mapped to a transition. Violating transitions are always determined based on existing activities, e.g. undesired activities are not taken into account in this violation type.

• R > 0: A positive result number describes which activity step violates the Petri net. The 32 most significant bits of the result value describe the source activity and the other 32 bits the target activity of the violating step.

• R = 2147483647: Case ended before reaching an end place.

• R = 2147483646: Could not evaluate the case because the model requires too much computation power. In most cases, such models can be transferred into equivalent, simpler models.

By summing up the absolute conformance values of a case using a PU_SUM, it can be determined if a case conforms (the sum is 0 in that case) or not (the sum is larger than 0).

As the integer encoding is not suitable for the end-user, the CONFORMANCE operator can be wrapped in the READABLE command. If there is a violation, this will translate the encoding into a message explaining the violation:

• Conforms: Activity matches the Petri net.

• X is an undesired activity: Activity is not mapped to a transition.

• X is followed by Y: The transition is not found in the specified Petri net. Violating transitions are always determined based on existing activities, e.g. undesired activities are not taken into account in this violation type.

• X is executed as start activity: Case starts with the false activity.

• Incomplete: Case ended before reaching an end place.

• Too complex: Could not evaluate the case because the model requires too much computation power. In most cases, such models can be transferred into equivalent, simpler models.

###### NULL handling

A NULL value conforms with any Petri net, hence a match is returned.

###### Examples

[1]

In this simple example the case fully matches the Petri net, which is indicated for all its rows of the output:

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

1

'B'

Fri Jan 01 2016 02:00:00.000

Result

Column1 : int

Column2 : string

0

'Conforms'

0

'Conforms'

[2]

In this simple example a non matched activity (C) is part of the case:

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

1

'C'

Fri Jan 01 2016 02:00:00.000

Result

Column1 : int

Column2 : string

0

'Conforms'

-2

'C is an undesired activity'

[3]

In this example, conformance is calculated on case level, i.e. for each case, we return if the case conforms (if there is no violation) or not (the case has at least one violation). This can be done by summing up all absolute violation values using PU_SUM and evaluating the result in a CASE WHEN. When the result of the PU_SUM equals 0, the case does not contain any violation and therefore conforms with the model. This approach can be used to calculate the number of conforming or non-conforming cases. The condition of the CASE WHEN can also be used in a FILTER statement to filter on conforming or non-conforming cases.

Query

Column1

         "Cases"."Case"


Column2

         CASE WHEN PU_SUM ( "Cases" , ABS ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) ) ) = 0 THEN 'Case conforms' ELSE 'Case does not conform' END


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

2

'A'

Fri Jan 01 2016 02:00:00.000

2

'C'

Fri Jan 01 2016 03:00:00.000

3

'A'

Fri Jan 01 2016 04:00:00.000

3

'B'

Fri Jan 01 2016 05:00:00.000

Cases

Case : int

1

2

3

Foreign Keys

 Cases.Case Activities.Case

Result

Column1 : int

Column2 : string

1

'Case does not conform'

2

'Case does not conform'

3

'Case conforms'

[4]

In this simple example the second A activity violates the Petri net:

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

1

'A'

Fri Jan 01 2016 02:00:00.000

Result

Column1 : int

Column2 : string

0

'Conforms'

4294967297

'A is followed by A'

[5]

In this simple example the case doesn't violate the Petri net but stops in the middle of the case:

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

2

'A'

Fri Jan 01 2016 02:00:00.000

2

'B'

Fri Jan 01 2016 03:00:00.000

Result

Column1 : int

Column2 : string

2147483647

'Incomplete'

0

'Conforms'

0

'Conforms'

[6]

In this simple example the start activity B violates the Petri net:

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'B'

Fri Jan 01 2016 01:00:00.000

1

'A'

Fri Jan 01 2016 02:00:00.000

1

'B'

Fri Jan 01 2016 03:00:00.000

Result

Column1 : int

Column2 : string

57423712747522

'B executed as start activity'

0

'Conforms'

0

'Conforms'

[7]

In this example, activity C is not mapped to any transition on this Petri Net:

Therefore it is marked as undesired and ignored by the conformance algorithm. After ignoring C, the variant becomes A, A and therefore the violation \"A is followed by A\" is detected.

Query

Column1

         CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] )


Column2

         READABLE ( CONFORMANCE ( "Activities"."Activity" , [ "P_0" "P_1" "P_2" ] , [ "T_01" "T_12" ] , [ [ "P_0" "T_01" ] [ "T_01" "P_1" ] [ "P_1" "T_12" ] [ "T_12" "P_2" ] ] , [ [ 'A' "T_01" ] [ 'B' "T_12" ] ] , [ "P_0" ] , [ "P_2" ] ) )


Input

Output

Activities

Case : int

Activity : string

Timestamp : date

1

'A'

Fri Jan 01 2016 01:00:00.000

1

'C'

Fri Jan 01 2016 02:00:00.000

1

'A'

Fri Jan 01 2016 03:00:00.000

Result

Column1 : int

Column2 : string

0

'Conforms'

-2

'C is an undesired activity'

4294967297

'A is followed by A'