| """ Functions related to graph covers.""" |
|
|
| from functools import partial |
| from itertools import chain |
|
|
| import networkx as nx |
| from networkx.utils import arbitrary_element, not_implemented_for |
|
|
| __all__ = ["min_edge_cover", "is_edge_cover"] |
|
|
|
|
| @not_implemented_for("directed") |
| @not_implemented_for("multigraph") |
| @nx._dispatchable |
| def min_edge_cover(G, matching_algorithm=None): |
| """Returns the min cardinality edge cover of the graph as a set of edges. |
| |
| A smallest edge cover can be found in polynomial time by finding |
| a maximum matching and extending it greedily so that all nodes |
| are covered. This function follows that process. A maximum matching |
| algorithm can be specified for the first step of the algorithm. |
| The resulting set may return a set with one 2-tuple for each edge, |
| (the usual case) or with both 2-tuples `(u, v)` and `(v, u)` for |
| each edge. The latter is only done when a bipartite matching algorithm |
| is specified as `matching_algorithm`. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| An undirected graph. |
| |
| matching_algorithm : function |
| A function that returns a maximum cardinality matching for `G`. |
| The function must take one input, the graph `G`, and return |
| either a set of edges (with only one direction for the pair of nodes) |
| or a dictionary mapping each node to its mate. If not specified, |
| :func:`~networkx.algorithms.matching.max_weight_matching` is used. |
| Common bipartite matching functions include |
| :func:`~networkx.algorithms.bipartite.matching.hopcroft_karp_matching` |
| or |
| :func:`~networkx.algorithms.bipartite.matching.eppstein_matching`. |
| |
| Returns |
| ------- |
| min_cover : set |
| |
| A set of the edges in a minimum edge cover in the form of tuples. |
| It contains only one of the equivalent 2-tuples `(u, v)` and `(v, u)` |
| for each edge. If a bipartite method is used to compute the matching, |
| the returned set contains both the 2-tuples `(u, v)` and `(v, u)` |
| for each edge of a minimum edge cover. |
| |
| Examples |
| -------- |
| >>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)]) |
| >>> sorted(nx.min_edge_cover(G)) |
| [(2, 1), (3, 0)] |
| |
| Notes |
| ----- |
| An edge cover of a graph is a set of edges such that every node of |
| the graph is incident to at least one edge of the set. |
| The minimum edge cover is an edge covering of smallest cardinality. |
| |
| Due to its implementation, the worst-case running time of this algorithm |
| is bounded by the worst-case running time of the function |
| ``matching_algorithm``. |
| |
| Minimum edge cover for `G` can also be found using the `min_edge_covering` |
| function in :mod:`networkx.algorithms.bipartite.covering` which is |
| simply this function with a default matching algorithm of |
| :func:`~networkx.algorithms.bipartite.matching.hopcraft_karp_matching` |
| """ |
| if len(G) == 0: |
| return set() |
| if nx.number_of_isolates(G) > 0: |
| |
| raise nx.NetworkXException( |
| "Graph has a node with no edge incident on it, so no edge cover exists." |
| ) |
| if matching_algorithm is None: |
| matching_algorithm = partial(nx.max_weight_matching, maxcardinality=True) |
| maximum_matching = matching_algorithm(G) |
| |
| try: |
| |
| min_cover = set(maximum_matching.items()) |
| bipartite_cover = True |
| except AttributeError: |
| min_cover = maximum_matching |
| bipartite_cover = False |
| |
| uncovered_nodes = set(G) - {v for u, v in min_cover} - {u for u, v in min_cover} |
| for v in uncovered_nodes: |
| |
| |
| |
| |
| |
| |
| u = arbitrary_element(G[v]) |
| min_cover.add((u, v)) |
| if bipartite_cover: |
| min_cover.add((v, u)) |
| return min_cover |
|
|
|
|
| @not_implemented_for("directed") |
| @nx._dispatchable |
| def is_edge_cover(G, cover): |
| """Decides whether a set of edges is a valid edge cover of the graph. |
| |
| Given a set of edges, whether it is an edge covering can |
| be decided if we just check whether all nodes of the graph |
| has an edge from the set, incident on it. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| An undirected bipartite graph. |
| |
| cover : set |
| Set of edges to be checked. |
| |
| Returns |
| ------- |
| bool |
| Whether the set of edges is a valid edge cover of the graph. |
| |
| Examples |
| -------- |
| >>> G = nx.Graph([(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)]) |
| >>> cover = {(2, 1), (3, 0)} |
| >>> nx.is_edge_cover(G, cover) |
| True |
| |
| Notes |
| ----- |
| An edge cover of a graph is a set of edges such that every node of |
| the graph is incident to at least one edge of the set. |
| """ |
| return set(G) <= set(chain.from_iterable(cover)) |
|
|