Commit 908a8705 authored by m4jidRafiei's avatar m4jidRafiei
Browse files

first commit

parents
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.6" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/PP_IOPM.iml" filepath="$PROJECT_DIR$/.idea/PP_IOPM.iml" />
</modules>
</component>
</project>
\ No newline at end of file
## Introduction
This project implements privacy-aware inter-organizational process mining.
## Python package
The implementation has been published as a standard Python package. Use the following command to install the corresponding Python package:
```shell
pip install pp-iopm
```
## Usage
Look at the "main_....py" files to see the usage example.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This file has been generated with the OpenXES library. It conforms -->
<!-- to the XML serialization of the XES standard for log storage and -->
<!-- management. -->
<!-- XES standard version: 1.0 -->
<!-- OpenXES library version: 1.0RC7 -->
<!-- OpenXES is available from http://www.openxes.org/ -->
<log xes.version="1.0" xes.features="nested-attributes" openxes.version="1.0RC7" xmlns="http://www.xes-standard.org/">
<extension name="Lifecycle" prefix="lifecycle" uri="http://www.xes-standard.org/lifecycle.xesext"/>
<extension name="Organizational" prefix="org" uri="http://www.xes-standard.org/org.xesext"/>
<extension name="Time" prefix="time" uri="http://www.xes-standard.org/time.xesext"/>
<extension name="Concept" prefix="concept" uri="http://www.xes-standard.org/concept.xesext"/>
<extension name="Semantic" prefix="semantic" uri="http://www.xes-standard.org/semantic.xesext"/>
<global scope="trace">
<string key="concept:name" value="__INVALID__"/>
</global>
<global scope="event">
<string key="concept:name" value="__INVALID__"/>
<string key="lifecycle:transition" value="complete"/>
</global>
<classifier name="MXML Legacy Classifier" keys="concept:name lifecycle:transition"/>
<classifier name="Event Name" keys="concept:name"/>
<classifier name="Resource" keys="org:resource"/>
<string key="source" value="CPN Tools simulation"/>
<string key="concept:name" value="teleclaims.mxml"/>
<string key="lifecycle:model" value="standard"/>
<string key="description" value="Simulated process"/>
<trace>
<string key="concept:name" value="0"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="a"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="b"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="c"/>
</event>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="d"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="e"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="f"/>
</event>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="g"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="h"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="k"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="a"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="b"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="m"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="n"/>
<string key="lifecycle:transition" value="start"/>
</event>
</trace>
</log>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This file has been generated with the OpenXES library. It conforms -->
<!-- to the XML serialization of the XES standard for log storage and -->
<!-- management. -->
<!-- XES standard version: 1.0 -->
<!-- OpenXES library version: 1.0RC7 -->
<!-- OpenXES is available from http://www.openxes.org/ -->
<log xes.version="1.0" xes.features="nested-attributes" openxes.version="1.0RC7" xmlns="http://www.xes-standard.org/">
<extension name="Lifecycle" prefix="lifecycle" uri="http://www.xes-standard.org/lifecycle.xesext"/>
<extension name="Organizational" prefix="org" uri="http://www.xes-standard.org/org.xesext"/>
<extension name="Time" prefix="time" uri="http://www.xes-standard.org/time.xesext"/>
<extension name="Concept" prefix="concept" uri="http://www.xes-standard.org/concept.xesext"/>
<extension name="Semantic" prefix="semantic" uri="http://www.xes-standard.org/semantic.xesext"/>
<global scope="trace">
<string key="concept:name" value="__INVALID__"/>
</global>
<global scope="event">
<string key="concept:name" value="__INVALID__"/>
<string key="lifecycle:transition" value="complete"/>
</global>
<classifier name="MXML Legacy Classifier" keys="concept:name lifecycle:transition"/>
<classifier name="Event Name" keys="concept:name"/>
<classifier name="Resource" keys="org:resource"/>
<string key="source" value="CPN Tools simulation"/>
<string key="concept:name" value="teleclaims.mxml"/>
<string key="lifecycle:model" value="standard"/>
<string key="description" value="Simulated process"/>
<trace>
<string key="concept:name" value="0"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="a"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="b"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="c"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="a"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="b"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="m"/>
<string key="lifecycle:transition" value="start"/>
</event>
<event>
<string key="org:resource" value="Alex"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="concept:name" value="n"/>
<string key="lifecycle:transition" value="start"/>
</event>
</trace>
</log>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This file has been generated with the OpenXES library. It conforms -->
<!-- to the XML serialization of the XES standard for log storage and -->
<!-- management. -->
<!-- XES standard version: 1.0 -->
<!-- OpenXES library version: 1.0RC7 -->
<!-- OpenXES is available from http://www.openxes.org/ -->
<log xes.version="1.0" xes.features="nested-attributes" openxes.version="1.0RC7" xmlns="http://www.xes-standard.org/">
<extension name="Lifecycle" prefix="lifecycle" uri="http://www.xes-standard.org/lifecycle.xesext"/>
<extension name="Organizational" prefix="org" uri="http://www.xes-standard.org/org.xesext"/>
<extension name="Time" prefix="time" uri="http://www.xes-standard.org/time.xesext"/>
<extension name="Concept" prefix="concept" uri="http://www.xes-standard.org/concept.xesext"/>
<extension name="Semantic" prefix="semantic" uri="http://www.xes-standard.org/semantic.xesext"/>
<global scope="trace">
<string key="concept:name" value="__INVALID__"/>
</global>
<global scope="event">
<string key="concept:name" value="__INVALID__"/>
<string key="lifecycle:transition" value="complete"/>
</global>
<classifier name="MXML Legacy Classifier" keys="concept:name lifecycle:transition"/>
<classifier name="Event Name" keys="concept:name"/>
<classifier name="Resource" keys="org:resource"/>
<string key="source" value="CPN Tools simulation"/>
<string key="concept:name" value="teleclaims.mxml"/>
<string key="lifecycle:model" value="standard"/>
<string key="description" value="Simulated process"/>
<trace>
<string key="concept:name" value="0"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="d"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="e"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="f"/>
</event>
</trace>
</log>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This file has been generated with the OpenXES library. It conforms -->
<!-- to the XML serialization of the XES standard for log storage and -->
<!-- management. -->
<!-- XES standard version: 1.0 -->
<!-- OpenXES library version: 1.0RC7 -->
<!-- OpenXES is available from http://www.openxes.org/ -->
<log xes.version="1.0" xes.features="nested-attributes" openxes.version="1.0RC7" xmlns="http://www.xes-standard.org/">
<extension name="Lifecycle" prefix="lifecycle" uri="http://www.xes-standard.org/lifecycle.xesext"/>
<extension name="Organizational" prefix="org" uri="http://www.xes-standard.org/org.xesext"/>
<extension name="Time" prefix="time" uri="http://www.xes-standard.org/time.xesext"/>
<extension name="Concept" prefix="concept" uri="http://www.xes-standard.org/concept.xesext"/>
<extension name="Semantic" prefix="semantic" uri="http://www.xes-standard.org/semantic.xesext"/>
<global scope="trace">
<string key="concept:name" value="__INVALID__"/>
</global>
<global scope="event">
<string key="concept:name" value="__INVALID__"/>
<string key="lifecycle:transition" value="complete"/>
</global>
<classifier name="MXML Legacy Classifier" keys="concept:name lifecycle:transition"/>
<classifier name="Event Name" keys="concept:name"/>
<classifier name="Resource" keys="org:resource"/>
<string key="source" value="CPN Tools simulation"/>
<string key="concept:name" value="teleclaims.mxml"/>
<string key="lifecycle:model" value="standard"/>
<string key="description" value="Simulated process"/>
<trace>
<string key="concept:name" value="0"/>
<string key="description" value="Simulated process instance"/>
<event>
<string key="call centre" value="Brisbane"/>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="concept:name" value="g"/>
</event>
<event>
<string key="org:resource" value="Paolo"/>
<date key="time:timestamp" value="1970-01-01T01:00:00.000+01:00"/>
<string key="lifecycle:transition" value="start"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="h"/>
</event>
<event>
<string key="org:resource" value="Frank"/>
<date key="time:timestamp" value="1970-01-01T01:00:41.000+01:00"/>
<string key="lifecycle:transition" value="complete"/>
<string key="location" value="Brisbane"/>
<string key="concept:name" value="k"/>
</event>
</trace>
</log>
import os
from pm4py.objects.log.importer.xes import importer as xes_importer
import pm4py
from pp_iopm.Connector import Connector
from pp_iopm.IOPM import IOPM
current_dir = os.path.dirname(os.path.realpath(__file__))
log_name = "Sepsis_scenarios.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log = xes_importer.apply(log_path)
log = pm4py.insert_artificial_start_end(log)
connector_obj = Connector(log)
basic_conn_all, case_ids = connector_obj.convert_to_basic_connector()
iopm = IOPM(3)
org_names = ["ER","LB","FI"]
org_activities = [["ER Registration", "ER Triage", "ER Sepsis Triage"],
["IV Liquid", "IV Antibiotics", "Admission NC", "Admission IC", "LacticAcid", "CRP", "Leucocytes"],
["Release A", "Release B", "Release C", "Release D", "Release E", "Return ER"]
]
iopm.define_orgs(org_names,org_activities)
handover_tables = iopm.create_handover_tables(log)
handover_relations, handover_to, handover_from = iopm.discover_handover_relations(handover_tables, case_ids)
log_name = "Sepsis_scenarios_ER.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_ER = xes_importer.apply(log_path)
log_ER = pm4py.insert_artificial_start_end(log_ER)
connector_obj = Connector(log_ER)
basic_conn_ER, cases_ER = connector_obj.convert_to_basic_connector()
log_name = "Sepsis_scenarios_LB.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_LB = xes_importer.apply(log_path)
log_LB = pm4py.insert_artificial_start_end(log_LB)
connector_obj = Connector(log_LB)
basic_conn_LB,cases_LB = connector_obj.convert_to_basic_connector()
log_name = "Sepsis_scenarios_FI.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_FI = xes_importer.apply(log_path)
log_FI = pm4py.insert_artificial_start_end(log_FI)
connector_obj = Connector(log_FI)
basic_conn_FI,cases_FI = connector_obj.convert_to_basic_connector()
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(basic_conn_all)
# dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(handover_relations)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
cuel_without_handover = basic_conn_ER + basic_conn_LB + basic_conn_FI
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_without_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
cuel_with_handover, remaining_handover = iopm.update_cuel_scm(cuel_without_handover,handover_relations)
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_with_handover + remaining_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
print("Done!")
\ No newline at end of file
import os
from pm4py.objects.log.importer.xes import importer as xes_importer
import pm4py
from pp_iopm.Connector import Connector
from pp_iopm.IOPM import IOPM
current_dir = os.path.dirname(os.path.realpath(__file__))
log_name = "artificial.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log = xes_importer.apply(log_path)
log = pm4py.insert_artificial_start_end(log)
connector_obj = Connector(log)
basic_conn_all, case_ids = connector_obj.convert_to_basic_connector()
number_of_org = 3
iopm = IOPM(number_of_org)
org_names = ["1","2","3"]
org_activities = [["a","b","c","m","n"],
["d","e","f"],
["g","h","k"]
]
iopm.define_orgs(org_names,org_activities)
handover_tables = iopm.create_handover_tables(log)
handover_relations, handover_to, handover_from = iopm.discover_handover_relations(handover_tables, case_ids)
log_name = "artificial_1.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_1 = xes_importer.apply(log_path)
log_1 = pm4py.insert_artificial_start_end(log_1)
connector_obj = Connector(log_1)
basic_conn_1, cases_1 = connector_obj.convert_to_basic_connector()
log_name = "artificial_2.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_2 = xes_importer.apply(log_path)
log_2 = pm4py.insert_artificial_start_end(log_2)
connector_obj = Connector(log_2)
basic_conn_2,cases_2 = connector_obj.convert_to_basic_connector()
log_name = "artificial_3.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_3 = xes_importer.apply(log_path)
log_3 = pm4py.insert_artificial_start_end(log_3)
connector_obj = Connector(log_3)
basic_conn_3,cases_3 = connector_obj.convert_to_basic_connector()
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(basic_conn_all)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="png")
cuel_without_handover = basic_conn_1 + basic_conn_2 + basic_conn_3
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_without_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="png")
cuel_with_handover = iopm.update_cuel_subcon_scm(cuel_without_handover, handover_relations)
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_with_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="png")
print("Done!")
\ No newline at end of file
import os
from pm4py.objects.log.importer.xes import importer as xes_importer
import pm4py
from pp_iopm.Connector import Connector
from pp_iopm.IOPM import IOPM
current_dir = os.path.dirname(os.path.realpath(__file__))
log_name = "Sepsis_scenarios.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log = xes_importer.apply(log_path)
log = pm4py.insert_artificial_start_end(log)
connector_obj = Connector(log)
basic_conn_all, case_ids = connector_obj.convert_to_basic_connector()
iopm = IOPM(2)
org_names = ["ER","LB"]
org_activities = [["ER Registration", "ER Triage", "ER Sepsis Triage","Release A", "Release B", "Release C", "Release D", "Release E", "Return ER"],
["IV Liquid", "IV Antibiotics", "Admission NC", "Admission IC", "LacticAcid", "CRP", "Leucocytes"],
]
iopm.define_orgs(org_names,org_activities)
handover_tables = iopm.create_handover_tables(log)
handover_relations, handover_to, handover_from = iopm.discover_handover_relations(handover_tables, case_ids)
log_name = "Sepsis_scenarios_ER_FI.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_ER_FI = xes_importer.apply(log_path)
log_ER_FI = pm4py.insert_artificial_start_end(log_ER_FI)
connector_obj = Connector(log_ER_FI)
basic_conn_ER_FI, cases_ER_FI = connector_obj.convert_to_basic_connector()
log_name = "Sepsis_scenarios_LB.xes"
log_path = os.path.join(current_dir, 'event_logs', log_name)
log_LB = xes_importer.apply(log_path)
log_LB = pm4py.insert_artificial_start_end(log_LB)
connector_obj = Connector(log_LB)
basic_conn_LB,cases_LB = connector_obj.convert_to_basic_connector()
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(basic_conn_all)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
cuel_without_handover = basic_conn_ER_FI + basic_conn_LB
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_without_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
cuel_with_handover, remaining_hor = iopm.update_cuel_subcon(cuel_without_handover,handover_relations)
dict_freq, dict_start, dict_end = connector_obj.convert_list_to_dict(cuel_with_handover)
pm4py.view_dfg(dict(dict_freq), dict(dict_start), dict(dict_end), format="pdf")
print("Done!")
\ No newline at end of file
class Connector():
def __init__(self,log):
self.log = log
def convert_to_basic_connector(self, with_handover = False, org_name = None, iopm = None):
basic_conn = {'connector': [], 'handover': 0}
case_ids = []
for case in self.log:
case_ids.append(case.attributes["concept:name"])
for index, event in enumerate(case):
if index % 2 == 0:
connector = []
connector.append(event["concept:name"])
if index > 0:
connector_2 = []
connector_2.append(basic_conn['connector'][-1][1])
connector_2.append(event["concept:name"])
con_tupe = tuple(connector_2)
basic_conn['connector'].append(con_tupe)
else:
connector.append(event["concept:name"])
con_tupe= tuple(connector)
basic_conn['connector'].append(con_tupe)
return basic_conn['connector'], case_ids
def check_handover(self,connector, org_name, iopm):
act_list = iopm.get_act_list_of_org(org_name)
def convert_list_to_dict(self, list):
from collections import defaultdict
DEFAULT_ARTIFICIAL_START_ACTIVITY = "▶"
DEFAULT_ARTIFICIAL_END_ACTIVITY = "■"
dict_freq = defaultdict(int)
dict_start = defaultdict(int)
dict_end = defaultdict(int)
for item in list:
#ignoring artificial start and end
if not (item[0] == DEFAULT_ARTIFICIAL_START_ACTIVITY or item