code: def to_networkx(
      G: nxcg.Graph, *, sort_edges: bool = False
  ) -> nx.Graph:
      """Convert a nx_cugraph graph to networkx graph.
  
      All edge and node attributes and ``G.graph`` properties are converted.
  
      Parameters
      ----------
      G : nx_cugraph.Graph
      sort_edges : bool, default False
          Whether to sort the edge data of the input graph by (src, dst) indices
          before converting. This can be useful to convert to networkx graphs
          that iterate over edges consistently since edges are stored in dicts
          in the order they were added.
  
      Returns
      -------
      networkx.Graph
  
      See Also
      --------
      from_networkx : The opposite; convert networkx graph to nx_cugraph graph
      """
      rv = G.to_networkx_class()()
      id_to_key = G.id_to_key
      if sort_edges:
          G._sort_edge_indices()
  
      node_values = G.node_values
      node_masks = G.node_masks
      if node_values:
          node_iter = range(len(G))
          if id_to_key is not None:
              node_iter = map(id_to_key.__getitem__, node_iter)
          full_node_dicts = _iter_attr_dicts(node_values, node_masks)
          rv.add_nodes_from(zip(node_iter, full_node_dicts))
      elif id_to_key is not None:
          rv.add_nodes_from(id_to_key)
      else:
          rv.add_nodes_from(range(len(G)))
  
      src_indices = G.src_indices
      dst_indices = G.dst_indices
      edge_values = G.edge_values
      edge_masks = G.edge_masks
      if not G.is_directed():
          # Only add upper triangle of the adjacency matrix so we don't double-add edges
          mask = src_indices <= dst_indices
          src_indices = src_indices[mask]
          dst_indices = dst_indices[mask]
          if edge_values:
              edge_values = {k: v[mask] for k, v in edge_values.items()}
          if edge_masks:
              edge_masks = {k: v[mask] for k, v in edge_masks.items()}
      src_indices = src_iter = src_indices.tolist()
      dst_indices = dst_iter = dst_indices.tolist()
      if id_to_key is not None:
          src_iter = map(id_to_key.__getitem__, src_indices)
          dst_iter = map(id_to_key.__getitem__, dst_indices)
      if G.is_multigraph() and (
          G.edge_keys is not None or G.edge_indices is not None
      ):
          if G.edge_keys is not None:
              edge_keys = G.edge_keys
          else:
              edge_keys = G.edge_indices.tolist()
          if edge_values:
              full_edge_dicts = _iter_attr_dicts(
                  edge_values, edge_masks
              )
              rv.add_edges_from(
                  zip(src_iter, dst_iter, edge_keys, full_edge_dicts)
              )
          else:
              rv.add_edges_from(zip(src_iter, dst_iter, edge_keys))
      elif edge_values:
          full_edge_dicts = _iter_attr_dicts(edge_values, edge_masks)
          rv.add_edges_from(zip(src_iter, dst_iter, full_edge_dicts))
      else:
          rv.add_edges_from(zip(src_iter, dst_iter))
  
      rv.graph.update(G.graph)
      return rv
  
file_path: cugraph/python/nx-cugraph/nx_cugraph/convert.py
imports: from __future__ import annotations
  import itertools
  import operator
  from collections import Counter
  from collections.abc import Mapping
  from typing import TYPE_CHECKING
  import cupy
  import networkx
  import numpy
  import nx_cugraph
  from .utils import index_dtype
label_desc: Use image node_id 4 for calling a global function with example usage: to_networkx(G) and returns: rv