def test_alignment(self): log = xes_importer.apply( os.path.join("input_data", "running-example.xes")) from pm4py.algo.discovery.alpha import algorithm as alpha_miner net, im, fm = alpha_miner.apply(log) from pm4py.algo.conformance.alignments import algorithm as alignments aligned_traces = alignments.apply( log, net, im, fm, variant=alignments.Variants.VERSION_STATE_EQUATION_A_STAR) aligned_traces = alignments.apply( log, net, im, fm, variant=alignments.Variants.VERSION_DIJKSTRA_NO_HEURISTICS) from pm4py.evaluation.replay_fitness import evaluator as rp_fitness_evaluator fitness = rp_fitness_evaluator.apply( log, net, im, fm, variant=rp_fitness_evaluator.Variants.ALIGNMENT_BASED) evaluation = rp_fitness_evaluator.evaluate( aligned_traces, variant=rp_fitness_evaluator.Variants.ALIGNMENT_BASED) from pm4py.evaluation.precision import evaluator as precision_evaluator precision = precision_evaluator.apply( log, net, im, fm, variant=rp_fitness_evaluator.Variants.ALIGNMENT_BASED)
def test_alignment(self): log = xes_importer.apply(os.path.join("input_data", "running-example.xes")) from pm4py.algo.discovery.alpha import algorithm as alpha_miner net, im, fm = alpha_miner.apply(log) from pm4py.algo.conformance.alignments import algorithm as alignments aligned_traces = alignments.apply(log, net, im, fm, variant=alignments.Variants.VERSION_STATE_EQUATION_A_STAR) aligned_traces = alignments.apply(log, net, im, fm, variant=alignments.Variants.VERSION_DIJKSTRA_NO_HEURISTICS)
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.apply( os.path.join(INPUT_DATA_DIR, "running-example.pnml")) log = xes_importer.apply( 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_alg.apply( trace, imported_petri1, marking1, final_marking, variant=align_alg.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 execute_script(): log = importer.apply(os.path.join("..", "tests", "input_data", "running-example.xes")) net, im, fm = inductive_miner.apply(log) aligned_traces = alignments.apply(log, net, im, fm) gviz = visualizer.apply(log, aligned_traces, parameters={visualizer.Variants.CLASSIC.value.Parameters.FORMAT: "svg"}) visualizer.view(gviz)
def conformance_diagnostics_alignments( log: EventLog, petri_net: PetriNet, initial_marking: Marking, final_marking: Marking) -> List[Dict[str, Any]]: """ Apply the alignments algorithm between a log and a Petri net The methods return the full alignment diagnostics. Parameters ------------- log Event log petri_net Petri net initial_marking Initial marking final_marking Final marking Returns ------------- aligned_traces A list of alignments for each trace of the log (in the same order as the traces in the event log) """ from pm4py.algo.conformance.alignments import algorithm as alignments return alignments.apply(log, petri_net, initial_marking, final_marking)
def apply(log, petri_net, initial_marking, final_marking, align_variant=alignments.DEFAULT_VARIANT, parameters=None): """ Evaluate fitness based on alignments Parameters ---------------- log Event log petri_net Petri net initial_marking Initial marking final_marking Final marking align_variant Variants of the alignments to apply parameters Parameters of the algorithm Returns --------------- dictionary Containing two keys (percFitTraces and averageFitness) """ if align_variant == decomp_alignments.Variants.RECOMPOS_MAXIMAL.value: alignment_result = decomp_alignments.apply(log, petri_net, initial_marking, final_marking, variant=align_variant, parameters=parameters) else: alignment_result = alignments.apply(log, petri_net, initial_marking, final_marking, variant=align_variant, parameters=parameters) return evaluate(alignment_result)
def getFitness(net,m0,mf,log,size_of_run): ''' Prefix-aware fitness :param net: :param m0: :param mf: :param log: :param size_of_run: :return: ''' sum=0 for l in log._list: model_cost_function = dict() sync_cost_function = dict() for t in net.transitions: if t.label is not None: model_cost_function[t]=2**(len(l)+size_of_run-getIndexOfT(t,m0)) sync_cost_function[t]=0 trace_cost_function = dict() for a in range (0,len(l)): trace_cost_function[a]=2**(len(l)+size_of_run-a) parameters = {} parameters[alignments.Variants.VERSION_STATE_EQUATION_A_STAR.value.Parameters.PARAM_MODEL_COST_FUNCTION] = model_cost_function parameters[alignments.Variants.VERSION_STATE_EQUATION_A_STAR.value.Parameters.PARAM_SYNC_COST_FUNCTION] = sync_cost_function parameters[alignments.Variants.VERSION_STATE_EQUATION_A_STAR.value.Parameters.PARAM_TRACE_COST_FUNCTION] = trace_cost_function ali = alignments.apply(l, net, m0, mf, parameters=parameters, variant=versions.dijkstra_no_heuristics) if ali == None: vizu.apply(net, m0, mf).view() sum+=ali['cost'] return sum
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 algorithm as alignments aligned_traces = alignments.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 g(): aa = time.time() aligned_traces = alignments.apply( Shared.log, Shared.net, Shared.im, Shared.fm, variant=alignments.Variants.VERSION_DIJKSTRA_NO_HEURISTICS) bb = time.time() print(bb - aa)
def f(): aa = time.time() aligned_traces = alignments.apply( Shared.log, Shared.net, Shared.im, Shared.fm, variant=alignments.Variants.VERSION_DIJKSTRA_LESS_MEMORY) bb = time.time() print(bb - aa)
def test_inductiveminer_log(self): log = xes_importer.apply( os.path.join("input_data", "running-example.xes")) net, im, fm = inductive_miner.apply(log) aligned_traces_tr = tr_alg.apply(log, net, im, fm) aligned_traces_alignments = align_alg.apply(log, net, im, fm) evaluation = eval_alg.apply(log, net, im, fm) fitness = rp_fit.apply(log, net, im, fm) precision = precision_evaluator.apply(log, net, im, fm) gen = generalization.apply(log, net, im, fm) sim = simplicity.apply(net)
def test_alphaminer_df(self): log = pd.read_csv(os.path.join("input_data", "running-example.csv")) log = dataframe_utils.convert_timestamp_columns_in_df(log) net, im, fm = alpha_miner.apply(log) aligned_traces_tr = tr_alg.apply(log, net, im, fm) aligned_traces_alignments = align_alg.apply(log, net, im, fm) evaluation = eval_alg.apply(log, net, im, fm) fitness = rp_fit.apply(log, net, im, fm) precision = precision_evaluator.apply(log, net, im, fm) gen = generalization.apply(log, net, im, fm) sim = simplicity.apply(net)
def test_inductiveminer_stream(self): df = pd.read_csv(os.path.join("input_data", "running-example.csv")) df = dataframe_utils.convert_timestamp_columns_in_df(df) stream = log_conversion.apply(df, variant=log_conversion.TO_EVENT_STREAM) net, im, fm = inductive_miner.apply(stream) aligned_traces_tr = tr_alg.apply(stream, net, im, fm) aligned_traces_alignments = align_alg.apply(stream, net, im, fm) evaluation = eval_alg.apply(stream, net, im, fm) fitness = rp_fit.apply(stream, net, im, fm) precision = precision_evaluator.apply(stream, net, im, fm) gen = generalization.apply(stream, net, im, fm) sim = simplicity.apply(net)
def conformance_diagnostics_alignments(log: EventLog, *args) -> List[Dict[str, Any]]: """ Apply the alignments algorithm between a log and a process model. The methods return the full alignment diagnostics. Parameters ------------- log Event log args Specification of the process model Returns ------------- aligned_traces A list of alignments for each trace of the log (in the same order as the traces in the event log) """ if len(args) == 3: if type(args[0]) is PetriNet: # Petri net alignments from pm4py.algo.conformance.alignments import algorithm as alignments return alignments.apply(log, args[0], args[1], args[2]) elif type(args[0]) is dict or type(args[0]) is Counter: # DFG alignments from pm4py.objects.dfg.utils import dfg_alignment return dfg_alignment.apply(log, args[0], args[1], args[2]) elif len(args) == 1: if type(args[0]) is ProcessTree: # process tree alignments from pm4py.algo.conformance.tree_alignments import algorithm as tree_alignments return tree_alignments.apply(log, args[0]) # try to convert to Petri net import pm4py from pm4py.algo.conformance.alignments import algorithm as alignments net, im, fm = pm4py.convert_to_petri_net(*args) return alignments.apply(log, net, im, fm)
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.apply( os.path.join(INPUT_DATA_DIR, "running-example.xes")) net, marking, final_marking = inductive_miner.apply(log) for trace in log: cf_result = \ align_alg.apply(trace, net, marking, final_marking, variant=align_alg.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 execute_script(): log = pm4py.read_xes( os.path.join("..", "tests", "input_data", "receipt.xes")) print("number of cases", len(log)) print("number of events", sum(len(x) for x in log)) print("number of variants", len(pm4py.get_variants(log))) ac = get.get_attribute_values(log, "concept:name") dfg, sa, ea = pm4py.discover_dfg(log) perc = 0.5 dfg, sa, ea, ac = dfg_filtering.filter_dfg_on_activities_percentage( dfg, sa, ea, ac, perc) dfg, sa, ea, ac = dfg_filtering.filter_dfg_on_paths_percentage( dfg, sa, ea, ac, perc) aa = time.time() aligned_traces = dfg_alignment.apply(log, dfg, sa, ea) bb = time.time() net, im, fm = pm4py.convert_to_petri_net(dfg, sa, ea) for trace in aligned_traces: if trace["cost"] != trace["internal_cost"]: print(trace) pass print(bb - aa) print(sum(x["visited_states"] for x in aligned_traces)) print(sum(x["cost"] // 10000 for x in aligned_traces)) gviz = visualizer.apply(dfg, activities_count=ac, parameters={ "start_activities": sa, "end_activities": ea, "format": "svg" }) visualizer.view(gviz) cc = time.time() aligned_traces2 = petri_alignments.apply( log, net, im, fm, variant=petri_alignments.Variants.VERSION_DIJKSTRA_LESS_MEMORY) dd = time.time() print(dd - cc) print(sum(x["visited_states"] for x in aligned_traces2)) print(sum(x["cost"] // 10000 for x in aligned_traces2))
def conformance_alignments(log, petri_net, initial_marking, final_marking): """ Apply the alignments algorithm between a log and a Petri net Parameters ------------- log Event log petri_net Petri net initial_marking Initial marking final_marking Final marking Returns ------------- aligned_traces A list of alignments for each trace of the log """ from pm4py.algo.conformance.alignments import algorithm as alignments return alignments.apply(log, petri_net, initial_marking, final_marking)
t0 = time.time() token_replay.apply(a32f0n00_log, a32f0n00_net, a32f0n00_im, a32f0n00_fm) t1 = time.time() T3[0] = (t1 - t0) T3[2] = math.ceil(T3[1] / (T3[0] + 0.00000001) * 1000.0) print( "TEST 3 - Applying token-based replay between A32F0N00 log and model - %.5f s (test score: %d)" % (T3[0], T3[2])) if ENABLE_TESTS: # TEST 4: perform alignments between A32F0N00 log and model t0 = time.time() alignments.apply( a32f0n00_log, a32f0n00_net, a32f0n00_im, a32f0n00_fm, variant=alignments.Variants.VERSION_DIJKSTRA_NO_HEURISTICS) t1 = time.time() T4[0] = (t1 - t0) T4[2] = math.ceil(T4[1] / (T4[0] + 0.00000001) * 1000.0) print( "TEST 4 - Applying alignments between A32F0N00 log and model - %.5f s (test score: %d)" % (T4[0], T4[2])) if ENABLE_TESTS: # TEST 5: perform playout of the a32f0n00 Petri net t0 = time.time() playout.apply(a32f0n00_net, a32f0n00_im, a32f0n00_fm) t1 = time.time() T5[0] = (t1 - t0)
createAlignments.py : compute alignment costs with pm4py ''' # read parameter : python3 createAlignments.py output_file xes_file pnml_file argv=sys.argv filename=argv[1] net, m0, mf = importer.importer.apply(argv[3]) log = xes_importer.apply(argv[2]) # compute alignment for variants only variants = get_variants.get_variants(log) start=time.time() for l in variants: ali=alignments.apply(variants[l][0],net, m0,mf,variant=versions.dijkstra_no_heuristics) # export in a CSV file with : trace, trace with moves, run, run with moves, cost, frequency if ali: writer=open(filename,"a") alignment=ali["alignment"] cost=ali["cost"] phrase1="" phrase1None="" phrase2="" phrase2None="" for (a,b) in alignment: if a!=">>": # activities are separated with ::: phrase1+=a+":::" phrase1None+=a+":::" if b!=">>" and b!=None:
def test_align(self): log = pm4py.read_xes("input_data/running-example.xes") net, im, fm = pm4py.discover_petri_net_inductive(log, noise_threshold=0.2) aligned_traces = alignments.apply(log, net, im, fm) diagn_df = alignments.get_diagnostics_dataframe(log, aligned_traces)
def get_attributes(log, decision_points, attributes, use_trace_attributes, trace_attributes, k, net, initial_marking, final_marking, decision_points_names, parameters=None): """ This method aims to construct for each decision place a table where for each decision place a list if given with the label of the later decision and as value the given attributes :param log: Log on which the method is applied :param alignments: Computed alignments for a log and a model :param decision_points: Places that have multiple outgoing arcs :param attributes: Attributes that are considered :param use_trace_attributes: If trace attributes have to be considered or not :param trace_attributes: List of trace attributes that are considered :param k: Taking k last activities into account :return: Dictionary that has as keys the decision places. The value for this key is a list. The content of these lists are tuples. The first element of these tuples is information regrading the attributes, the second element of these tuples is the transition which chosen in a decision. """ if parameters is None: parameters = {} I = {} for key in decision_points: I[key] = [] A = {} for attri in attributes: A[attri] = None i = 0 # first, take a look at the variants variants_idxs = variants_module.get_variants_from_log_trace_idx( log, parameters=parameters) one_variant = [] for variant in variants_idxs: one_variant.append(variant) # TODO: Token based replay code mit paramter für nur varianten einbeziehen ausstatten replay_result = token_replay.apply(log, net, initial_marking, final_marking, parameters=parameters) replay_result = simplify_token_replay(replay_result) count = 0 for variant in replay_result: if variant['trace_fitness'] == 1.0: for trace_index in variants_idxs[one_variant[count]]: last_k_list = [None] * k trace = log[trace_index] if use_trace_attributes: for attribute in trace_attributes: # can be done here since trace attributes does not change for whole trace A[attribute] = trace.attributes[attribute] j = 0 # j is a pointer which points to the current event inside a trace for transition in variant['activated_transitions']: for key, value in decision_points_names.items(): if transition.label in value: for element in last_k_list: if element != None: if transition.label != None: I[key].append( (element.copy(), transition.label)) else: I[key].append( (element.copy(), transition.name)) for attri in attributes: # print(variant, transition.label, j) if attri in trace[j]: # only add the attribute information if it is present in the event A[attri] = trace[j][attri] # add A to last_k_list. Using modulo to access correct entry last_k_list[j % k] = A.copy() if transition.label != None: if not j + 1 >= len(trace): # Problem otherwise: If there are tau-transition after the last event related transition, # the pointer j which points to the current event in a trace, gets out of range j += 1 else: example_trace = log[variants_idxs[one_variant[count]][0]] align_parameters = copy(parameters) align_parameters[star.Parameters. PARAM_ALIGNMENT_RESULT_IS_SYNC_PROD_AWARE] = True alignment = ali.apply(example_trace, net, initial_marking, final_marking, parameters=align_parameters)['alignment'] for trace_index in variants_idxs[one_variant[count]]: last_k_list = [None] * k trace = log[trace_index] if use_trace_attributes: for attribute in trace_attributes: # can be done here since trace attributes does not change for whole trace A[attribute] = trace.attributes[attribute] j = 0 for el in alignment: if el[1][1] != '>>': # If move in model for key, value in decision_points.items(): if el[0][1] in value: for element in last_k_list: if element != None: # only add those entries where information is provided if el[1][1] == None: # for some dt algorithms, the entry None might be a problem, since it is left out later I[key].append( (element.copy(), el[0][1])) else: I[key].append( (element.copy(), el[1][1])) if el[1][0] != '>>' and el[1][1] != '>>': # If there is a move in log and model for attri in attributes: if attri in trace[j]: # only add the attribute information if it is present in the event A[attri] = trace[j][attri] # add A to last_k_list. Using modulo to access correct entry last_k_list[j % k] = A.copy() if el[1][0] != '>>': # only go to next event in trace if the current event has been aligned # TODO: Discuss if this is correct or can lead to problems j += 1 count += 1 return I