[8]:
import warnings
warnings.filterwarnings("ignore", category=UserWarning)
Log Filtering with Linear Temporal Properties¶
The filtering of a log according to Linear Temporal Logic properties is implemented with an LTLf checker based on automata. First of all we create an D4PyEventLog object that wraps the log.
[9]:
import os
from Declare4Py.D4PyEventLog import D4PyEventLog
log_path = os.path.join("../../../", "tests", "test_logs","Sepsis Cases.xes.gz")
event_log = D4PyEventLog()
event_log.parse_xes_log(log_path)
The classes LTLTemplate and LTLModel are responsible for the LTLf template definitions and their instantiations into LTLf models given some activities and/or payload names:
[10]:
from Declare4Py.ProcessModels.LTLModel import LTLTemplate
from Declare4Py.ProcessModels.LTLModel import LTLModel
template : LTLTemplate = LTLTemplate('is_first_state_a')
model_1 : LTLModel= template.fill_template(['ER Registration'], attr_type=['concept:name'])
template: LTLTemplate = LTLTemplate('eventually_a')
model_2 : LTLModel = template.fill_template(['Leucocytes'], attr_type=['concept:name'])
The class LTLAnalyzer is therefore needed to analyze the log and filtering its traces according to multiple input LTLf models.
[11]:
from Declare4Py.ProcessMiningTasks.ConformanceChecking.LTLAnalyzer import LTLAnalyzer
analyzer = LTLAnalyzer(event_log, [model_1, model_2])
conf_check_res_df = analyzer.run_multiple_models(minimize_automaton=False)
The output is a Pandas DataFrame that can be easily queried.
[12]:
print(f"Accepted traces: {len(conf_check_res_df[conf_check_res_df['accepted'] == True])}")
conf_check_res_df
Accepted traces: 957
[12]:
| case:concept:name | accepted | |
|---|---|---|
| 0 | A | True |
| 1 | B | True |
| 2 | C | True |
| 3 | D | True |
| 4 | E | True |
| ... | ... | ... |
| 1045 | HNA | True |
| 1046 | INA | False |
| 1047 | JNA | False |
| 1048 | KNA | True |
| 1049 | LNA | False |
1050 rows × 2 columns
The same easy coding holds also for Branched-DECLARE templates:
[13]:
template = LTLTemplate('alternate_response')
activities_a = ["Er Registration", "IV Liquid"]
activities_b = ["CRP", "IV Antibiotics"]
model_1 = template.fill_template(activities_a, activities_b)
template = LTLTemplate('not_precedence')
activities_a = ["ER Sepsis Triage", "CRP"]
activities_b = ["IV Antibiotics", "LacticAcid"]
model_2 = template.fill_template(activities_a, activities_b)
analyzer = LTLAnalyzer(event_log, [model_1, model_2])
conf_check_res_df = analyzer.run_multiple_models()
We therefore access the Pandas Dataframe
[14]:
print(f"Accepted traces: {len(conf_check_res_df[conf_check_res_df['accepted'] == True])}")
conf_check_res_df
Accepted traces: 117
[14]:
| case:concept:name | accepted | |
|---|---|---|
| 0 | A | False |
| 1 | B | False |
| 2 | C | False |
| 3 | D | False |
| 4 | E | False |
| ... | ... | ... |
| 1045 | HNA | False |
| 1046 | INA | False |
| 1047 | JNA | False |
| 1048 | KNA | False |
| 1049 | LNA | False |
1050 rows × 2 columns
More information about managing process models and the LTLf or B-Declare templates can be found in tutorials 2 and 3.