Select Git revision
experiments.py
eventlog.py 7.86 KiB
import pandas as pd
import simplesimmodel as model
import numpy as np
from collections import OrderedDict
import simpy
from pm4py.objects.log.exporter.xes import exporter as xes_exporter
from pm4py.objects.log.importer.xes import importer as xes_importer
from pm4py.objects.log.obj import EventLog
from pm4py.objects.log.obj import Trace
from pm4py.objects.log.obj import Event
import os
"""
Event log generator for our simulation model:
- generate an event log
- update an event log (adding new events)
- export event log
- get current state of an event log
"""
def add_start_event(process, event_id, case_id, activity, start_timestamp):
process.event_log.append(event_id)
process.event_log[event_id] = {
'CaseID': case_id,
'Activity': activity,
'StartTimestamp': float(start_timestamp),
'EndTimestamp': None
}
process.event_counter += 1
def add_end_event(process, event_id, end_timestamp):
event = process.event_log[event_id]
event['EndTimestamp'] = end_timestamp
def export_to_csv(process, file_path):
event_log_df = pd.DataFrame.from_dict(process.event_log)
event_log_df.to_csv(file_path, index=False)
def export_to_xes(process, file_path):
event_log = process.event_log
# Create an empty event log object
event_log_obj = EventLog()
# Iterate over each event in the event log
for event_data in event_log:
# Create a new trace
trace = Trace()
# Create a new event
event = Event()
# Set the attributes of the event based on the dictionary values
event['Activity'] = event_data['Activity']
event['StartTimestamp'] = event_data['StartTimestamp']
event['EndTimestamp'] = event_data['EndTimestamp']
event['CaseID'] = event_data['CaseID']
# Add the event to the trace
trace.append(event)
# Add the trace to the event log
event_log_obj.append(trace)
# Export the event log to XES format
xes_exporter.apply(event_log_obj, file_path)
def convert_to_dataframe(name):
file_path = r"Frontend/upload/" + name
# print(path)
file_extension = os.path.splitext(file_path)[1].lower()
if file_extension == '.csv':
event_log_df = pd.read_csv(file_path)
elif file_extension == '.xes':
# Read the XES file
event_log = xes_importer.apply(file_path)
# Extract the event attributes and create a list of dictionaries
event_data = []
for trace in event_log:
for event in trace:
event_data.append(event)
# Create a pandas DataFrame from the event data
event_log_df = pd.DataFrame(event_data)
else:
print(f"Unsupported file type: {file_extension}")
# print(event_log_df)
return event_log_df
def get_active_cases(name):
event_log_df = convert_to_dataframe(name)
active_cases = event_log_df.groupby('CaseID').filter(lambda x: 'order completed' not in x['Activity'].values)['CaseID'].unique().tolist()
print(active_cases)
return active_cases
def get_state(case_id,name):
process = np.zeros(13, dtype=int)
num_s = 1
process[0] = num_s
num_ot = 4
process[1] = num_ot
num_sh_a = 2
process[2] = num_sh_a
num_sh_b = 2
process[3] = num_sh_b
num_sh_c = 2
process[4] = num_sh_c
num_m_a = 4
process[5] = num_m_a
num_m_b = 10
process[6] = num_m_b
num_p_a = 2
process[7] = num_p_a
num_p_b = 3
process[8] = num_p_b
num_p_c = 3
process[9] = num_p_c
num_ds_a = 25
process[10] = num_ds_a
num_ds_b = 40
process[11] = num_ds_b
num_ds_c = 45
process[12] = num_ds_c
case = np.zeros(15, dtype=int)
activity_mapping = {
'place order': 1,
'arrange standard order': 2,
'arrange custom order': 3,
'pick from stock A': 4,
'pick from stock B': 5,
'pick from stock C': 6,
'manufacture A': 7,
'manufacture B': 8,
'pack A': 9,
'pack B': 10,
'pack C': 11,
'attempt delivery A': 12,
'attempt delivery B': 13,
'attempt delivery C': 14,
'order completed': 15,
}
event_log = convert_to_dataframe(name)
# Sort the event log by case ID and start timestamp
event_log.sort_values(by=['CaseID', 'StartTimestamp'], inplace=True)
# Group the event log by case ID and get the last activity for each case
last_activities = event_log.groupby('CaseID').tail(1).reset_index()
# Remap the activity names to numbers using the mapping dictionary
last_activities['Activity'] = last_activities['Activity'].map(activity_mapping)
# Filter the cases where the end timestamp of the last activity is None or empty
unfinished_cases = last_activities[last_activities['EndTimestamp'].isnull()]['CaseID'].tolist()
# Update the state of the ressources given all unfinished cases
for i in unfinished_cases:
activity = last_activities[last_activities['CaseID'] == i]['Activity'].values[0]
if activity == 1 or activity == 15:
process[0] -= 1
elif activity == 2 or activity == 3:
process[1] -= 1
else:
process[activity-2] -= 1
# Get the state of the case for the given Case ID
filtered_log = event_log[event_log['CaseID'] == case_id]
activities = filtered_log['Activity'].map(activity_mapping).tolist()
for i in activities:
case[i-1] += 1
# Get the last event for the given Case ID
event = last_activities[last_activities['CaseID'] == case_id]['Activity'].values[0]
"""
state = {
'process': process,
'case': case,
'event': event
}
"""
state = OrderedDict()
state['case'] = case
state['event'] = event
state['process'] = process
# print(state)
return state
# connect with frontend!!!
def generate_event_log(time):
ressources = []
num_s = 1
ressources.append(num_s+1)
num_ot = 4
ressources.append(num_ot+1)
num_sh_a = 2
ressources.append(num_sh_a+1)
num_sh_b = 2
ressources.append(num_sh_b+1)
num_sh_c = 2
ressources.append(num_sh_c+1)
num_m_a = 4
ressources.append(num_m_a+1)
num_m_b = 10
ressources.append(num_m_b+1)
num_p_a = 2
ressources.append(num_p_a+1)
num_p_b = 3
ressources.append(num_p_b+1)
num_p_c = 3
ressources.append(num_p_c+1)
num_ds_a = 25
ressources.append(num_ds_a+1)
num_ds_b = 40
ressources.append(num_ds_b+1)
num_ds_c = 45
ressources.append(num_ds_c+1)
# generate event log
env = simpy.Environment()
business_process = model.BusinessProcess(env, ressources)
business_process.event_log_flag = True
env.process(model.run_process(env, business_process))
env.run(until = time)
export_to_csv(business_process, r'Frontend/export/eventlog.csv')
export_to_xes(business_process, r'Frontend/export/eventlog.xes')
def show_active_cases(name):
activity_mapping = {
1: 'place order',
2: 'arrange standard order',
3: 'arrange custom order',
4: 'pick from stock A',
5: 'pick from stock B',
6: 'pick from stock C',
7: 'manufacture A',
8: 'manufacture B',
9: 'pack A',
10: 'pack B',
11: 'pack C',
12: 'attempt delivery A',
13: 'attempt delivery B',
14: 'attempt delivery C',
15: 'order completed',
}
caselist = get_active_cases(name)
reslist = []
for case in caselist:
state = get_state(case, name)
trace = []
events = state['case']
for i in range(len(events)):
if events[i] == 1:
trace.append(activity_mapping[i+1])
tup = (case, trace)
reslist.append(tup)
return reslist
def main():
# generate_event_log(10000)
print(get_state(5, "eventlog.csv"))
if __name__ == "__main__":
main()