def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        # remove all nodes of degree 0 or 1 as they can't be part of any cycles
        remove_node_deg_01(graph)

        nodes = graph.nodes()
        for L in range(0, len(nodes) + 1):
            for subset in itertools.combinations(nodes, L):
                # make an induced subgraph with the current node subset removed
                new_graph = graph_minus(graph, subset)

                if is_acyclic(new_graph):
                    return subset

        return set()
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        # remove all nodes of degree 0 or 1 as they can't be part of any cycles
        remove_node_deg_01(graph)

        # reset the cache dict
        self.cacheDict = {}
        return self._get_fbvs(graph)
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        # remove all nodes of degree 0 or 1 as they can't be part of any cycles
        remove_node_deg_01(graph)

        # reset the cache dict
        self.cacheDict = {}
        return self._get_fbvs(graph)
Пример #4
0
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        # remove all nodes of degree 0 or 1 as they can't be part of any cycles
        remove_node_deg_01(graph)

        # get the set of nodes that is in at least one cycle
        cycles = cycle_basis(graph)
        nodes_in_cycles = set([item for sublist in cycles for item in sublist])

        for L in range(0, len(nodes_in_cycles) + 1):
            for subset in itertools.combinations(nodes_in_cycles, L):
                # make an induced subgraph with the current node subset removed
                new_graph = graph_minus(graph, subset)

                if is_acyclic(new_graph):
                    return subset

        return set()
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        if type(graph) is not MultiGraph:
            graph = MultiGraph(graph)

        for i in range(1, graph.number_of_nodes()):
            result = self.get_fbvs_max_size(graph, i)
            if result is not None:
                return result  # in the worst case, result is n-2 nodes
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        # remove all nodes of degree 0 or 1 as they can't be part of any cycles
        remove_node_deg_01(graph)

        # get the set of nodes that is in at least one cycle
        cycles = cycle_basis(graph)
        nodes_in_cycles = set([item for sublist in cycles for item in sublist])

        for L in range(0, len(nodes_in_cycles) + 1):
            for subset in itertools.combinations(nodes_in_cycles, L):
                # make an induced subgraph with the current node subset removed
                new_graph = graph_minus(graph, subset)

                if is_acyclic(new_graph):
                    return subset

        return set()
Пример #7
0
    def get_fbvs(self, graph: Graph):
        if is_acyclic(graph):
            return set()

        if type(graph) is not MultiGraph:
            graph = MultiGraph(graph)

        for i in range(1, graph.number_of_nodes()):
            result = self.get_fbvs_max_size(graph, i)
            if result is not None:
                return result  # in the worst case, result is n-2 nodes
    def fvs_disjoint(self, g: MultiGraph, w: set, k: int) -> set:
        """
        Given an undirected graph G and a fbvs W in G of size at least (k + 1), is it possible to construct
        a fbvs X of size at most k using only the nodes of G - W?

        :return: The set X, or `None` if it's not possible to construct X
        """

        # If G[W] isn't a forest, then a solution X not using W can't remove W's cycles.
        if not is_acyclic(g.subgraph(w)):
            return None

        # Apply reductions exhaustively.
        k, soln_redux = self.apply_reductions(g, w, k)

        # If k becomes negative, it indicates that the reductions included
        # more than k nodes. In other word, reduction 2 shows that there are more than k nodes
        # in G - W that will create cycle in W. Hence, no solution of size <= k exists.
        if k < 0:
            return None

        # From now onwards we assume that k >= 0

        # If G has been reduced to nothing and k is >= 0 then the solution generated by the reductions
        # is already optimal.
        if len(g) == 0:
            return soln_redux

        # Recall that H is a forest as W is a feedback vertex set. Thus H has a node x of degree at most 1.
        # Find an x in H of degree at most 1.
        h = graph_minus(g, w)
        x = None
        for v in h.nodes():
            if h.degree(v) <= 1:
                x = v
                break
        assert x is not None, "There must be at least one node x of degree at most 1"

        # Branch on (G - {x}, W, k−1) and (G, W ∪ {x}, k)
        # G is copied in the left branch (as it is modified), but passed directly in the right.
        soln_left = self.fvs_disjoint(graph_minus(g, {x}), w, k - 1)

        if soln_left is not None:
            return soln_redux.union(soln_left).union({x})

        soln_right = self.fvs_disjoint(g, w.union({x}), k)

        if soln_right is not None:
            return soln_redux.union(soln_right)

        return None
    def reduction2(self, g: MultiGraph, w: set, h: MultiGraph, k: int) -> (int, int, bool):
        """
        If there exists a node v in H such that G[W ∪ {v}]
        contains a cycle, then include v in the solution, delete v and decrease the
        parameter by 1. That is, the new instance is (G - {v}, W, k - 1).

        If v introduces a cycle, it must be part of X as none of the vertices in W
        will be available to neutralise this cycle.
        """
        for v in h.nodes():
            # Check if G[W ∪ {v}] contains a cycle.
            if not is_acyclic(g.subgraph(w.union({v}))):
                g.remove_node(v)
                h.remove_nodes_from([v])
                return k - 1, v, True
        return k, None, False