Exemple #1
0
    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)
Exemple #2
0
    def detect_concurrent(self):
        if self.contains_empty_trace():
            return [False, []]
        inverted_dfg = [
        ]  # create an inverted dfg, the connected components of this dfg are the split
        for a in self.activities:
            for b in self.activities:
                if a != b:
                    if not self.is_followed_by(self.dfg, a,
                                               b) or not self.is_followed_by(
                                                   self.dfg, b, a):
                        if ((a, b), 1) not in inverted_dfg:
                            inverted_dfg.append(((a, b), 1))
                            inverted_dfg.append(((b, a), 1))
        self.inverted_dfg = inverted_dfg
        new_ingoing = get_ingoing_edges(inverted_dfg)
        new_outgoing = get_outgoing_edges(inverted_dfg)
        conn = detection_utils.get_connected_components(
            new_ingoing, new_outgoing, self.activities)
        if len(conn) > 1:
            conn = parallel_cut_utils.check_par_cut(conn, self.ingoing,
                                                    self.outgoing)
            if len(conn) > 1:
                if parallel_cut_utils.check_sa_ea_for_each_branch(
                        conn, self.start_activities, self.end_activities):
                    return [True, conn]

        return [False, []]
Exemple #3
0
    def detect_parallel_cut(self, orig_conn_components, this_nx_graph,
                            strongly_connected_components):
        """
        Detects parallel cut

        Parameters
        --------------
        orig_conn_components
            Connected components of the graph
        this_nx_graph
            NX graph calculated on the DFG
        strongly_connected_components
            Strongly connected components
        """
        conn_components = detection_utils.get_connected_components(
            self.negated_ingoing, self.negated_outgoing, self.activities)

        if len(conn_components) > 1:
            conn_components = parallel_cut_utils.check_par_cut(
                conn_components, self.ingoing, self.outgoing)

            if self.check_sa_ea_for_each_branch(conn_components):
                return [True, conn_components]

        return [False, []]
    def detect_parallel_cut(self):
        """
        Detects parallel cut
        """
        conn_components = detection_utils.get_connected_components(self.negated_ingoing, self.negated_outgoing, self.activities)

        if len(conn_components) > 1:
            conn_components = detection_utils.check_par_cut(conn_components, self.ingoing, self.outgoing)
            if conn_components is not None:
                for comp in conn_components:
                    comp_ok = False
                    for el in self.initial_dfg:
                        if (el[0][0] in comp and el[0][1] not in self.activities) or (
                                el[0][1] in comp and el[0][0] not in self.activities):
                            comp_ok = True
                            break
                    if self.rec_depth == 0:
                        for sa in self.start_activities:
                            if sa in comp:
                                comp_ok = True
                                #print("siii")
                                break
                    if not comp_ok:
                        return [False, conn_components]
                return [True, conn_components]

        return [False, []]
Exemple #5
0
    def detect_parallel_cut(self):
        """
        Detects parallel cut
        """
        conn_components = detection_utils.get_connected_components(self.negated_ingoing, self.negated_outgoing, self.activities)

        if len(conn_components) > 1:
            conn_components = detection_utils.check_par_cut(conn_components, self.ingoing, self.outgoing)

            if self.check_sa_ea_for_each_branch(conn_components):
                return [True, conn_components]

        return [False, []]
Exemple #6
0
    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)
Exemple #7
0
    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)
