custom_function

This file contains all the customizable functions, which the user can define, and which are called by the simulator in the specific steps.

The following table describes the case and inter-case features that can be used as input from a predictive model.

Feature Description
id_case Case id of the trace to which the event belongs.
activity Represents the next activity to be performedg.
enabled_time Timestamp of when the activity requests the role to be executed.
start_time Timestamp of when the activity starts to run.
end_time Timestamp of when the activity ends to run.
role Designated role to perform the next activity.
resource Role resource available to perform the activity.
wip_wait Represents the number of traces running in the simulation before the waiting time.
wip_start Represents the number of traces running in the simulation once an available resource is obtained to run the activity.
wip_end Represents the number of traces running in the simulation at the end of the activity execution.
wip_activity Represents the number of events running in the simulation that perform the same activity, once an available resource is obtained.
ro_total The percentage of occupancy in terms of resources in use for the roles defined in the simulation.
ro_single The percentage of occupancy in terms of resources in use for the role defined for the next activity.
queue Represents the length of the queue for the required resource.
prefix List of activities already performed.
attribute_case Attributes defined for the trace.
attribute_event Attributes defined for the next event to be executed.
  1'''
  2This file contains all the customizable functions, which the user can define,
  3and which are called by the simulator in the specific steps.
  4
  5The following table describes the case and inter-case features that can be
  6used as input from a predictive model.
  7
  8| Feature      | Description  |
  9|:------------:|:-------------------------- |
 10| id_case | Case id of the trace to which the event belongs. |
 11| activity | Represents the next activity to be performedg. |
 12| enabled_time | Timestamp of when the activity requests the role to be executed. |
 13| start_time |  Timestamp of when the activity starts to run.   |
 14| end_time |   Timestamp of when the activity ends to run.    |
 15| role |   Designated role to perform the next activity.   |
 16| resource |  Role resource available to perform the activity.   |
 17| wip_wait | Represents the number of traces running in the simulation before the waiting time.  |
 18| wip_start |  Represents the number of traces running in the simulation once an available resource is obtained to run the activity. |
 19| wip_end | Represents the number of traces running in the simulation at the end of the activity execution. |
 20| wip_activity |  Represents the number of events running in the simulation that perform the same activity, once an available resource is obtained.   |
 21| ro_total |    The percentage of occupancy in terms of resources in use for the roles defined in the simulation.   |
 22| ro_single |   The percentage of occupancy in terms of resources in use for the role defined for the next activity.     |
 23| queue |  Represents the length of the queue for the required resource.  |
 24| prefix |  List of activities already performed.  |
 25| attribute_case |  Attributes defined for the trace.      |
 26| attribute_event |  Attributes defined for the next event to be executed.   |
 27
 28'''
 29
 30from statsmodels.tsa.ar_model import AutoRegResults
 31from utility import Buffer
 32import random
 33import pickle
 34from datetime import datetime
 35import os
 36
 37
 38def case_function_attribute(case: int, time: datetime):
 39    """
 40        Function to add one or more attributes to each trace.
 41        Input parameters are case id number and trace start timestamp and return a dictionary.
 42        For example, we generate a trace attribute, the requested loan amount, to simulate the process from the BPIChallenge2012A.xes log.
 43    """
 44    return {"AMOUNT": random.randint(100, 99999)}
 45
 46
 47def event_function_attribute(case: int, time: datetime):
 48    """
 49        Function to add one or more attributes to each event.
 50        Input parameters are case id number and trace start timestamp and return a dictionary.
 51        In the following example, we assume that there are multiple bank branches where activities
 52        are executed by day of the week. From Monday to Wednesday, activities are executed in the
 53        Eindhoven branch otherwise in the Utrecht one.
 54    """
 55    bank = "Utrecht" if time.weekday() > 3 else "Eindhoven"
 56    return {"bank_branch": bank}
 57
 58
 59def custom_arrivals_time(case):
 60    """
 61    Function to define a new arrival of a trace.
 62    For example, we used an AutoRegression model for the *arrivals example*.
 63    """
 64    loaded = AutoRegResults.load('../example/example_arrivals/arrival_AutoReg_model.pkl')
 65    return loaded.predict(case+1, case+1)[0]
 66
 67
 68def custom_processing_time(buffer: Buffer):
 69    """
 70    Define the processing time of the activity (return the duration in seconds).
 71    Example of features that can be used to predict:
 72
 73    ```json
 74            {
 75                "id_case": 23,
 76                "activity": "A_ACCEPTED",
 77                "enabled_time": "2023-08-23 11:14:13",
 78                "start_time": "2023-08-23 11:14:13",
 79                "end_time": "2023-08-23 11:20:13",
 80                "role": "Role 2",
 81                "resource": "Sue",
 82                "wip_wait": 3,
 83                "wip_start": 3,
 84                "wip_end": 3,
 85                "wip_activity": 1,
 86                "ro_total": [0.5, 1],
 87                "ro_single": 1,
 88                "queue": 0,
 89                "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED"],
 90                "attribute_case": {"AMOUNT": 59024},
 91                "attribute_event": {"bank_branch": "Eindhoven"}
 92            }
 93    ```
 94    """
 95    input_feature = list()
 96    input_feature.append(buffer.get_feature("wip_start"))
 97    input_feature.append(buffer.get_feature("wip_activity"))
 98    input_feature.append(buffer.get_feature("start_time").weekday())
 99    input_feature.append(buffer.get_feature("start_time").hour)
