def put_skips_in_loop_cut(self): """ Puts the skips in loop cuts """ all_start_activities = infer_start_activities_from_prev_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities) if not all_start_activities: self.children[0].must_insert_skip = True self.children[1].must_insert_skip = True return
def detect_loop_cut(self): """ Detect loop cut """ start_activities = self.start_activities if len(start_activities) == 0: start_activities = infer_start_activities_from_prev_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities) end_activities = self.end_activities end_activities = list(set(end_activities) - set(start_activities)) if len(end_activities) == 0: end_activities = infer_end_activities_from_succ_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities) end_activities = list(set(end_activities) - set(start_activities)) if len(end_activities) == 0: end_activities = infer_end_activities_from_succ_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities, include_self=False) all_end_activities = copy(end_activities) end_activities = list(set(end_activities) - set(start_activities)) end_activities_that_are_also_start = list(set(all_end_activities) - set(end_activities)) do_part = [] redo_part = [] dangerous_redo_part = [] exit_part = [] for sa in start_activities: do_part.append(sa) for ea in end_activities: exit_part.append(ea) for act in self.activities: if act not in start_activities and act not in end_activities: input_connected_activities = get_all_activities_connected_as_input_to_activity(self.dfg, act) output_connected_activities = get_all_activities_connected_as_output_to_activity(self.dfg, act) if set(output_connected_activities).issubset(start_activities) and set(start_activities).issubset( output_connected_activities): if len(input_connected_activities.intersection(exit_part)) > 0: dangerous_redo_part.append(act) redo_part.append(act) else: do_part.append(act) if len(do_part) > 0 and (len(redo_part) > 0 or len(exit_part)) > 0: if len(redo_part) > 0: return [True, [do_part + exit_part, redo_part], len(end_activities_that_are_also_start) > 0] else: return [True, [do_part, redo_part + exit_part], len(end_activities_that_are_also_start) > 0] return [False, [], []]
def check_sa_ea_for_each_branch(self, conn_components): """ Checks if each branch of the parallel cut has a start and an end node of the subgraph Parameters -------------- conn_components Parallel cut Returns ------------- boolean True if each branch of the parallel cut has a start and an end node """ parallel_cut_sa = list( set(self.initial_start_activities).union( infer_start_activities_from_prev_connections_and_current_dfg( self.initial_dfg, self.dfg, self.activities, include_self=False)).intersection(self.activities)) parallel_cut_ea = list( set(self.initial_end_activities).union( infer_end_activities_from_succ_connections_and_current_dfg( self.initial_dfg, self.dfg, self.activities, include_self=False)).intersection(self.activities)) if conn_components is None: return False for comp in conn_components: comp_sa_ok = False comp_ea_ok = False for sa in parallel_cut_sa: if sa in comp: comp_sa_ok = True break for ea in parallel_cut_ea: if ea in comp: comp_ea_ok = True break if not (comp_sa_ok and comp_ea_ok): return False return True
def put_skips_in_seq_cut(self): """ Puts the skips in sequential cut """ # first, put skips when in some cut there is an ending activity in_end_act = set(self.initial_end_activities) i = 0 while i < len(self.children) - 1: activities_set = set(self.children[i].activities) intersection = activities_set.intersection(in_end_act) if len(intersection) > 0: j = i + 1 while j < len(self.children): self.children[j].must_insert_skip = True j = j + 1 i = i + 1 # second, put skips when in some cut you are not sure to pass through i = 0 while i < len(self.children) - 1: act_i = self.children[i].activities act_i_output_appearences = {} max_value = i for act in act_i: if act in self.outgoing: for out_act in self.outgoing[act]: act_i_output_appearences[out_act] = len(self.children) - 1 j = i + 1 while j < len(self.children): act_children = self.children[j].activities for act in act_children: if act in act_i_output_appearences and act_i_output_appearences[act] == len(self.children) - 1: act_i_output_appearences[act] = j if j > max_value: max_value = j j = j + 1 j = i + 1 while j < max_value: self.children[j].must_insert_skip = True j = j + 1 i = i + 1 # third, put skips when some input activities do not pass there out_start_activities = infer_start_activities_from_prev_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities, include_self=False) out_start_activities_diff = out_start_activities - set(self.activities) for act in out_start_activities_diff: out_act_here = set() for el in self.initial_dfg: if el[0][0] == act and el[0][1] in self.activities: out_act_here.add(el[0][1]) i = 0 while i < len(self.children): child_act = set(self.children[i].activities) inte = child_act.intersection(out_act_here) if inte: for el in inte: out_act_here.remove(el) if len(out_act_here) > 0: self.children[i].must_insert_skip = True i = i + 1 # fourth, put skips until all start activities are reached remaining_act = self.start_activities i = 0 while i < len(self.children): child_act = set(self.children[i].activities) inte = child_act.intersection(remaining_act) if inte: for el in inte: remaining_act.remove(el) if len(remaining_act) > 0: self.children[i].must_insert_skip = True i = i + 1
def __init__(self, dfg, master_dfg, initial_dfg, activities, counts, rec_depth, noise_threshold=0, initial_start_activities=None, initial_end_activities=None): """ Constructor Parameters ----------- dfg Directly follows graph of this subtree master_dfg Original DFG initial_dfg Referral directly follows graph that should be taken in account adding hidden/loop transitions activities Activities of this subtree counts Shared variable rec_depth Current recursion depth noise_threshold Noise threshold initial_start_activities Start activities of the log initial_end_activities End activities of the log """ self.master_dfg = copy(master_dfg) self.initial_dfg = copy(initial_dfg) self.counts = counts self.rec_depth = rec_depth self.noise_threshold = noise_threshold self.initial_start_activities = initial_start_activities if self.initial_start_activities is None: self.initial_start_activities = infer_start_activities(master_dfg) self.initial_end_activities = initial_end_activities if self.initial_end_activities is None: self.initial_end_activities = infer_end_activities(master_dfg) self.second_iteration = None self.activities = None self.dfg = None self.outgoing = None self.ingoing = None self.self_loop_activities = None self.initial_ingoing = None self.initial_outgoing = None self.activities_direction = None self.activities_dir_list = None self.negated_dfg = None self.negated_activities = None self.negated_outgoing = None self.negated_ingoing = None self.detected_cut = None self.children = None self.must_insert_skip = False self.need_loop_on_subtree = False self.initialize_tree(dfg, initial_dfg, activities) # start/end activities of the initial log intersected with the current set of activities self.initial_start_activities = list(set(self.initial_start_activities).intersection(set(self.activities))) self.initial_end_activities = list(set(self.initial_end_activities).intersection(set(self.activities))) if rec_depth > 0: self.start_activities = list( set(self.initial_start_activities).union(infer_start_activities(self.dfg)).union( infer_start_activities_from_prev_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities)).intersection( self.activities)) self.end_activities = list(set(self.initial_end_activities).union(infer_end_activities(self.dfg)).union( infer_end_activities_from_succ_connections_and_current_dfg(self.initial_dfg, self.dfg, self.activities)).intersection( self.activities)) else: self.start_activities = self.initial_start_activities self.end_activities = self.initial_end_activities self.detect_cut()