code: def barabasi_albert_graph(n, m, seed=None, initial_graph=None):
      """Returns a random graph using Barabási–Albert preferential attachment
  
      A graph of $n$ nodes is grown by attaching new nodes each with $m$
      edges that are preferentially attached to existing nodes with high degree.
  
      Parameters
      ----------
      n : int
          Number of nodes
      m : int
          Number of edges to attach from a new node to existing nodes
      seed : integer, random_state, or None (default)
          Indicator of random number generation state.
          See :ref:`Randomness<randomness>`.
      initial_graph : Graph or None (default)
          Initial network for Barabási–Albert algorithm.
          It should be a connected graph for most use cases.
          A copy of `initial_graph` is used.
          If None, starts from a star graph on (m+1) nodes.
  
      Returns
      -------
      G : Graph
  
      Raises
      ------
      NetworkXError
          If `m` does not satisfy ``1 <= m < n``, or
          the initial graph number of nodes m0 does not satisfy ``m <= m0 <= n``.
  
      References
      ----------
      .. [1] A. L. Barabási and R. Albert "Emergence of scaling in
         random networks", Science 286, pp 509-512, 1999.
      """
  
      if m < 1 or m >= n:
          raise nx.NetworkXError(
              f"Barabási–Albert network must have m >= 1 and m < n, m = {m}, n = {n}"
          )
  
      if initial_graph is None:
          # Default initial graph : star graph on (m + 1) nodes
          G = star_graph(m)
      else:
          if len(initial_graph) < m or len(initial_graph) > n:
              raise nx.NetworkXError(
                  f"Barabási–Albert initial graph needs between m={m} and n={n} nodes"
              )
          G = initial_graph.copy()
  
      # List of existing nodes, with nodes repeated once for each adjacent edge
      repeated_nodes = [n for n, d in G.degree() for _ in range(d)]
      # Start adding the other n - m0 nodes.
      source = len(G)
      while source < n:
          # Now choose m unique nodes from the existing nodes
          # Pick uniformly from repeated_nodes (preferential attachment)
          targets = _random_subset(repeated_nodes, m, seed)
          # Add edges to m nodes from the source.
          G.add_edges_from(zip([source] * m, targets))
          # Add one node to the list for each new edge just created.
          repeated_nodes.extend(targets)
          # And the new node "source" has m edges to add to the list.
          repeated_nodes.extend([source] * m)
  
          source += 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 10 for calling a global function with example usage: barabasi_albert_graph(n, m, seed, initial_graph) and returns: G