100    loaded_model = pickle.load(
101        open(os.getcwd()+'/example/example_process_times/processing_time_random_forest.pkl', 'rb'))
102    y_pred_f = loaded_model.predict([input_feature])
103    return int(y_pred_f[0])
104
105
106def custom_waiting_time(buffer: Buffer):
107    """ Define the waiting time of the activity (return the duration in seconds).
108    Example of features that can be used to predict:
109    ```json
110    {
111        "id_case": 15,
112        "activity": "A_PARTLYSUBMITTED",
113        "enabled_time": "None",
114        "start_time": "None",
115        "end_time": "None",
116        "role": "Role 2",
117        "resource": "None",
118        "wip_wait": 21,
119        "wip_start": -1,
120        "wip_end": -1,
121        "wip_activity": 1,
122        "ro_total": [0.5, 1],
123        "ro_single": 1,
124        "queue": 13,
125        "prefix": ["A_SUBMITTED"],
126        "attribute_case": {"AMOUNT": 18207},
127        "attribute_event": {"bank_branch": "Eindhoven"}
128
129    }
130    ```
131    """
132    input_feature = list()
133    buffer.print_values()
134    input_feature.append(buffer.get_feature("wip_wait"))
135    input_feature.append(buffer.get_feature("wip_activity"))
136    input_feature.append(buffer.get_feature("enabled_time").weekday())
137    input_feature.append(buffer.get_feature("enabled_time").hour)
138    input_feature.append(buffer.get_feature("ro_single"))
139    input_feature.append(buffer.get_feature("queue"))
140    loaded_model = pickle.load(
141        open(os.getcwd() + '/example/example_process_times/waiting_time_random_forest.pkl', 'rb'))
142    y_pred_f = loaded_model.predict([input_feature])
143    return int(y_pred_f[0])
144
145
146def custom_decision_mining(buffer: Buffer):
147    """
148    Function to define the next activity from a decision point in the Petri net model.
149    For example, we used a Random Forest model for the decision mining example.
150
151    Example of features that can be used to predict:
152    ```json
153        {
154            "id_case": 43,
155            "activity": "A_FINALIZED",
156            "enabled_time": "2023-08-24 16:24:29",
157            "start_time": "2023-08-24 19:37:31",
158            "end_time": "2023-08-24 20:03:34",
159            "role": "Role 2",
160            "resource": "Sue",
161            "wip_wait": 16,
162            "wip_start": 4,
163            "wip_end": 4,
164            "wip_activity": 2,
165            "ro_total": [0.0, 1],
166            "ro_single": 1,
167            "queue": 15,
168            "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED", "A_ACCEPTED"],
169            "attribute_case": {"AMOUNT": 86061},
170            "attribute_event": {"bank_branch": "Eindhoven"}
171
172        }
173    ```
174    """
175    input_feature = list()
176    prefix = buffer.get_feature("prefix")
177    input_feature.append(1 if 'A_PREACCEPTED' in prefix else 0)
178    input_feature.append(1 if 'A_ACCEPTED' in prefix else 0)
179    input_feature.append(1 if 'A_FINALIZED' in prefix else 0)
180    input_feature.append(buffer.get_feature("attribute_case")['AMOUNT'])
181    input_feature.append(buffer.get_feature("end_time").hour)
182    input_feature.append(buffer.get_feature("end_time").weekday())
183
184    loaded_model = pickle.load(
185        open(os.getcwd() + '/example/example_decision_mining/random_forest.pkl', 'rb'))
186    y_pred_f = loaded_model.predict([input_feature])
187    return int(y_pred_f[0])
def case_function_attribute(case: int, time: datetime.datetime):
39def case_function_attribute(case: int, time: datetime):
40    """
41        Function to add one or more attributes to each trace.
42        Input parameters are case id number and trace start timestamp and return a dictionary.
43        For example, we generate a trace attribute, the requested loan amount, to simulate the process from the BPIChallenge2012A.xes log.
44    """
45    return {"AMOUNT": random.randint(100, 99999)}

