test_maxcut.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import random
  2. import networkx as nx
  3. from networkx.algorithms.approximation import maxcut
  4. def _is_valid_cut(G, set1, set2):
  5. union = set1.union(set2)
  6. assert union == set(G.nodes)
  7. assert len(set1) + len(set2) == G.number_of_nodes()
  8. def _cut_is_locally_optimal(G, cut_size, set1):
  9. # test if cut can be locally improved
  10. for i, node in enumerate(set1):
  11. cut_size_without_node = nx.algorithms.cut_size(
  12. G, set1 - {node}, weight="weight"
  13. )
  14. assert cut_size_without_node <= cut_size
  15. def test_random_partitioning():
  16. G = nx.complete_graph(5)
  17. _, (set1, set2) = maxcut.randomized_partitioning(G, seed=5)
  18. _is_valid_cut(G, set1, set2)
  19. def test_random_partitioning_all_to_one():
  20. G = nx.complete_graph(5)
  21. _, (set1, set2) = maxcut.randomized_partitioning(G, p=1)
  22. _is_valid_cut(G, set1, set2)
  23. assert len(set1) == G.number_of_nodes()
  24. assert len(set2) == 0
  25. def test_one_exchange_basic():
  26. G = nx.complete_graph(5)
  27. random.seed(5)
  28. for u, v, w in G.edges(data=True):
  29. w["weight"] = random.randrange(-100, 100, 1) / 10
  30. initial_cut = set(random.sample(sorted(G.nodes()), k=5))
  31. cut_size, (set1, set2) = maxcut.one_exchange(
  32. G, initial_cut, weight="weight", seed=5
  33. )
  34. _is_valid_cut(G, set1, set2)
  35. _cut_is_locally_optimal(G, cut_size, set1)
  36. def test_one_exchange_optimal():
  37. # Greedy one exchange should find the optimal solution for this graph (14)
  38. G = nx.Graph()
  39. G.add_edge(1, 2, weight=3)
  40. G.add_edge(1, 3, weight=3)
  41. G.add_edge(1, 4, weight=3)
  42. G.add_edge(1, 5, weight=3)
  43. G.add_edge(2, 3, weight=5)
  44. cut_size, (set1, set2) = maxcut.one_exchange(G, weight="weight", seed=5)
  45. _is_valid_cut(G, set1, set2)
  46. _cut_is_locally_optimal(G, cut_size, set1)
  47. # check global optimality
  48. assert cut_size == 14
  49. def test_negative_weights():
  50. G = nx.complete_graph(5)
  51. random.seed(5)
  52. for u, v, w in G.edges(data=True):
  53. w["weight"] = -1 * random.random()
  54. initial_cut = set(random.sample(sorted(G.nodes()), k=5))
  55. cut_size, (set1, set2) = maxcut.one_exchange(G, initial_cut, weight="weight")
  56. # make sure it is a valid cut
  57. _is_valid_cut(G, set1, set2)
  58. # check local optimality
  59. _cut_is_locally_optimal(G, cut_size, set1)
  60. # test that all nodes are in the same partition
  61. assert len(set1) == len(G.nodes) or len(set2) == len(G.nodes)