def test_importingExportingPetri(self): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" imported_petri1, marking1, fmarking1 = petri_importer.import_net( os.path.join(INPUT_DATA_DIR, "running-example.pnml")) soundness = check_soundness.check_petri_wfnet_and_soundness( imported_petri1) del soundness petri_exporter.export_net( imported_petri1, marking1, os.path.join(OUTPUT_DATA_DIR, "running-example.pnml")) imported_petri2, marking2, fmarking2 = petri_importer.import_net( os.path.join(OUTPUT_DATA_DIR, "running-example.pnml")) soundness = check_soundness.check_petri_wfnet_and_soundness( imported_petri2) del soundness self.assertEqual(sorted([x.name for x in imported_petri1.places]), sorted([x.name for x in imported_petri2.places])) self.assertEqual(sorted([x.name for x in imported_petri1.transitions]), sorted([x.name for x in imported_petri2.transitions])) self.assertEqual( sorted( [x.source.name + x.target.name for x in imported_petri1.arcs]), sorted( [x.source.name + x.target.name for x in imported_petri2.arcs])) self.assertEqual([x.name for x in marking1], [x.name for x in marking2]) os.remove(os.path.join(OUTPUT_DATA_DIR, "running-example.pnml"))
def test_importingPetriLogAlignment(self): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" imported_petri1, marking1, fmarking1 = petri_importer.import_net( os.path.join(INPUT_DATA_DIR, "running-example.pnml")) soundness = check_soundness.check_petri_wfnet_and_soundness( imported_petri1) del soundness log = xes_importer.import_log( os.path.join(INPUT_DATA_DIR, "running-example.xes")) final_marking = petri.petrinet.Marking() for p in imported_petri1.places: if not p.out_arcs: final_marking[p] = 1 for trace in log: cf_result = state_equation_a_star.apply(trace, imported_petri1, marking1, final_marking)['alignment'] is_fit = True for couple in cf_result: if not (couple[0] == couple[1] or couple[0] == ">>" and couple[1] is None): is_fit = False if not is_fit: raise Exception("should be fit")
def execute_script(): # loads the log log = xes_importer.apply( os.path.join("..", "tests", "input_data", "receipt.xes")) # apply the simple miner net, im, fm = simple_miner.apply(log, classic_output=True) # checks if the Petri net is a sound workflow net is_sound_wfnet = check_petri_wfnet_and_soundness(net) print("is_sound_wfnet = ", is_sound_wfnet)
def test_importingPetriLogTokenReplay(self): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" imported_petri1, marking1, fmarking1 = petri_importer.import_net( os.path.join(INPUT_DATA_DIR, "running-example.pnml")) soundness = check_soundness.check_petri_wfnet_and_soundness(imported_petri1) del soundness log = xes_importer.import_log(os.path.join(INPUT_DATA_DIR, "running-example.xes")) aligned_traces = token_replay.apply_log(log, imported_petri1, marking1, fmarking1) del aligned_traces
def obtainPetriNetThroughImdf(self, log_name): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" if ".xes" in log_name: log = xes_importer.import_log(log_name) else: event_log = csv_importer.import_event_stream(log_name) log = log_conv_fact.apply(event_log) net, marking, final_marking = inductive_miner.apply(log) soundness = check_soundness.check_petri_wfnet_and_soundness(net) del soundness return log, net, marking, final_marking
def obtainPetriNetThroughAlphaMiner(self, log_name): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" if ".xes" in log_name: trace_log = xes_importer.import_log(log_name) else: event_log = csv_importer.import_log(log_name) trace_log = log_transform.transform_event_log_to_trace_log( event_log) net, marking, fmarking = alpha_factory.apply(trace_log) soundness = check_soundness.check_petri_wfnet_and_soundness(net) del soundness return trace_log, net, marking, fmarking
def obtainPetriNetThroughAlphaMiner(self, log_name): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" if ".xes" in log_name: log = xes_importer.apply(log_name) else: df = pd.read_csv(log_name) df = dataframe_utils.convert_timestamp_columns_in_df(df) log = log_conversion.apply(df) net, marking, fmarking = alpha_alg.apply(log) soundness = check_soundness.check_petri_wfnet_and_soundness(net) del soundness return log, net, marking, fmarking
def obtainPetriNetThroughImdf(self, log_name, variant=inductive_miner.DEFAULT_VARIANT): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" if ".xes" in log_name: log = xes_importer.apply(log_name) else: df = pd.read_csv(log_name) df = dataframe_utils.convert_timestamp_columns_in_df(df) log = log_conversion.apply(df) # apply dummily the test to all the available variants net, marking, final_marking = inductive_miner.apply( log, variant=inductive_miner.DFG_BASED) net, marking, final_marking = inductive_miner.apply(log, variant=variant) soundness = check_soundness.check_petri_wfnet_and_soundness(net) del soundness return log, net, marking, final_marking
def obtainPetriNetThroughImdf(self, log_name, variant=inductive_miner.DEFAULT_VARIANT): # to avoid static method warnings in tests, # that by construction of the unittest package have to be expressed in such way self.dummy_variable = "dummy_value" if ".xes" in log_name: log = xes_importer.import_log(log_name) else: event_log = csv_importer.import_event_stream(log_name) log = log_conv_fact.apply(event_log) # apply dummily the test to all the available variants net, marking, final_marking = inductive_miner.apply( log, variant=inductive_miner.DFG_BASED_OLD_VERSION) net, marking, final_marking = inductive_miner.apply( log, variant=inductive_miner.DFG_BASED) net, marking, final_marking = inductive_miner.apply(log, variant=variant) soundness = check_soundness.check_petri_wfnet_and_soundness(net) del soundness return log, net, marking, final_marking
pmutil.constants.PARAMETER_CONSTANT_ATTRIBUTE_KEY: activity_key } t1 = time.time() alpha_model, alpha_initial_marking, alpha_final_marking = alpha.apply( log, parameters=parameters_discovery) pnml_exporter.export_net(alpha_model, alpha_initial_marking, os.path.join( pnmlFolder, logNamePrefix + "_alpha.pnml"), final_marking=alpha_final_marking) t2 = time.time() print("time interlapsed for calculating Alpha Model", (t2 - t1)) print( "alpha is_sound_wfnet", check_soundness.check_petri_wfnet_and_soundness(alpha_model, debug=True)) t1 = time.time() heu_model, heu_initial_marking, heu_final_marking = heuristics_miner.apply( log, parameters=parameters_discovery) pnml_exporter.export_net(heu_model, heu_initial_marking, os.path.join( pnmlFolder, logNamePrefix + "_alpha.pnml"), final_marking=heu_final_marking) t2 = time.time() print("time interlapsed for calculating Heuristics Model", (t2 - t1)) print( "heuristics is_sound_wfnet",
def get_s_components_from_petri(net, im, fm, rec_depth=0, curr_s_comp=None, visited_places=None, list_s_components=None): """ Gets the S-components from a Petri net Parameters ------------- net Petri net im Initial marking fm Final marking curr_s_comp Current S component visited_places Visited places list_s_components List of S-components Returns -------------- s_components List of S-components """ MAX_REC_DEPTH = 6 if list_s_components is None: list_s_components = [] if len(im) > 1 or len(fm) > 1: return list_s_components if not check_petri_wfnet_and_soundness(net): return list_s_components source = list(im.keys())[0] if curr_s_comp is None: curr_s_comp = [source] if visited_places is None: visited_places = [] something_changed = True while something_changed and rec_depth < MAX_REC_DEPTH: something_changed = False places_to_visit = sorted(list(set(curr_s_comp[len(visited_places):])), key=lambda x: len(x.out_arcs), reverse=True) for place_to_visit in places_to_visit: visited_places.append(place_to_visit) target_trans = sorted(list( set([arc.target for arc in place_to_visit.out_arcs])), key=lambda x: len(x.out_arcs)) for trans in target_trans: visited_places_names = [x.name for x in visited_places] target_trans_target = list( set([ arc.target for arc in trans.out_arcs if arc.target.name not in visited_places_names ])) if target_trans_target: something_changed = True if len(target_trans_target) == 1: new_place = target_trans_target[0] curr_s_comp.append(new_place) else: for new_place in target_trans_target: [new_curr_s_comp, new_visited_places ] = deepcopy([curr_s_comp, visited_places]) new_curr_s_comp.append(new_place) list_s_components = get_s_components_from_petri( net, im, fm, rec_depth=rec_depth + 1, curr_s_comp=new_curr_s_comp, visited_places=new_visited_places, list_s_components=list_s_components) if not set([place.name for place in curr_s_comp]) in list_s_components: list_s_components.append(set([place.name for place in curr_s_comp])) return list_s_components
def apply(log, parameters=None): """ Returns a log from which a sound workflow net could be extracted taking into account a discovery algorithm returning models only with visible transitions Parameters ------------ log Trace log parameters Possible parameters of the algorithm, including: discovery_algorithm -> Discovery algorithm to consider, possible choices: alphaclassic max_no_variants -> Maximum number of variants to consider to return a Petri net Returns ------------ filtered_log Filtered trace log """ if parameters is None: parameters = {} discovery_algorithm = parameters[ "discovery_algorithm"] if "discovery_algorithm" in parameters else "alphaclassic" max_no_variants = parameters[ "max_no_variants"] if "max_no_variants" in parameters else 20 all_variants_dictio = variants_filter.get_variants(log, parameters=parameters) all_variants_list = [] for var in all_variants_dictio: all_variants_list.append([var, len(all_variants_dictio[var])]) all_variants_list = sorted(all_variants_list, key=lambda x: (x[1], x[0]), reverse=True) considered_variants = [] considered_traces = [] i = 0 while i < min(len(all_variants_list), max_no_variants): variant = all_variants_list[i][0] considered_variants.append(variant) considered_traces.append(all_variants_dictio[variant][0]) filtered_log = TraceLog(considered_traces) net = None initial_marking = None final_marking = None if discovery_algorithm == "alphaclassic" or discovery_algorithm == "alpha": net, initial_marking, final_marking = alpha_miner.apply( filtered_log, parameters=parameters) is_sound = check_soundness.check_petri_wfnet_and_soundness(net) if not is_sound: del considered_variants[-1] del considered_traces[-1] else: try: alignments = alignment_factory.apply(filtered_log, net, initial_marking, final_marking) del alignments fitness = replay_fitness_factory.apply(filtered_log, net, initial_marking, final_marking, parameters=parameters) if fitness["log_fitness"] < 0.99999: del considered_variants[-1] del considered_traces[-1] except TypeError: del considered_variants[-1] del considered_traces[-1] i = i + 1 sound_log = TraceLog() if considered_variants: sound_log = variants_filter.apply(log, considered_variants, parameters=parameters) return sound_log
} ] print("log") for j in log_param_list: print(j) auto_log = utils.discover_annotated_automaton(log, j) net_log, im_log, fm_log = sb.petri_net_synthesis(auto_log) print("# of trans: ", len(auto_log.transitions)) print("# of states: ", len(auto_log.states)) ev = evaluation_factory.apply(log, net_log, im_log, fm_log) ev['fitness'] = ev['fitness']['averageFitness'] print("fitness: ", round(ev['fitness']['averageFitness'], 2)) print("precision: ", round(ev['precision'], 2)) print("simplicity: ", round(ev['simplicity'], 2)) print("generalization: ", round(ev['generalization'], 2)) soundness_log = check_soundness.check_petri_wfnet_and_soundness( net_log) if soundness_log: fitness = replay_factory.apply(log, net_log, im_log, fm_log) ev['align_fitness'] = fitness['averageFitness'] else: ev['align_fitness'] = -1 wr.writerow([ j, len(auto_log.transitions), len(auto_log.states), soundness_log, round(ev['fitness'], 2), round(ev['align_fitness'], 2), round(ev['precision'], 2), round(ev['simplicity'], 2), round(ev['generalization'], 2) ], round(ev['fscore'], 2), round(ev['metricsAverageWeight'], 2))
def apply(df, parameters=None): """ Returns a Pandas dataframe from which a sound workflow net could be extracted taking into account a discovery algorithm returning models only with visible transitions Parameters ------------ df Pandas dataframe parameters Possible parameters of the algorithm, including: max_no_variants -> Maximum number of variants to consider to return a Petri net Returns ------------ filtered_df Filtered dataframe """ if parameters is None: parameters = {} if PARAMETER_CONSTANT_CASEID_KEY not in parameters: parameters[PARAMETER_CONSTANT_CASEID_KEY] = CASE_CONCEPT_NAME if PARAMETER_CONSTANT_ACTIVITY_KEY not in parameters: parameters[PARAMETER_CONSTANT_ACTIVITY_KEY] = DEFAULT_NAME_KEY if PARAMETER_CONSTANT_TIMESTAMP_KEY not in parameters: parameters[PARAMETER_CONSTANT_TIMESTAMP_KEY] = DEFAULT_TIMESTAMP_KEY if PARAMETER_CONSTANT_ATTRIBUTE_KEY not in parameters: parameters[PARAMETER_CONSTANT_ATTRIBUTE_KEY] = parameters[ PARAMETER_CONSTANT_ACTIVITY_KEY] caseid_glue = parameters[PARAMETER_CONSTANT_CASEID_KEY] activity_key = parameters[PARAMETER_CONSTANT_ACTIVITY_KEY] timest_key = parameters[PARAMETER_CONSTANT_TIMESTAMP_KEY] max_no_variants = parameters[ "max_no_variants"] if "max_no_variants" in parameters else 20 variants_df = case_statistics.get_variants_df(df, parameters=parameters) parameters["variants_df"] = variants_df variant_stats = case_statistics.get_variant_statistics( df, parameters=parameters) all_variants_list = [] for var in variant_stats: all_variants_list.append([var["variant"], var[caseid_glue]]) all_variants_list = sorted(all_variants_list, key=lambda x: (x[1], x[0]), reverse=True) considered_variants = [] considered_traces = [] i = 0 while i < min(len(all_variants_list), max_no_variants): variant = all_variants_list[i][0] considered_variants.append(variant) filtered_df = variants_filter.apply(df, considered_variants, parameters=parameters) dfg_frequency = dfg_util.get_dfg_graph(filtered_df, measure="frequency", perf_aggregation_key="median", case_id_glue=caseid_glue, activity_key=activity_key, timestamp_key=timest_key) net, initial_marking, final_marking = alpha_miner.apply_dfg( dfg_frequency, parameters=parameters) is_sound = check_soundness.check_petri_wfnet_and_soundness(net) if not is_sound: del considered_variants[-1] else: traces_of_this_variant = variants_filter.apply( df, [variant], parameters=parameters).groupby(caseid_glue) traces_of_this_variant_keys = list( traces_of_this_variant.groups.keys()) trace_of_this_variant = traces_of_this_variant.get_group( traces_of_this_variant_keys[0]) this_trace = transform.transform_event_log_to_trace_log( pandas_df_imp.convert_dataframe_to_event_log( trace_of_this_variant), case_glue=caseid_glue)[0] if not activity_key == DEFAULT_NAME_KEY: for j in range(len(this_trace)): this_trace[j][DEFAULT_NAME_KEY] = this_trace[j][ activity_key] considered_traces.append(this_trace) filtered_log = TraceLog(considered_traces) try: alignments = alignment_factory.apply(filtered_log, net, initial_marking, final_marking) del alignments fitness = replay_fitness_factory.apply(filtered_log, net, initial_marking, final_marking, parameters=parameters) if fitness["log_fitness"] < 0.99999: del considered_variants[-1] del considered_traces[-1] except TypeError: del considered_variants[-1] del considered_traces[-1] i = i + 1 return variants_filter.apply(df, considered_variants, parameters=parameters)