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 = align_factory.apply( trace, imported_petri1, marking1, final_marking, version=align_factory.VERSION_DIJKSTRA_NO_HEURISTICS )['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 get_alignments_decoration(net, im, fm, log=None, aligned_traces=None, parameters=None): """ Get a decoration for the Petri net based on alignments Parameters ------------- net Petri net im Initial marking fm Final marking log Event log aligned_traces Aligned traces parameters Parameters of the algorithm Returns ------------- decorations Decorations to use """ if parameters is None: parameters = {} if aligned_traces is None and log is not None: from pm4py.algo.conformance.alignments import factory as alignments_factory aligned_traces = alignments_factory.apply(log, net, im, fm, parameters={"ret_tuple_as_trans_desc": True}) decorations = {} net_transitions = {} for trans in net.transitions: net_transitions[trans.name] = trans for align_trace0 in aligned_traces: align_trace = align_trace0["alignment"] for move in align_trace: move_trans_name = move[0][1] activity_trace_name = move[0][0] if move_trans_name in net_transitions: trans = net_transitions[move_trans_name] if trans not in decorations: decorations[trans] = {"count_fit": 0, "count_move_on_model": 0} if activity_trace_name == ">>": decorations[trans]["count_move_on_model"] = decorations[trans]["count_move_on_model"] + 1 else: decorations[trans]["count_fit"] = decorations[trans]["count_fit"] + 1 for trans in decorations: if trans.label is not None: decorations[trans]["label"] = trans.label + " (" + str( decorations[trans]["count_move_on_model"]) + "," + str(decorations[trans]["count_fit"]) + ")" decorations[trans]["color"] = get_transitions_color(decorations[trans]["count_move_on_model"], decorations[trans]["count_fit"]) return decorations
def clean_log_from_non_fitting_traces(log, model, i_m, f_m, occurence=False): activities = Utility.get_activities(log) #filter event log. The perfect fitting traces are kept. However, for unfitting traces, we keep the alligned event log replay_result = alignments.apply(log, model, i_m, f_m) return Utility.get_perfect_fitting_trace_variants_and_number_of_occurence( replay_result, activities, occurence)
def perform_alignments(log, petri_string, parameters=None): """ Perform alignments Parameters ------------ log Log net Petri net parameters Parameters of the algorithm Returns ------------- petri SVG of the decorated Petri table SVG of the decorated table """ if parameters is None: parameters = {} net, im, fm = pnml.import_petri_from_string(petri_string, parameters=parameters) parameters_align = copy(parameters) parameters_align["ret_tuple_as_trans_desc"] = True alignments = align_factory.apply(log, net, im, fm, parameters=parameters_align) decorations = alignments_decoration.get_alignments_decoration( net, im, fm, aligned_traces=alignments, parameters=parameters) gviz_on_petri = pn_vis_factory.apply(net, im, fm, aggregated_statistics=decorations, variant="alignments", parameters={"format": "svg"}) svg_on_petri = get_base64_from_gviz(gviz_on_petri) parameters_table = copy(parameters) parameters_table["format"] = "svg" gviz_table = align_table_factory.apply(log, alignments, parameters=parameters_table) svg_table = get_base64_from_gviz(gviz_table) return svg_on_petri, svg_table
def test_heu_log(self): log = xes_importer.apply( os.path.join("input_data", "running-example.xes")) net, im, fm = heuristics_miner.apply(log) aligned_traces_tr = tr_factory.apply(log, net, im, fm) aligned_traces_alignments = align_factory.apply(log, net, im, fm) evaluation = eval_factory.apply(log, net, im, fm) fitness = rp_fit_factory.apply(log, net, im, fm) precision = precision_factory.apply(log, net, im, fm) generalization = generalization_factory.apply(log, net, im, fm) simplicity = simplicity_factory.apply(net)
def test_inductiveminer_df(self): log = csv_import_adapter.import_dataframe_from_path( os.path.join("input_data", "running-example.csv")) net, im, fm = inductive_miner.apply(log) aligned_traces_tr = tr_factory.apply(log, net, im, fm) aligned_traces_alignments = align_factory.apply(log, net, im, fm) evaluation = eval_factory.apply(log, net, im, fm) fitness = rp_fit_factory.apply(log, net, im, fm) precision = precision_factory.apply(log, net, im, fm) generalization = generalization_factory.apply(log, net, im, fm) simplicity = simplicity_factory.apply(net)
def test_inductiveminer_stream(self): stream = csv_importer.apply( os.path.join("input_data", "running-example.csv")) net, im, fm = inductive_miner.apply(stream) aligned_traces_tr = tr_factory.apply(stream, net, im, fm) aligned_traces_alignments = align_factory.apply(stream, net, im, fm) evaluation = eval_factory.apply(stream, net, im, fm) fitness = rp_fit_factory.apply(stream, net, im, fm) precision = precision_factory.apply(stream, net, im, fm) generalization = generalization_factory.apply(stream, net, im, fm) simplicity = simplicity_factory.apply(net)
def test_alignment(self): log = xes_importer.apply( os.path.join("input_data", "running-example.xes")) from pm4py.algo.discovery.alpha import factory as alpha_miner net, im, fm = alpha_miner.apply(log) from pm4py.algo.conformance.alignments import factory as alignments aligned_traces = alignments.apply( log, net, im, fm, version=alignments.VERSION_STATE_EQUATION_A_STAR) aligned_traces = alignments.apply( log, net, im, fm, version=alignments.VERSION_DIJKSTRA_NO_HEURISTICS) from pm4py.evaluation.replay_fitness import factory as rp_fitness_evaluator fitness = rp_fitness_evaluator.apply( log, net, im, fm, variant=rp_fitness_evaluator.ALIGNMENT_BASED) evaluation = rp_fitness_evaluator.evaluate( aligned_traces, variant=rp_fitness_evaluator.ALIGNMENT_BASED) from pm4py.evaluation.precision import factory as precision_evaluator precision = precision_evaluator.apply( log, net, im, fm, variant=precision_evaluator.ALIGN_ETCONFORMANCE)
def test_alignment_pnml(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" log = xes_importer.import_log(os.path.join(INPUT_DATA_DIR, "running-example.xes")) net, marking, final_marking = inductive_miner.apply(log) for trace in log: cf_result = align_factory.apply(trace, net, marking, final_marking, version=align_factory.VERSION_DIJKSTRA_NO_HEURISTICS)['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")
#----------------- from pm4py.objects.log.importer.csv import factory as csv_importer excellentLog1A = csv_importer.import_event_stream('Excellent1A_fixed.csv') from pm4py.objects.conversion.log import factory as conversion_factory log1 = conversion_factory.apply(excellentLog1A) from pm4py.visualization.dfg import factory as dfg_vis_factory gviz = dfg_vis_factory.apply(dfg1, log=log1, variant="frequency") dfg_vis_factory.view(gviz) from pm4py.objects.conversion.dfg import factory as dfg_mining_factory net, im, fm = dfg_mining_factory.apply(dfg1) from pm4py.visualization.petrinet import factory as pn_vis_factory gviz = pn_vis_factory.apply(net, im, fm) pn_vis_factory.view(gviz) from pm4py.evaluation.replay_fitness import factory as replay_factory fitness_alpha = replay_factory.apply(log1, net, im, fm) from pm4py.algo.conformance.alignments import factory as align_factory alignments = align_factory.apply(log1, net, im, fm) print(alignments) #excellentLog1A = excellentLog1A.sort_values(by=['org:resource','case','time:timestamp'])
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
def py_data_2019_demo_script(): event_data = xes_log_importer.apply('<path_to_data>') model, marking_i, marking_f = pn_importer.apply('<path_to_model>') alignments = alignment_algorithm.apply(event_data, model, marking_i, marking_f) print(alignments)
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)