code: def gnm_random_graph(n, m, seed=None, directed=False):
      """Returns a $G_{n,m}$ random graph.
  
      In the $G_{n,m}$ model, a graph is chosen uniformly at random from the set
      of all graphs with $n$ nodes and $m$ edges.
  
      This algorithm should be faster than :func:`dense_gnm_random_graph` for
      sparse graphs.
  
      Parameters
      ----------
      n : int
          The number of nodes.
      m : int
          The number of edges.
      seed : integer, random_state, or None (default)
          Indicator of random number generation state.
          See :ref:`Randomness<randomness>`.
      directed : bool, optional (default=False)
          If True return a directed graph
  
      See also
      --------
      dense_gnm_random_graph
  
      """
      if directed:
          G = nx.DiGraph()
      else:
          G = nx.Graph()
      G.add_nodes_from(range(n))
  
      if n == 1:
          return G
      max_edges = n * (n - 1)
      if not directed:
          max_edges /= 2.0
      if m >= max_edges:
          return complete_graph(n, create_using=G)
  
      nlist = list(G)
      edge_count = 0
      while edge_count < m:
          # generate random edge,u,v
          u = seed.choice(nlist)
          v = seed.choice(nlist)
          if u == v or G.has_edge(u, v):
              continue
          else:
              G.add_edge(u, v)
              edge_count = edge_count + 1
      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 4 for calling a global function with example usage: gnm_random_graph(n, m, seed, directed) and returns: G, G, complete_graph