def get_all_footprints(tree, parameters=None): """ Gets all the footprints for the nodes of the tree Parameters ----------------- tree Process tree parameters Parameters of the algorithm Returns ---------------- dictio Dictionary that associates a footprint to each node of the tree """ if parameters is None: parameters = {} # for each node of the bottom up, proceed to getting the footprints bottomup = bottomup_disc.get_bottomup_nodes(tree, parameters=parameters) footprints_dictio = {} for i in range(len(bottomup)): footprints_dictio[bottomup[i]] = get_footprints(bottomup[i], footprints_dictio) return footprints_dictio
def apply(tree: ProcessTree, parameters : Optional[Dict[Union[str, Parameters], Any]] = None) -> EventLog: """ Performs an extensive playout of the process tree Parameters ------------- tree Process tree parameters Possible parameters, including: - Parameters.MIN_TRACE_LENGTH => minimum length of a trace (default: 1) - Parameters.MAX_TRACE_LENGTH => maximum length of a trace (default: min_allowed_trace_length) - Parameters.MAX_LOOP_OCC => maximum number of occurrences for a loop (default: MAX_TRACE_LENGTH) - Parameters.ACTIVITY_KEY => activity key - Parameters.MAX_LIMIT_NUM_TRACES => maximum number to the limit of traces; the playout shall stop when the number is reached (default: 100000) Returns ------------- log Event log """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) # to save memory in the returned log, allocate each activity once. to know the list of activities of the # process tree, use the footprints module fp_tree = fp_discovery.apply(tree, parameters=parameters) activities = fp_tree["activities"] activities = {act: Event({activity_key: act}) for act in activities} min_allowed_trace_length = bottomup_discovery.get_min_trace_length(tree, parameters=parameters) min_trace_length = exec_utils.get_param_value(Parameters.MIN_TRACE_LENGTH, parameters, 1) max_trace_length = exec_utils.get_param_value(Parameters.MAX_TRACE_LENGTH, parameters, min_allowed_trace_length) max_loop_occ = exec_utils.get_param_value(Parameters.MAX_LOOP_OCC, parameters, int(max_trace_length / 2)) max_limit_num_traces = exec_utils.get_param_value(Parameters.MAX_LIMIT_NUM_TRACES, parameters, 100000) return_set_strings = exec_utils.get_param_value(Parameters.RETURN_SET_STRINGS, parameters, False) bottomup = bottomup_discovery.get_bottomup_nodes(tree, parameters=parameters) min_rem_dict = bottomup_discovery.get_min_rem_dict(tree, parameters=parameters) max_rem_dict = bottomup_discovery.get_max_rem_dict(tree, parameters=parameters) playout_dictio = {} for i in range(len(bottomup)): get_playout(bottomup[i], playout_dictio, min_trace_length, max_trace_length, max_loop_occ, min_rem_dict, max_rem_dict, max_limit_num_traces) tree_playout_traces = playout_dictio[tree][TRACES] if return_set_strings: return tree_playout_traces log = EventLog() for tr0 in tree_playout_traces: trace = Trace() for act in tr0: trace.append(activities[act]) log.append(trace) return log
def apply(pt: ProcessTree, align_result: Union[typing.AlignmentResult, typing.ListAlignments], parameters: Optional[Dict[Any, Any]] = None) -> ProcessTree: """ Annotate a process tree with frequency information (number of events / number of cases), given the results of an alignment performed on the process tree. Parameters ---------------- pt Process tree parameters Parameters of the algorithm, including: - Parameters.NUM_EVENTS_PROPERTY => number of events - Parameters.NUM_CASES_PROPERTY => number of cases Returns ---------------- pt Annotated process tree """ if parameters is None: parameters = {} num_events_property = exec_utils.get_param_value(Parameters.NUM_EVENTS_PROPERTY, parameters, "num_events") num_cases_property = exec_utils.get_param_value(Parameters.NUM_CASES_PROPERTY, parameters, "num_cases") bottomup_nodes = bottomup.get_bottomup_nodes(pt, parameters=parameters) all_paths_open_enabled_events = [] all_paths_open_enabled_cases = [] for trace in align_result: state = trace["state"] paths = [] while state.parent is not None: if state.path: paths.append(state.path) state = state.parent paths.reverse() paths_enabled = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.ENABLED] paths_open = [y[0] for x in paths for y in x if y[1] is ProcessTree.OperatorState.OPEN if y[0] not in paths_enabled] all_paths_open_enabled_events = all_paths_open_enabled_events + paths_enabled + paths_open all_paths_open_enabled_cases = all_paths_open_enabled_cases + list(set(paths_enabled + paths_open)) all_paths_open_enabled_events_counter = Counter(all_paths_open_enabled_events) all_paths_open_enabled_cases_counter = Counter(all_paths_open_enabled_cases) for node in bottomup_nodes: node._properties[num_events_property] = all_paths_open_enabled_events_counter[node] node._properties[num_cases_property] = all_paths_open_enabled_cases_counter[node] return pt
def apply(tree: ProcessTree, trace: Trace, parameters: Optional[Dict[Any, Any]] = None, **kwargs) -> ProcessTree: """ Reduce a process tree replacing the skippable elements that have empty intersection with the trace. Parameters ----------------- tree Process tree trace Trace of an event log parameters Parameters of the algorithm, possible values: Parameters.ACTIVITY_KEY Returns ------------------ tree Reduced process tree """ if parameters is None: parameters = {} activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, xes_constants.DEFAULT_NAME_KEY) activities = set(x[activity_key] for x in trace) tree = deepcopy(tree) from pm4py.algo.discovery.footprints.tree.variants import bottomup as footprints bottomup_nodes = bottomup.get_bottomup_nodes(tree) fps = footprints.get_all_footprints(tree) fps = {id(x): y for x, y in fps.items()} return reduce(bottomup_nodes, fps, activities)
alignments_clean)["average_trace_fitness"] if fitness_al_clean < fitness_im_clean: print("ALERT") input() else: print("OK ALIGNMENTS", fitness_al_clean) precision_im_clean = pm4py.algo.conformance.footprints.util.evaluation.fp_precision( fp_log, fp_tree_clean) precision_im = pm4py.algo.conformance.footprints.util.evaluation.fp_precision( fp_log, fp_tree_im) precision_imf = pm4py.algo.conformance.footprints.util.evaluation.fp_precision( fp_log, fp_tree_imf) precision_imd = pm4py.algo.conformance.footprints.util.evaluation.fp_precision( fp_log, fp_tree_imd) print("IMCLEAN fp-fitness=%.3f fp-precision=%.3f" % (fitness_im_clean, precision_im_clean)) print("IM fp-fitness=%.3f fp-precision=%.3f" % (fitness_im, precision_im)) print("IMf fp-fitness=%.3f fp-precision=%.3f" % (fitness_imf, precision_imf)) print("IMd fp-fitness=%.3f fp-precision=%.3f" % (fitness_imd, precision_imd)) except: bottomup_nodes = bottomup_disc.get_bottomup_nodes(tree_im_clean) for node in bottomup_nodes: if node.parent is None: print(node, node.parent) traceback.print_exc() input()
def apply(tree, conf_results, parameters=None): """ Projects conformance results on top of the process tree Parameters -------------- tree Process tree conf_results Conformance results (footprints on the entire log vs entire model) parameters Parameters of the algorithm Returns -------------- color_map Color map to be provided to the visualization """ if parameters is None: parameters = {} start_activities = {} end_activities = {} if type(conf_results) is list: raise Exception( "the visualization can only be applied with total footprints (not trace-by-trace)!" ) elif type(conf_results) is dict: footprints = conf_results start_activities = conf_results[START_ACTIVITIES] end_activities = conf_results[END_ACTIVITIES] else: footprints = conf_results bottomup_nodes = bottomup_util.get_bottomup_nodes(tree, parameters=parameters) labels_dictio = { x.label: x for x in bottomup_nodes if x.operator is None and x.label is not None } all_fp_dictio = bottomup_discovery.get_all_footprints( tree, parameters=parameters) conf_colors = {} for res in start_activities: if res in labels_dictio: conf_colors[labels_dictio[res]] = FP_START_END_DEV_COLOR for res in end_activities: if res in labels_dictio: conf_colors[labels_dictio[res]] = FP_START_END_DEV_COLOR for res in footprints: if res[0] in labels_dictio and res[1] in labels_dictio: conf_colors[labels_dictio[res[0]]] = FP_DEV_COLOR conf_colors[labels_dictio[res[1]]] = FP_DEV_COLOR for n in bottomup_nodes: if res[0] in all_fp_dictio[n][ Outputs.ACTIVITIES.value] and res[1] in all_fp_dictio[ n][Outputs.ACTIVITIES.value]: conf_colors[n] = FP_DEV_COLOR break return conf_colors