code: def reverse(
      g,
      copy_ndata=True,
      copy_edata=False,
      *,
      share_ndata=None,
      share_edata=None,
  ):
      r"""Return a new graph with every edges being the reverse ones in the input graph.
  
      The reverse (also called converse, transpose) of a graph with edges
      :math:`(i_1, j_1), (i_2, j_2), \cdots` of type ``(U, E, V)`` is a new graph with edges
      :math:`(j_1, i_1), (j_2, i_2), \cdots` of type ``(V, E, U)``.
  
      The returned graph shares the data structure with the original graph, i.e. dgl.reverse
      will not create extra storage for the reversed graph.
  
      Parameters
      ----------
      g : DGLGraph
          The input graph.
      copy_ndata: bool, optional
          If True, the node features of the reversed graph are copied from the
          original graph. If False, the reversed graph will not have any node features.
          (Default: True)
      copy_edata: bool, optional
          If True, the edge features of the reversed graph are copied from the
          original graph. If False, the reversed graph will not have any edge features.
          (Default: False)
  
      Return
      ------
      DGLGraph
          The reversed graph.
  
      Notes
      -----
      If :attr:`copy_ndata` or :attr:`copy_edata` is True,
      the resulting graph will share the node or edge feature
      tensors with the input graph. Hence, users should try to avoid in-place operations
      which will be visible to both graphs.
  
      This function discards the batch information. Please use
      :func:`dgl.DGLGraph.set_batch_num_nodes`
      and :func:`dgl.DGLGraph.set_batch_num_edges` on the transformed graph
      to maintain the information.
  
      Examples
      --------
      **Homogeneous graphs**
  
      Create a graph to reverse.
  
      >>> import dgl
      >>> import torch as th
      >>> g = dgl.graph((th.tensor([0, 1, 2]), th.tensor([1, 2, 0])))
      >>> g.ndata['h'] = th.tensor([[0.], [1.], [2.]])
      >>> g.edata['h'] = th.tensor([[3.], [4.], [5.]])
  
      Reverse the graph.
  
      >>> rg = dgl.reverse(g, copy_edata=True)
      >>> rg.ndata['h']
      tensor([[0.],
              [1.],
              [2.]])
  
      The i-th edge in the reversed graph corresponds to the i-th edge in the
      original graph. When :attr:`copy_edata` is True, they have the same features.
  
      >>> rg.edges()
      (tensor([1, 2, 0]), tensor([0, 1, 2]))
      >>> rg.edata['h']
      tensor([[3.],
              [4.],
              [5.]])
  
      **Heterogenenous graphs**
  
      >>> g = dgl.heterograph({
      ...     ('user', 'follows', 'user'): (th.tensor([0, 2]), th.tensor([1, 2])),
      ...     ('user', 'plays', 'game'): (th.tensor([1, 2, 1]), th.tensor([2, 1, 1]))
      ... })
      >>> g.nodes['game'].data['hv'] = th.ones(3, 1)
      >>> g.edges['plays'].data['he'] = th.zeros(3, 1)
  
      The resulting graph will have edge types
      ``('user', 'follows', 'user)`` and ``('game', 'plays', 'user')``.
  
      >>> rg = dgl.reverse(g, copy_ndata=True)
      >>> rg
      Graph(num_nodes={'game': 3, 'user': 3},
            num_edges={('user', 'follows', 'user'): 2, ('game', 'plays', 'user'): 3},
            metagraph=[('user', 'user'), ('game', 'user')])
      >>> rg.edges(etype='follows')
      (tensor([1, 2]), tensor([0, 2]))
      >>> rg.edges(etype='plays')
      (tensor([2, 1, 1]), tensor([1, 2, 1]))
      >>> rg.nodes['game'].data['hv']
      tensor([[1.],
              [1.],
              [1.]])
      >>> rg.edges['plays'].data
      {}
      """
      if share_ndata is not None:
          dgl_warning(
              "share_ndata argument has been renamed to copy_ndata."
          )
          copy_ndata = share_ndata
      if share_edata is not None:
          dgl_warning(
              "share_edata argument has been renamed to copy_edata."
          )
          copy_edata = share_edata
      if g.is_block:
          # TODO(0.5 release, xiangsx) need to handle BLOCK
          # currently reversing a block results in undefined behavior
          raise DGLError("Reversing a block graph is not supported.")
      gidx = g._graph.reverse()
      new_g = DGLGraph(gidx, g.ntypes, g.etypes)
  
      # handle ndata
      if copy_ndata:
          # for each ntype
          for ntype in g.ntypes:
              new_g.nodes[ntype].data.update(g.nodes[ntype].data)
  
      # handle edata
      if copy_edata:
          # for each etype
          for utype, etype, vtype in g.canonical_etypes:
              new_g.edges[vtype, etype, utype].data.update(
                  g.edges[utype, etype, vtype].data
              )
  
      return new_g
  
imports: import copy
  from collections.abc import Iterable, Mapping
  import numpy
  import scipy.sparse
  import scipy.sparse.linalg
  from ..utils import version
  from ..None import backend, batch, convert, function, ndarray, subgraph, utils
  from .._ffi.function import _init_api
  from ..base import dgl_warning, DGLError, EID, NID
  from ..frame import Frame
  from ..heterograph import DGLGraph
  from ..heterograph_index import create_heterograph_from_relations, create_metagraph_index
  from ..partition import metis_partition, metis_partition_assignment, partition_graph_with_halo
  from ..sampling.neighbor import sample_neighbors
label_desc: Use image node_id 13 for calling a global function with example usage: reverse(g, copy_ndata, copy_edata) and returns: new_g