Exemple #8
0
    def detect_cut(self, second_iteration=False):
        """
        Detect generally a cut in the graph (applying all the algorithms)
        """
        if pkgutil.find_loader("networkx"):
            import networkx as nx
        else:
            msg = "networkx is not available. inductive miner cannot be used!"
            logging.error(msg)
            raise Exception(msg)

        if self.dfg:

            this_nx_graph = transform_dfg_to_directed_nx_graph(self.dfg, activities=self.activities)
            conn_components = detection_utils.get_connected_components(self.ingoing, self.outgoing, self.activities)
            strongly_connected_components = [list(x) for x in nx.strongly_connected_components(this_nx_graph)]

            xor_cut = self.detect_xor_cut(conn_components, this_nx_graph, strongly_connected_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 = self.detect_sequential_cut(conn_components, this_nx_graph, 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(conn_components, this_nx_graph, strongly_connected_components)
                    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 = self.detect_loop_cut(conn_components, this_nx_graph, strongly_connected_components)
                        if loop_cut[0]:
                            if loop_cut[2]:
                                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:
                                self.detected_cut = "sequential"
                                self.need_loop_on_subtree = True
                                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)
                                    self.children.append(next_subtree)
                                    next_subtree.must_insert_skip = True
                        else:
                            if self.noise_threshold > 0:
                                if not second_iteration:
                                    self.initialize_tree(self.dfg, self.initial_dfg, None, second_iteration=True)
                                else:
                                    self.detected_cut = "flower"
                            else:
                                self.detected_cut = "flower"

        else:
            self.detected_cut = "base_xor"
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    def detect_loop(self):
        # p0 is part of return value, it contains the partition of activities
        # write all start and end activities in p1
        if self.contains_empty_trace():
            return [False, []]
        start_activities = list(
            start_activities_filter.get_start_activities(
                self.log, parameters=self.parameters).keys())
        end_activities = list(
            end_activities_filter.get_end_activities(
                self.log, parameters=self.parameters).keys())
        p1 = []
        for act in start_activities:
            if act not in p1:
                p1.append(act)
        for act in end_activities:
            if act not in p1:
                p1.append(act)

        # create new dfg without the transitions to start and end activities
        new_dfg = copy(self.dfg)
        copy_dfg = copy(new_dfg)
        for ele in copy_dfg:
            if ele[0][0] in p1 or ele[0][1] in p1:
                new_dfg.remove(ele)
        # get connected components of this new dfg
        new_ingoing = get_ingoing_edges(new_dfg)
        new_outgoing = get_outgoing_edges(new_dfg)
        # it was a pain in the *** to get a working directory of the current_activities, as we can't iterate ove the dfg
        current_activities = {}
        for element in self.activities:
            if element not in p1:
                current_activities.update({element: 1})
        p0 = detection_utils.get_connected_components(new_ingoing,
                                                      new_outgoing,
                                                      current_activities)
        p0.insert(0, p1)

        iterable_dfg = []
        for i in range(0, len(self.dfg)):
            iterable_dfg.append(self.dfg[i][0])
        # p0 is like P1,P2,...,Pn in line 3 on page 190 of the IM Thesis
        # check for subsets in p0 that have connections to and end or from a start activity
        p0_copy = []
        for int_el in p0:
            p0_copy.append(int_el)
        for element in p0_copy:  # for every set in p0
            removed = False
            if element in p0 and element != p0[0]:
                for act in element:  # for every activity in this set
                    for e in end_activities:  # for every end activity
                        if e not in start_activities:
                            if (act, e) in iterable_dfg:  # check if connected
                                # is there an element in dfg pointing from any act in a subset of p0 to an end activity
                                for activ in element:
                                    if activ not in p0[0]:
                                        p0[0].append(activ)
                                if element in p0:
                                    p0.remove(
                                        element
                                    )  # remove subsets that are connected to an end activity
                                removed = True
                                break
                    if removed:
                        break
                    for s in start_activities:
                        if s not in end_activities:
                            if not removed:
                                if (s, act) in iterable_dfg:
                                    for acti in element:
                                        if acti not in p0[0]:
                                            p0[0].append(acti)
                                    if element in p0:
                                        p0.remove(
                                            element
                                        )  # remove subsets that are connected to an end activity
                                    removed = True
                                    break
                            else:
                                break
                    if removed:
                        break

        iterable_dfg = []
        for i in range(0, len(self.dfg)):
            iterable_dfg.append(self.dfg[i][0])

        p0_copy = []
        for int_el in p0:
            p0_copy.append(int_el)
        for element in p0_copy:
            if element in p0 and element != p0[0]:
                for act in element:
                    for e in self.end_activities:
                        if (
                                e, act
                        ) in iterable_dfg:  # get those act, that are connected from an end activity
                            for e2 in self.end_activities:  # check, if the act is connected from all end activities
                                if (e2, act) not in iterable_dfg:
                                    for acti in element:
                                        if acti not in p0[0]:
                                            p0[0].append(acti)
                                    if element in p0:
                                        p0.remove(
                                            element
                                        )  # remove subsets that are connected to an end activity
                                    break
                    for s in self.start_activities:
                        if (
                                act, s
                        ) in iterable_dfg:  # same as above (in this case for activities connected to
                            # a start activity)
                            for s2 in self.start_activities:
                                if (act, s2) not in iterable_dfg:
                                    for acti in element:
                                        if acti not in p0[0]:
                                            p0[0].append(acti)
                                    if element in p0:
                                        p0.remove(
                                            element
                                        )  # remove subsets that are connected to an end activity
                                    break

        if len(p0) > 1:
            return [True, p0]
        else:
            return [False, []]