def check_cut_im_plain(self): if pkgutil.find_loader("networkx"): import networkx as nx conn_components = detection_utils.get_connected_components( self.ingoing, self.outgoing, self.activities) this_nx_graph = transform_dfg_to_directed_nx_graph( self.dfg, activities=self.activities) strongly_connected_components = [ list(x) for x in nx.strongly_connected_components(this_nx_graph) ] xor_cut = self.detect_xor(conn_components) if xor_cut[0]: return True, 'concurrent', xor_cut else: sequence_cut = cut_detection.detect_sequential_cut( self, self.dfg, strongly_connected_components) if sequence_cut[0]: return True, 'sequential', sequence_cut else: parallel_cut = self.detect_concurrent() if parallel_cut[0]: return True, 'parallel', parallel_cut else: loop_cut = self.detect_loop() if loop_cut[0]: return True, 'loopCut', loop_cut else: return False, 'noCut', [] else: msg = "networkx is not available. inductive miner cannot be used!" logging.error(msg) raise Exception(msg)
def check_for_cut(self, test_log, deleted_activity=None, parameters=None): if pkgutil.find_loader("networkx"): import networkx as nx if deleted_activity is not None: del self.activities[deleted_activity] if parameters is None: parameters = {} dfg = [(k, v) for k, v in dfg_inst.apply( test_log, parameters=parameters).items() if v > 0] self.dfg = dfg self.outgoing = get_outgoing_edges(self.dfg) self.ingoing = get_ingoing_edges(self.dfg) self.log = test_log conn_components = detection_utils.get_connected_components( self.ingoing, self.outgoing, self.activities) this_nx_graph = transform_dfg_to_directed_nx_graph( self.dfg, activities=self.activities) strongly_connected_components = [ list(x) for x in nx.strongly_connected_components(this_nx_graph) ] # search for cut and return true as soon as a cut is found: xor_cut = self.detect_xor(conn_components) if xor_cut[0]: return True else: sequence_cut = cut_detection.detect_sequential_cut( self, self.dfg, strongly_connected_components) if sequence_cut[0]: return True else: parallel_cut = self.detect_concurrent() if parallel_cut[0]: return True else: loop_cut = self.detect_loop() if loop_cut[0]: return True else: return False else: msg = "networkx is not available. inductive miner cannot be used!" logging.error(msg) raise Exception(msg)
def detect_cut(self, second_iteration=False, parameters=None): if pkgutil.find_loader("networkx"): import networkx as nx if parameters is None: parameters = {} activity_key = exec_utils.get_param_value( Parameters.ACTIVITY_KEY, parameters, pmutil.xes_constants.DEFAULT_NAME_KEY) # check base cases: empty_log = base_case.empty_log(self.log) single_activity = base_case.single_activity(self.log, activity_key) if empty_log: self.detected_cut = 'empty_log' elif single_activity: self.detected_cut = 'single_activity' # if no base cases are found, search for a cut: else: conn_components = detection_utils.get_connected_components( self.ingoing, self.outgoing, self.activities) this_nx_graph = transform_dfg_to_directed_nx_graph( self.dfg, activities=self.activities) strongly_connected_components = [ list(x) for x in nx.strongly_connected_components(this_nx_graph) ] xor_cut = self.detect_xor(conn_components) # the following part searches for a cut in the current log_skeleton # if a cut is found, the log_skeleton is split according to the cut, the resulting logs are saved in new_logs # recursion is used on all the logs in new_logs if xor_cut[0]: logging.debug("xor_cut") self.detected_cut = 'concurrent' new_logs = split.split_xor(xor_cut[1], self.log, activity_key) for i in range(len(new_logs)): new_logs[ i] = filtering_utils.keep_one_trace_per_variant( new_logs[i], parameters=parameters) for l in new_logs: new_dfg = [(k, v) for k, v in dfg_inst.apply( l, parameters=parameters).items() if v > 0] activities = attributes_filter.get_attribute_values( l, activity_key) start_activities = list( start_activities_filter.get_start_activities( l, parameters=parameters).keys()) end_activities = list( end_activities_filter.get_end_activities( l, parameters=parameters).keys()) self.children.append( SubtreePlain(l, new_dfg, self.master_dfg, self.initial_dfg, activities, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, start_activities=start_activities, end_activities=end_activities, initial_start_activities=self. initial_start_activities, initial_end_activities=self. initial_end_activities, parameters=parameters)) else: sequence_cut = cut_detection.detect_sequential_cut( self, self.dfg, strongly_connected_components) if sequence_cut[0]: logging.debug("sequence_cut") new_logs = split.split_sequence( sequence_cut[1], self.log, activity_key) for i in range(len(new_logs)): new_logs[ i] = filtering_utils.keep_one_trace_per_variant( new_logs[i], parameters=parameters) self.detected_cut = "sequential" for l in new_logs: new_dfg = [(k, v) for k, v in dfg_inst.apply( l, parameters=parameters).items() if v > 0] activities = attributes_filter.get_attribute_values( l, activity_key) start_activities = list( start_activities_filter.get_start_activities( l, parameters=parameters).keys()) end_activities = list( end_activities_filter.get_end_activities( l, parameters=parameters).keys()) self.children.append( SubtreePlain( l, new_dfg, self.master_dfg, self.initial_dfg, activities, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, start_activities=start_activities, end_activities=end_activities, initial_start_activities=self. initial_start_activities, initial_end_activities=self. initial_end_activities, parameters=parameters)) else: parallel_cut = self.detect_concurrent() if parallel_cut[0]: logging.debug("parallel_cut") new_logs = split.split_parallel( parallel_cut[1], self.log, activity_key) for i in range(len(new_logs)): new_logs[ i] = filtering_utils.keep_one_trace_per_variant( new_logs[i], parameters=parameters) self.detected_cut = "parallel" for l in new_logs: new_dfg = [(k, v) for k, v in dfg_inst.apply( l, parameters=parameters).items() if v > 0] activities = attributes_filter.get_attribute_values( l, activity_key) start_activities = list( start_activities_filter. get_start_activities( l, parameters=parameters).keys()) end_activities = list( end_activities_filter.get_end_activities( l, parameters=parameters).keys()) self.children.append( SubtreePlain( l, new_dfg, self.master_dfg, self.initial_dfg, activities, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, start_activities=start_activities, end_activities=end_activities, initial_start_activities=self. initial_start_activities, initial_end_activities=self. initial_end_activities, parameters=parameters)) else: loop_cut = self.detect_loop() if loop_cut[0]: logging.debug("loop_cut") new_logs = split.split_loop( loop_cut[1], self.log, activity_key) for i in range(len(new_logs)): new_logs[ i] = filtering_utils.keep_one_trace_per_variant( new_logs[i], parameters=parameters) self.detected_cut = "loopCut" for l in new_logs: new_dfg = [ (k, v) for k, v in dfg_inst.apply( l, parameters=parameters).items() if v > 0 ] activities = attributes_filter.get_attribute_values( l, activity_key) start_activities = list( start_activities_filter. get_start_activities( l, parameters=parameters).keys()) end_activities = list( end_activities_filter. get_end_activities( l, parameters=parameters).keys()) self.children.append( SubtreePlain( l, new_dfg, self.master_dfg, self.initial_dfg, activities, self.counts, self.rec_depth + 1, noise_threshold=self. noise_threshold, start_activities=start_activities, end_activities=end_activities, initial_start_activities=self. initial_start_activities, initial_end_activities=self. initial_end_activities, parameters=parameters)) # if the code gets to this point, there is no base_case and no cut found in the log_skeleton # therefore, we now apply fall through: else: self.apply_fall_through(parameters) else: msg = "networkx is not available. inductive miner cannot be used!" logging.error(msg) raise Exception(msg)
def detect_cut(self): """ Detect generally a cut in the graph (applying all the algorithms) """ if not self.second_iteration: self.second_tree.initialize_tree() self.second_tree.detect_cut() if self.dfg and len(self.activities) > 1: if self.contains_empty_traces: self.traces = Counter( {x: y for x, y in self.traces.items() if len(x) > 0}) conn_components = detection_utils.get_connected_components( self.ingoing, self.outgoing, self.activities) this_nx_graph = detection_utils.transform_dfg_to_directed_nx_graph( self.activities, self.dfg) strongly_connected_components = [ list(x) for x in nx.strongly_connected_components(this_nx_graph) ] xor_cut = cut_detection.detect_xor_cut(self.dfg, conn_components) if xor_cut[0]: for comp in xor_cut[1]: self.detected_cut = "xor" self.cut_value = 4 self.children.append( SubtreeBasic( self.traces, comp, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, parent=self, rec_must_insert_skip=self.rec_must_insert_skip)) else: seq_cut = cut_detection.detect_sequential_cut( self.dfg, strongly_connected_components) if seq_cut[0]: self.detected_cut = "sequential" self.cut_value = 3 for child in seq_cut[1]: self.children.append( SubtreeBasic(self.traces, child, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, parent=self, rec_must_insert_skip=self. rec_must_insert_skip)) else: par_cut = self.detect_parallel_cut() if par_cut[0]: self.detected_cut = "parallel" self.cut_value = 2 for comp in par_cut[1]: self.children.append( SubtreeBasic( self.traces, comp, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, parent=self, rec_must_insert_skip=self. rec_must_insert_skip)) else: loop_cut = cut_detection.detect_loop_cut( self.dfg, self.activities, self.start_activities, self.end_activities) if loop_cut[0]: self.detected_cut = "loopCut" self.detected_cut_add_info = "loop" self.cut_value = 1 for index_enum, child in enumerate(loop_cut[1]): next_subtree = SubtreeBasic( self.traces, child, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, parent=self, rec_must_insert_skip=self. rec_must_insert_skip) self.children.append(next_subtree) else: self.detected_cut = "flower" else: self.detected_cut = "base_xor" kept_tree = self if not self.second_iteration: if self.cut_value >= self.second_tree.cut_value: kept_tree = self else: kept_tree = self.second_tree kept_tree.detect_cut_in_children() return kept_tree
def detect_cut(self, second_iteration=False): """ Detect generally a cut in the graph (applying all the algorithms) """ if self.dfg and len(self.activities) > 1: conn_components = detection_utils.get_connected_components(self.ingoing, self.outgoing, self.activities) this_nx_graph = detection_utils.transform_dfg_to_directed_nx_graph(self.activities, self.dfg) strongly_connected_components = [list(x) for x in nx.strongly_connected_components(this_nx_graph)] xor_cut = cut_detection.detect_xor_cut(self.dfg, conn_components) if xor_cut[0]: for comp in xor_cut[1]: new_dfg = filter_dfg_on_act(self.dfg, comp) self.detected_cut = "xor" self.children.append( SubtreeDFGBased(new_dfg, self.master_dfg, self.initial_dfg, comp, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, initial_start_activities=self.initial_start_activities, initial_end_activities=self.initial_end_activities)) else: seq_cut = cut_detection.detect_sequential_cut(self.dfg, strongly_connected_components) if seq_cut[0]: self.detected_cut = "sequential" for child in seq_cut[1]: dfg_child = filter_dfg_on_act(self.dfg, child) self.children.append( SubtreeDFGBased(dfg_child, self.master_dfg, self.initial_dfg, child, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, initial_start_activities=self.initial_start_activities, initial_end_activities=self.initial_end_activities)) self.put_skips_in_seq_cut() else: par_cut = self.detect_parallel_cut() if par_cut[0]: self.detected_cut = "parallel" for comp in par_cut[1]: new_dfg = filter_dfg_on_act(self.dfg, comp) self.children.append( SubtreeDFGBased(new_dfg, self.master_dfg, new_dfg, comp, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, initial_start_activities=self.initial_start_activities, initial_end_activities=self.initial_end_activities)) else: loop_cut = cut_detection.detect_loop_cut(self.dfg, self.activities, self.start_activities, self.end_activities) if loop_cut[0]: self.detected_cut = "loopCut" for index_enum, child in enumerate(loop_cut[1]): dfg_child = filter_dfg_on_act(self.dfg, child) next_subtree = SubtreeDFGBased(dfg_child, self.master_dfg, self.initial_dfg, child, self.counts, self.rec_depth + 1, noise_threshold=self.noise_threshold, initial_start_activities=self.initial_start_activities, initial_end_activities=self.initial_end_activities) if loop_cut[3]: next_subtree.must_insert_skip = True self.children.append(next_subtree) else: if self.noise_threshold > 0: if not second_iteration: self.initialize_tree(self.dfg, self.initial_dfg, None, second_iteration=True) else: pass self.detected_cut = "flower" else: self.detected_cut = "base_xor" self.must_insert_skip = False