code: def fast_gnp_random_graph(n, p, seed=None, directed=False):
      """Returns a $G_{n,p}$ random graph, also known as an Erdős-Rényi graph or
      a binomial graph.
  
      Parameters
      ----------
      n : int
          The number of nodes.
      p : float
          Probability for edge creation.
      seed : integer, random_state, or None (default)
          Indicator of random number generation state.
          See :ref:`Randomness<randomness>`.
      directed : bool, optional (default=False)
          If True, this function returns a directed graph.
  
      Notes
      -----
      The $G_{n,p}$ graph algorithm chooses each of the $[n (n - 1)] / 2$
      (undirected) or $n (n - 1)$ (directed) possible edges with probability $p$.
  
      This algorithm [1]_ runs in $O(n + m)$ time, where `m` is the expected number of
      edges, which equals $p n (n - 1) / 2$. This should be faster than
      :func:`gnp_random_graph` when $p$ is small and the expected number of edges
      is small (that is, the graph is sparse).
  
      See Also
      --------
      gnp_random_graph
  
      References
      ----------
      .. [1] Vladimir Batagelj and Ulrik Brandes,
         "Efficient generation of large random networks",
         Phys. Rev. E, 71, 036113, 2005.
      """
      G = empty_graph(n)
  
      if p <= 0 or p >= 1:
          return nx.gnp_random_graph(n, p, seed=seed, directed=directed)
  
      lp = math.log(1.0 - p)
  
      if directed:
          G = nx.DiGraph(G)
          v = 1
          w = -1
          while v < n:
              lr = math.log(1.0 - seed.random())
              w = w + 1 + int(lr / lp)
              while w >= v and v < n:
                  w = w - v
                  v = v + 1
              if v < n:
                  G.add_edge(w, v)
  
      # Nodes in graph are from 0,n-1 (start with v as the second node index).
      v = 1
      w = -1
      while v < n:
          lr = math.log(1.0 - seed.random())
          w = w + 1 + int(lr / lp)
          while w >= v and v < n:
              w = w - v
              v = v + 1
          if v < n:
              G.add_edge(v, 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 1 for calling a global function with example usage: fast_gnp_random_graph(n, p, seed, directed) and returns: G, nx