83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
# Copyright (C) 2011-2012 by
|
||
# Nicholas Mancuso <nick.mancuso@gmail.com>
|
||
# All rights reserved.
|
||
# BSD license.
|
||
#
|
||
# Author:
|
||
# Nicholas Mancuso <nick.mancuso@gmail.com>
|
||
"""Functions for computing an approximate minimum weight vertex cover.
|
||
|
||
A |vertex cover|_ is a subset of nodes such that each edge in the graph
|
||
is incident to at least one node in the subset.
|
||
|
||
.. _vertex cover: https://en.wikipedia.org/wiki/Vertex_cover
|
||
.. |vertex cover| replace:: *vertex cover*
|
||
|
||
"""
|
||
|
||
__all__ = ["min_weighted_vertex_cover"]
|
||
|
||
|
||
def min_weighted_vertex_cover(G, weight=None):
|
||
r"""Returns an approximate minimum weighted vertex cover.
|
||
|
||
The set of nodes returned by this function is guaranteed to be a
|
||
vertex cover, and the total weight of the set is guaranteed to be at
|
||
most twice the total weight of the minimum weight vertex cover. In
|
||
other words,
|
||
|
||
.. math::
|
||
|
||
w(S) \leq 2 * w(S^*),
|
||
|
||
where $S$ is the vertex cover returned by this function,
|
||
$S^*$ is the vertex cover of minimum weight out of all vertex
|
||
covers of the graph, and $w$ is the function that computes the
|
||
sum of the weights of each node in that given set.
|
||
|
||
Parameters
|
||
----------
|
||
G : NetworkX graph
|
||
|
||
weight : string, optional (default = None)
|
||
If None, every node has weight 1. If a string, use this node
|
||
attribute as the node weight. A node without this attribute is
|
||
assumed to have weight 1.
|
||
|
||
Returns
|
||
-------
|
||
min_weighted_cover : set
|
||
Returns a set of nodes whose weight sum is no more than twice
|
||
the weight sum of the minimum weight vertex cover.
|
||
|
||
Notes
|
||
-----
|
||
For a directed graph, a vertex cover has the same definition: a set
|
||
of nodes such that each edge in the graph is incident to at least
|
||
one node in the set. Whether the node is the head or tail of the
|
||
directed edge is ignored.
|
||
|
||
This is the local-ratio algorithm for computing an approximate
|
||
vertex cover. The algorithm greedily reduces the costs over edges,
|
||
iteratively building a cover. The worst-case runtime of this
|
||
implementation is $O(m \log n)$, where $n$ is the number
|
||
of nodes and $m$ the number of edges in the graph.
|
||
|
||
References
|
||
----------
|
||
.. [1] Bar-Yehuda, R., and Even, S. (1985). "A local-ratio theorem for
|
||
approximating the weighted vertex cover problem."
|
||
*Annals of Discrete Mathematics*, 25, 27–46
|
||
<http://www.cs.technion.ac.il/~reuven/PDF/vc_lr.pdf>
|
||
|
||
"""
|
||
cost = dict(G.nodes(data=weight, default=1))
|
||
# While there are uncovered edges, choose an uncovered and update
|
||
# the cost of the remaining edges.
|
||
for u, v in G.edges():
|
||
min_cost = min(cost[u], cost[v])
|
||
cost[u] -= min_cost
|
||
cost[v] -= min_cost
|
||
return {u for u, c in cost.items() if c == 0}
|