mycielski.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. """Functions related to the Mycielski Operation and the Mycielskian family
  2. of graphs.
  3. """
  4. import networkx as nx
  5. from networkx.utils import not_implemented_for
  6. __all__ = ["mycielskian", "mycielski_graph"]
  7. @not_implemented_for("directed")
  8. @not_implemented_for("multigraph")
  9. @nx._dispatchable(returns_graph=True)
  10. def mycielskian(G, iterations=1):
  11. r"""Returns the Mycielskian of a simple, undirected graph G
  12. The Mycielskian of graph preserves a graph's triangle free
  13. property while increasing the chromatic number by 1.
  14. The Mycielski Operation on a graph, :math:`G=(V, E)`, constructs a new
  15. graph with :math:`2|V| + 1` nodes and :math:`3|E| + |V|` edges.
  16. The construction is as follows:
  17. Let :math:`V = {0, ..., n-1}`. Construct another vertex set
  18. :math:`U = {n, ..., 2n}` and a vertex, `w`.
  19. Construct a new graph, `M`, with vertices :math:`U \bigcup V \bigcup w`.
  20. For edges, :math:`(u, v) \in E` add edges :math:`(u, v), (u, v + n)`, and
  21. :math:`(u + n, v)` to M. Finally, for all vertices :math:`u \in U`, add
  22. edge :math:`(u, w)` to M.
  23. The Mycielski Operation can be done multiple times by repeating the above
  24. process iteratively.
  25. More information can be found at https://en.wikipedia.org/wiki/Mycielskian
  26. Parameters
  27. ----------
  28. G : graph
  29. A simple, undirected NetworkX graph
  30. iterations : int
  31. The number of iterations of the Mycielski operation to
  32. perform on G. Defaults to 1. Must be a non-negative integer.
  33. Returns
  34. -------
  35. M : graph
  36. The Mycielskian of G after the specified number of iterations.
  37. Notes
  38. -----
  39. Graph, node, and edge data are not necessarily propagated to the new graph.
  40. """
  41. M = nx.convert_node_labels_to_integers(G)
  42. for i in range(iterations):
  43. n = M.number_of_nodes()
  44. M.add_nodes_from(range(n, 2 * n))
  45. old_edges = list(M.edges())
  46. M.add_edges_from((u, v + n) for u, v in old_edges)
  47. M.add_edges_from((u + n, v) for u, v in old_edges)
  48. M.add_node(2 * n)
  49. M.add_edges_from((u + n, 2 * n) for u in range(n))
  50. return M
  51. @nx._dispatchable(graphs=None, returns_graph=True)
  52. def mycielski_graph(n):
  53. """Generator for the n_th Mycielski Graph.
  54. The Mycielski family of graphs is an infinite set of graphs.
  55. :math:`M_1` is the singleton graph, :math:`M_2` is two vertices with an
  56. edge, and, for :math:`i > 2`, :math:`M_i` is the Mycielskian of
  57. :math:`M_{i-1}`.
  58. More information can be found at
  59. http://mathworld.wolfram.com/MycielskiGraph.html
  60. Parameters
  61. ----------
  62. n : int
  63. The desired Mycielski Graph.
  64. Returns
  65. -------
  66. M : graph
  67. The n_th Mycielski Graph
  68. Notes
  69. -----
  70. The first graph in the Mycielski sequence is the singleton graph.
  71. The Mycielskian of this graph is not the :math:`P_2` graph, but rather the
  72. :math:`P_2` graph with an extra, isolated vertex. The second Mycielski
  73. graph is the :math:`P_2` graph, so the first two are hard coded.
  74. The remaining graphs are generated using the Mycielski operation.
  75. """
  76. if n < 1:
  77. raise nx.NetworkXError("must satisfy n >= 1")
  78. if n == 1:
  79. return nx.empty_graph(1)
  80. else:
  81. return mycielskian(nx.path_graph(2), n - 2)