def apply_tree_dfg(dfg, parameters=None, activities=None, contains_empty_traces=False, start_activities=None, end_activities=None): """ Apply the IMDF algorithm to a DFG graph obtaining a process tree Parameters ---------- dfg Directly-follows graph parameters Parameters of the algorithm, including: Parameters.ACTIVITY_KEY -> attribute of the log to use as activity name (default concept:name) activities Activities of the process (default None) contains_empty_traces Boolean value that is True if the event log from which the DFG has been extracted contains empty traces start_activities If provided, the start activities of the log end_activities If provided, the end activities of the log Returns ---------- tree Process tree """ if parameters is None: parameters = {} noise_threshold = exec_utils.get_param_value(Parameters.NOISE_THRESHOLD, parameters, 0.0) if type(dfg) is Counter or type(dfg) is dict: newdfg = [] for key in dfg: value = dfg[key] newdfg.append((key, value)) dfg = newdfg c = Counts() s = SubtreeDFGBased(dfg, dfg, dfg, activities, c, 0, noise_threshold=noise_threshold, initial_start_activities=start_activities, initial_end_activities=end_activities) tree_repr = get_tree_repr_dfg_based.get_repr( s, 0, contains_empty_traces=contains_empty_traces) return tree_repr
def apply_tree_dfg(dfg, parameters, activities=None, contains_empty_traces=False): """ Apply the IMDF algorithm to a DFG graph obtaining a process tree Parameters ---------- dfg Directly-follows graph parameters Parameters of the algorithm, including: pmutil.constants.PARAMETER_CONSTANT_ACTIVITY_KEY -> attribute of the log to use as activity name (default concept:name) activities Activities of the process (default None) contains_empty_traces Boolean value that is True if the event log from which the DFG has been extracted contains empty traces Returns ---------- tree Process tree """ if parameters is None: parameters = {} noise_threshold = shared_constants.NOISE_THRESHOLD if "noiseThreshold" in parameters: noise_threshold = parameters["noiseThreshold"] if type(dfg) is Counter or type(dfg) is dict: newdfg = [] for key in dfg: value = dfg[key] newdfg.append((key, value)) dfg = newdfg c = Counts() s = Subtree(dfg, dfg, dfg, activities, c, 0, noise_threshold=noise_threshold) tree_repr = get_tree_repr_imdfa.get_repr( s, 0, contains_empty_traces=contains_empty_traces) return tree_repr
def apply_internal(traces, parameters=None): if parameters is None: parameters = {} noise_threshold = shared_constants.NOISE_THRESHOLD c = Counts() s = SubtreeBasic(traces, None, c, rec_depth=0, noise_threshold=noise_threshold) s.initialize_tree() s = s.detect_cut() tree_repr = get_tree_repr.get_repr( s, 0, contains_empty_traces=s.contains_empty_traces) #tree_repr = tree_util.fold(tree_repr) return tree_repr
def apply(tree, parameters=None): """ Conversion Process Tree to PetriNet. Parameters ----------- tree Process tree parameters PARAM_CHILD_LOCK Returns ----------- net Petri net initial_marking Initial marking final_marking Final marking """ counts = Counts() net = petri.petrinet.PetriNet('imdf_net_' + str(time.time())) initial_marking = Marking() final_marking = Marking() source = get_new_place(counts) source.name = SOURCE_NAME sink = get_new_place(counts) sink.name = SINK_NAME net.places.add(source) net.places.add(sink) initial_marking[source] = 1 final_marking[sink] = 1 generate_pn(tree, net, source, sink, counts, parameters) return net, initial_marking, final_marking
def apply_tree(log, parameters): """ Apply the IM_FF algorithm to a log obtaining a process tree Parameters ---------- log Log parameters Parameters of the algorithm, including: Parameters.ACTIVITY_KEY -> attribute of the log to use as activity name (default concept:name) Returns ---------- process_tree Process tree """ if parameters is None: parameters = {} if pkgutil.find_loader("pandas"): import pandas as pd from pm4py.statistics.variants.pandas import get as variants_get if type(log) is pd.DataFrame: vars = variants_get.get_variants_count(log, parameters=parameters) return apply_tree_variants(vars, parameters=parameters) activity_key = exec_utils.get_param_value(Parameters.ACTIVITY_KEY, parameters, pmutil.xes_constants.DEFAULT_NAME_KEY) log = converter.apply(log, parameters=parameters) # keep only the activity attribute (since the others are not used) log = filtering_utils.keep_only_one_attribute_per_event(log, activity_key) noise_threshold = exec_utils.get_param_value(Parameters.NOISE_THRESHOLD, parameters, shared_constants.NOISE_THRESHOLD_IMF) dfg = [(k, v) for k, v in dfg_inst.apply(log, parameters=parameters).items() if v > 0] c = Counts() activities = attributes_get.get_attribute_values(log, activity_key) start_activities = list(start_activities_get.get_start_activities(log, parameters=parameters).keys()) end_activities = list(end_activities_get.get_end_activities(log, parameters=parameters).keys()) contains_empty_traces = False traces_length = [len(trace) for trace in log] if traces_length: contains_empty_traces = min([len(trace) for trace in log]) == 0 # set the threshold parameter based on f and the max value in the dfg: max_value = 0 for key, value in dfg: if value > max_value: max_value = value threshold = noise_threshold * max_value recursion_depth = 0 sub = subtree.make_tree(log, dfg, dfg, dfg, activities, c, recursion_depth, noise_threshold, threshold, start_activities, end_activities, start_activities, end_activities, parameters=parameters) process_tree = get_tree_repr_implain.get_repr(sub, 0, contains_empty_traces=contains_empty_traces) # Ensures consistency to the parent pointers in the process tree tree_consistency.fix_parent_pointers(process_tree) # Fixes a 1 child XOR that is added when single-activities flowers are found tree_consistency.fix_one_child_xor_flower(process_tree) # folds the process tree (to simplify it in case fallthroughs/filtering is applied) process_tree = util.fold(process_tree) return process_tree
def apply_tree_dfg(dfg, parameters=None, activities=None, contains_empty_traces=False, start_activities=None, end_activities=None): """ Apply the IMDF algorithm to a DFG graph obtaining a process tree Parameters ---------- dfg Directly-follows graph parameters Parameters of the algorithm, including: Parameters.ACTIVITY_KEY -> attribute of the log_skeleton to use as activity name (default concept:name) activities Activities of the process (default None) contains_empty_traces Boolean value that is True if the event log_skeleton from which the DFG has been extracted contains empty traces start_activities If provided, the start activities of the log_skeleton end_activities If provided, the end activities of the log_skeleton Returns ---------- tree Process tree """ if parameters is None: parameters = {} noise_threshold = exec_utils.get_param_value(Parameters.NOISE_THRESHOLD, parameters, 0.0) if type(dfg) is Counter or type(dfg) is dict: newdfg = [] for key in dfg: value = dfg[key] newdfg.append((key, value)) dfg = newdfg c = Counts() s = SubtreeDFGBased(dfg, dfg, dfg, activities, c, 0, noise_threshold=noise_threshold, initial_start_activities=start_activities, initial_end_activities=end_activities) tree_repr = get_tree_repr_dfg_based.get_repr( s, 0, contains_empty_traces=contains_empty_traces) # Ensures consistency to the parent pointers in the process tree tree_consistency.fix_parent_pointers(tree_repr) # Fixes a 1 child XOR that is added when single-activities flowers are found tree_consistency.fix_one_child_xor_flower(tree_repr) # folds the process tree (to simplify it in case fallthroughs/filtering is applied) tree_repr = util.fold(tree_repr) return tree_repr
def apply(tree, parameters=None): """ Apply from Process Tree to Petri net Parameters ----------- tree Process tree parameters Parameters of the algorithm Returns ----------- net Petri net initial_marking Initial marking final_marking Final marking """ if parameters is None: parameters = {} del parameters counts = Counts() net = petri.petrinet.PetriNet('imdf_net_' + str(time.time())) initial_marking = Marking() final_marking = Marking() source = get_new_place(counts) source.name = "source" sink = get_new_place(counts) sink.name = "sink" net.places.add(source) net.places.add(sink) initial_marking[source] = 1 final_marking[sink] = 1 initial_mandatory = check_tau_mandatory_at_initial_marking(tree) final_mandatory = check_tau_mandatory_at_final_marking(tree) if initial_mandatory: initial_place = get_new_place(counts) net.places.add(initial_place) tau_initial = get_new_hidden_trans(counts, type_trans="tau") net.transitions.add(tau_initial) petri.utils.add_arc_from_to(source, tau_initial, net) petri.utils.add_arc_from_to(tau_initial, initial_place, net) else: initial_place = source if final_mandatory: final_place = get_new_place(counts) net.places.add(final_place) tau_final = get_new_hidden_trans(counts, type_trans="tau") net.transitions.add(tau_final) petri.utils.add_arc_from_to(final_place, tau_final, net) petri.utils.add_arc_from_to(tau_final, sink, net) else: final_place = sink net, counts, last_added_place = recursively_add_tree( tree, net, initial_place, final_place, counts, 0) net = petri_cleaning.clean_duplicate_transitions(net) return net, initial_marking, final_marking
def apply_tree(log, parameters=None): """ Apply the IM algorithm to a log obtaining a process tree Parameters ---------- log Log parameters Parameters of the algorithm, including: Parameters.ACTIVITY_KEY -> attribute of the log to use as activity name (default concept:name) Returns ---------- process_tree Process tree """ if parameters is None: parameters = {} if type(log) is pd.DataFrame: vars = variants_get.get_variants_count(log, parameters=parameters) return apply_tree_variants(vars, parameters=parameters) else: activity_key = exec_utils.get_param_value( Parameters.ACTIVITY_KEY, parameters, pmutil.xes_constants.DEFAULT_NAME_KEY) log = converter.apply(log, parameters=parameters) # since basic IM is influenced once per variant, it makes sense to keep one trace per variant log = filtering_utils.keep_one_trace_per_variant(log, parameters=parameters) # keep only the activity attribute (since the others are not used) log = filtering_utils.keep_only_one_attribute_per_event( log, activity_key) dfg = [(k, v) for k, v in dfg_inst.apply(log, parameters=parameters).items() if v > 0] c = Counts() activities = attributes_filter.get_attribute_values(log, activity_key) start_activities = list( start_activities_filter.get_start_activities( log, parameters=parameters).keys()) end_activities = list( end_activities_filter.get_end_activities( log, parameters=parameters).keys()) contains_empty_traces = False traces_length = [len(trace) for trace in log] if traces_length: contains_empty_traces = min([len(trace) for trace in log]) == 0 recursion_depth = 0 sub = subtree.make_tree(log, dfg, dfg, dfg, activities, c, recursion_depth, 0.0, start_activities, end_activities, start_activities, end_activities, parameters) process_tree = get_tree_repr_implain.get_repr( sub, 0, contains_empty_traces=contains_empty_traces) # Ensures consistency to the parent pointers in the process tree tree_consistency.fix_parent_pointers(process_tree) # Fixes a 1 child XOR that is added when single-activities flowers are found tree_consistency.fix_one_child_xor_flower(process_tree) # folds the process tree (to simplify it in case fallthroughs/filtering is applied) process_tree = util.fold(process_tree) return process_tree