Function to add one or more attributes to each trace. Input parameters are case id number and trace start timestamp and return a dictionary. For example, we generate a trace attribute, the requested loan amount, to simulate the process from the BPIChallenge2012A.xes log.

def event_function_attribute(case: int, time: datetime.datetime):
48def event_function_attribute(case: int, time: datetime):
49    """
50        Function to add one or more attributes to each event.
51        Input parameters are case id number and trace start timestamp and return a dictionary.
52        In the following example, we assume that there are multiple bank branches where activities
53        are executed by day of the week. From Monday to Wednesday, activities are executed in the
54        Eindhoven branch otherwise in the Utrecht one.
55    """
56    bank = "Utrecht" if time.weekday() > 3 else "Eindhoven"
57    return {"bank_branch": bank}

Function to add one or more attributes to each event. Input parameters are case id number and trace start timestamp and return a dictionary. In the following example, we assume that there are multiple bank branches where activities are executed by day of the week. From Monday to Wednesday, activities are executed in the Eindhoven branch otherwise in the Utrecht one.

def custom_arrivals_time(case, previous):
60def custom_arrivals_time(case, previous):
61    """
62    Function to define a new arrival of a trace. The input parameters are the case id number and the start timestamp of the previous trace.
63    For example, we used an AutoRegression model for the *arrivals example*.
64    """
65    loaded = AutoRegResults.load('example/example_arrivals/arrival_AutoReg_model.pkl')
66    return loaded.predict(case+1, case+1)[0]

Function to define a new arrival of a trace. The input parameters are the case id and the start timestamp of the previous trace. For example, we used an AutoRegression model for the arrivals example.

def custom_processing_time(buffer: utility.Buffer):
 69def custom_processing_time(buffer: Buffer):
 70    """
 71    Define the processing time of the activity (return the duration in seconds).
 72    Example of features that can be used to predict:
 73
 74    ```json
 75            {
 76                "id_case": 23,
 77                "activity": "A_ACCEPTED",
 78                "enabled_time": "2023-08-23 11:14:13",
 79                "start_time": "2023-08-23 11:14:13",
 80                "end_time": None,
 81                "role": "Role 2",
 82                "resource": "Sue",
 83                "wip_wait": 3,
 84                "wip_start": 3,
 85                "wip_end": -1,
 86                "wip_activity": 1,
 87                "ro_total": [0.5, 1],
 88                "ro_single": 1,
 89                "queue": 0,
 90                "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED"],
 91                "attribute_case": {"AMOUNT": 59024},
 92                "attribute_event": {"bank_branch": "Eindhoven"}
 93            }
 94    ```
 95    """
 96    input_feature = list()
 97    input_feature.append(buffer.get_feature("wip_start"))
 98    input_feature.append(buffer.get_feature("wip_activity"))
 99    input_feature.append(buffer.get_feature("start_time").weekday())
100    input_feature.append(buffer.get_feature("start_time").hour)
101    loaded_model = pickle.load(
102        open(os.getcwd()+'/example/example_process_times/processing_time_random_forest.pkl', 'rb'))
103    y_pred_f = loaded_model.predict([input_feature])
104    return int(y_pred_f[0])

Define the processing time of the activity (return the duration in seconds). A complete example can be found on Petrinet processing times. Example of features that can be used to predict:

        {
            "id_case": 23,
            "activity": "A_ACCEPTED",
            "enabled_time": "2023-08-23 11:14:13",
            "start_time": "2023-08-23 11:14:13",
            "end_time": None,
            "role": "Role 2",
            "resource": "Sue",
            "wip_wait": 3,
            "wip_start": 3,
            "wip_end": -1,
            "wip_activity": 1,
            "ro_total": [0.5, 1],
            "ro_single": 1,
            "queue": 0,
            "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED"],
            "attribute_case": {"AMOUNT": 59024},
            "attribute_event": {"bank_branch": "Eindhoven"}
        }
