Spaces:
Running
Running
import networkx as nx | |
from networkx.utils.decorators import not_implemented_for, py_random_state | |
__all__ = ["randomized_partitioning", "one_exchange"] | |
def randomized_partitioning(G, seed=None, p=0.5, weight=None): | |
"""Compute a random partitioning of the graph nodes and its cut value. | |
A partitioning is calculated by observing each node | |
and deciding to add it to the partition with probability `p`, | |
returning a random cut and its corresponding value (the | |
sum of weights of edges connecting different partitions). | |
Parameters | |
---------- | |
G : NetworkX graph | |
seed : integer, random_state, or None (default) | |
Indicator of random number generation state. | |
See :ref:`Randomness<randomness>`. | |
p : scalar | |
Probability for each node to be part of the first partition. | |
Should be in [0,1] | |
weight : object | |
Edge attribute key to use as weight. If not specified, edges | |
have weight one. | |
Returns | |
------- | |
cut_size : scalar | |
Value of the minimum cut. | |
partition : pair of node sets | |
A partitioning of the nodes that defines a minimum cut. | |
""" | |
cut = {node for node in G.nodes() if seed.random() < p} | |
cut_size = nx.algorithms.cut_size(G, cut, weight=weight) | |
partition = (cut, G.nodes - cut) | |
return cut_size, partition | |
def _swap_node_partition(cut, node): | |
return cut - {node} if node in cut else cut.union({node}) | |
def one_exchange(G, initial_cut=None, seed=None, weight=None): | |
"""Compute a partitioning of the graphs nodes and the corresponding cut value. | |
Use a greedy one exchange strategy to find a locally maximal cut | |
and its value, it works by finding the best node (one that gives | |
the highest gain to the cut value) to add to the current cut | |
and repeats this process until no improvement can be made. | |
Parameters | |
---------- | |
G : networkx Graph | |
Graph to find a maximum cut for. | |
initial_cut : set | |
Cut to use as a starting point. If not supplied the algorithm | |
starts with an empty cut. | |
seed : integer, random_state, or None (default) | |
Indicator of random number generation state. | |
See :ref:`Randomness<randomness>`. | |
weight : object | |
Edge attribute key to use as weight. If not specified, edges | |
have weight one. | |
Returns | |
------- | |
cut_value : scalar | |
Value of the maximum cut. | |
partition : pair of node sets | |
A partitioning of the nodes that defines a maximum cut. | |
""" | |
if initial_cut is None: | |
initial_cut = set() | |
cut = set(initial_cut) | |
current_cut_size = nx.algorithms.cut_size(G, cut, weight=weight) | |
while True: | |
nodes = list(G.nodes()) | |
# Shuffling the nodes ensures random tie-breaks in the following call to max | |
seed.shuffle(nodes) | |
best_node_to_swap = max( | |
nodes, | |
key=lambda v: nx.algorithms.cut_size( | |
G, _swap_node_partition(cut, v), weight=weight | |
), | |
default=None, | |
) | |
potential_cut = _swap_node_partition(cut, best_node_to_swap) | |
potential_cut_size = nx.algorithms.cut_size(G, potential_cut, weight=weight) | |
if potential_cut_size > current_cut_size: | |
cut = potential_cut | |
current_cut_size = potential_cut_size | |
else: | |
break | |
partition = (cut, G.nodes - cut) | |
return current_cut_size, partition | |