code: def watts_strogatz_graph(n, k, p, seed=None):
      """Returns a Watts–Strogatz small-world graph.
  
      Parameters
      ----------
      n : int
          The number of nodes
      k : int
          Each node is joined with its `k` nearest neighbors in a ring
          topology.
      p : float
          The probability of rewiring each edge
      seed : integer, random_state, or None (default)
          Indicator of random number generation state.
          See :ref:`Randomness<randomness>`.
  
      See Also
      --------
      newman_watts_strogatz_graph
      connected_watts_strogatz_graph
  
      Notes
      -----
      First create a ring over $n$ nodes [1]_.  Then each node in the ring is joined
      to its $k$ nearest neighbors (or $k - 1$ neighbors if $k$ is odd).
      Then shortcuts are created by replacing some edges as follows: for each
      edge $(u, v)$ in the underlying "$n$-ring with $k$ nearest neighbors"
      with probability $p$ replace it with a new edge $(u, w)$ with uniformly
      random choice of existing node $w$.
  
      In contrast with :func:`newman_watts_strogatz_graph`, the random rewiring
      does not increase the number of edges. The rewired graph is not guaranteed
      to be connected as in :func:`connected_watts_strogatz_graph`.
  
      References
      ----------
      .. [1] Duncan J. Watts and Steven H. Strogatz,
         Collective dynamics of small-world networks,
         Nature, 393, pp. 440--442, 1998.
      """
      if k > n:
          raise nx.NetworkXError("k>n, choose smaller k or larger n")
  
      # If k == n, the graph is complete not Watts-Strogatz
      if k == n:
          return nx.complete_graph(n)
  
      G = nx.Graph()
      nodes = list(range(n))  # nodes are labeled 0 to n-1
      # connect each node to k/2 neighbors
      for j in range(1, k // 2 + 1):
          targets = (
              nodes[j:] + nodes[0:j]
          )  # first j nodes are now last in list
          G.add_edges_from(zip(nodes, targets))
      # rewire edges from each node
      # loop over all nodes in order (label) and neighbors in order (distance)
      # no self loops or multiple edges allowed
      for j in range(1, k // 2 + 1):  # outer loop is neighbors
          targets = (
              nodes[j:] + nodes[0:j]
          )  # first j nodes are now last in list
          # inner loop in node order
          for u, v in zip(nodes, targets):
              if seed.random() < p:
                  w = seed.choice(nodes)
                  # Enforce no self-loops or multiple edges
                  while w == u or G.has_edge(u, w):
                      w = seed.choice(nodes)
                      if G.degree(u) >= n - 1:
                          break  # skip this rewiring
                  else:
                      G.remove_edge(u, v)
                      G.add_edge(u, w)
      return G
  
imports: import itertools
  import math
  from collections import defaultdict
  import networkx
  from networkx.utils import py_random_state
  from .classic import complete_graph, empty_graph, path_graph, star_graph
  from .degree_seq import degree_sequence_tree
label_desc: Use image node_id 6 for calling a global function with example usage: watts_strogatz_graph(n, k, p, seed) and returns: G, nx