def custom_waiting_time(buffer: utility.Buffer):
107def custom_waiting_time(buffer: Buffer):
108    """ Define the waiting time of the activity (return the duration in seconds).
109    Example of features that can be used to predict:
110    ```json
111    {
112        "id_case": 15,
113        "activity": "A_PARTLYSUBMITTED",
114        "enabled_time": "None",
115        "start_time": "None",
116        "end_time": "None",
117        "role": "Role 2",
118        "resource": "None",
119        "wip_wait": 21,
120        "wip_start": -1,
121        "wip_end": -1,
122        "wip_activity": 1,
123        "ro_total": [0.5, 1],
124        "ro_single": 1,
125        "queue": 13,
126        "prefix": ["A_SUBMITTED"],
127        "attribute_case": {"AMOUNT": 18207},
128        "attribute_event": {"bank_branch": "Eindhoven"}
129
130    }
131    ```
132    """
133    input_feature = list()
134    buffer.print_values()
135    input_feature.append(buffer.get_feature("wip_wait"))
136    input_feature.append(buffer.get_feature("wip_activity"))
137    input_feature.append(buffer.get_feature("enabled_time").weekday())
138    input_feature.append(buffer.get_feature("enabled_time").hour)
139    input_feature.append(buffer.get_feature("ro_single"))
140    input_feature.append(buffer.get_feature("queue"))
141    loaded_model = pickle.load(
142        open(os.getcwd() + '/example/example_process_times/waiting_time_random_forest.pkl', 'rb'))
143    y_pred_f = loaded_model.predict([input_feature])
144    return int(y_pred_f[0])

Define the waiting time of the activity (return the duration in seconds). A complete example can be found on Petrinet processing times. Example of features that can be used to predict:

{
    "id_case": 15,
    "activity": "A_PARTLYSUBMITTED",
    "enabled_time": "None",
    "start_time": "None",
    "end_time": "None",
    "role": "Role 2",
    "resource": "None",
    "wip_wait": 21,
    "wip_start": -1,
    "wip_end": -1,
    "wip_activity": 1,
    "ro_total": [0.5, 1],
    "ro_single": 1,
    "queue": 13,
    "prefix": ["A_SUBMITTED"],
    "attribute_case": {"AMOUNT": 18207},
    "attribute_event": {"bank_branch": "Eindhoven"}

}
def custom_decision_mining(buffer: utility.Buffer):
147def custom_decision_mining(buffer: Buffer):
148    """
149    Function to define the next activity from a decision point in the Petri net model.
150    For example, we used a Random Forest model for the *decision mining* example.
151
152    Example of features that can be used to predict:
153    ```json
154        {
155            "id_case": 43,
156            "activity": "A_FINALIZED",
157            "enabled_time": "2023-08-24 16:24:29",
158            "start_time": "2023-08-24 19:37:31",
159            "end_time": "2023-08-24 20:03:34",
160            "role": "Role 2",
161            "resource": "Sue",
162            "wip_wait": 16,
163            "wip_start": 4,
164            "wip_end": 4,
165            "wip_activity": 2,
166            "ro_total": [0.0, 1],
167            "ro_single": 1,
168            "queue": 15,
169            "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED", "A_ACCEPTED"],
170            "attribute_case": {"AMOUNT": 86061},
171            "attribute_event": {"bank_branch": "Eindhoven"}
172
173        }
174    ```
175    """
176    input_feature = list()
177    prefix = buffer.get_feature("prefix")
178    input_feature.append(1 if 'A_PREACCEPTED' in prefix else 0)
179    input_feature.append(1 if 'A_ACCEPTED' in prefix else 0)
180    input_feature.append(1 if 'A_FINALIZED' in prefix else 0)
181    input_feature.append(buffer.get_feature("attribute_case")['AMOUNT'])
182    input_feature.append(buffer.get_feature("end_time").hour)
183    input_feature.append(buffer.get_feature("end_time").weekday())
184
185    loaded_model = pickle.load(
186        open(os.getcwd() + '/example/example_decision_mining/random_forest.pkl', 'rb'))
187    y_pred_f = loaded_model.predict([input_feature])
188    return int(y_pred_f[0])

Function to define the next activity from a decision point in the Petri net model. For the decision mining example, we used a Random Forest model.

Example of features that can be used to predict:

    {
        "id_case": 43,
        "activity": "A_FINALIZED",
        "enabled_time": "2023-08-24 16:24:29",
        "start_time": "2023-08-24 19:37:31",
        "end_time": "2023-08-24 20:03:34",
        "role": "Role 2",
        "resource": "Sue",
        "wip_wait": 16,
        "wip_start": 4,
        "wip_end": 4,
        "wip_activity": 2,
        "ro_total": [0.0, 1],
        "ro_single": 1,
        "queue": 15,
        "prefix": ["A_SUBMITTED", "A_PARTLYSUBMITTED", "A_PREACCEPTED", "A_ACCEPTED"],
        "attribute_case": {"AMOUNT": 86061},
        "attribute_event": {"bank_branch": "Eindhoven"}

    }