code: def to_hetero(
      module: Module,
      metadata: Metadata,
      aggr: str = "sum",
      input_map: Optional[Dict[str, str]] = None,
      debug: bool = False,
  ) -> GraphModule:
      r"""Converts a homogeneous GNN model into its heterogeneous equivalent in
      which node representations are learned for each node type in
      :obj:`metadata[0]`, and messages are exchanged between each edge type in
      :obj:`metadata[1]`, as denoted in the `"Modeling Relational Data with Graph
      Convolutional Networks" <https://arxiv.org/abs/1703.06103>`_ paper.
  
      .. code-block:: python
  
          import torch
          from torch_geometric.nn import SAGEConv, to_hetero
  
          class GNN(torch.nn.Module):
              def __init__(self):
                  super().__init__()
                  self.conv1 = SAGEConv((-1, -1), 32)
                  self.conv2 = SAGEConv((32, 32), 32)
  
              def forward(self, x, edge_index):
                  x = self.conv1(x, edge_index).relu()
                  x = self.conv2(x, edge_index).relu()
                  return x
  
          model = GNN()
  
          node_types = ['paper', 'author']
          edge_types = [
              ('paper', 'cites', 'paper'),
              ('paper', 'written_by', 'author'),
              ('author', 'writes', 'paper'),
          ]
          metadata = (node_types, edge_types)
  
          model = to_hetero(model, metadata)
          model(x_dict, edge_index_dict)
  
      where :obj:`x_dict` and :obj:`edge_index_dict` denote dictionaries that
      hold node features and edge connectivity information for each node type and
      edge type, respectively.
  
      The below illustration shows the original computation graph of the
      homogeneous model on the left, and the newly obtained computation graph of
      the heterogeneous model on the right:
  
      .. figure:: ../_figures/to_hetero.svg
        :align: center
        :width: 90%
  
        Transforming a model via :func:`to_hetero`.
  
      Here, each :class:`~torch_geometric.nn.conv.MessagePassing` instance
      :math:`f_{\theta}^{(\ell)}` is duplicated and stored in a set
      :math:`\{ f_{\theta}^{(\ell, r)} : r \in \mathcal{R} \}` (one instance for
      each relation in :math:`\mathcal{R}`), and message passing in layer
      :math:`\ell` is performed via
  
      .. math::
  
          \mathbf{h}^{(\ell)}_v = \bigoplus_{r \in \mathcal{R}}
          f_{\theta}^{(\ell, r)} ( \mathbf{h}^{(\ell - 1)}_v, \{
          \mathbf{h}^{(\ell - 1)}_w : w \in \mathcal{N}^{(r)}(v) \}),
  
      where :math:`\mathcal{N}^{(r)}(v)` denotes the neighborhood of :math:`v \in
      \mathcal{V}` under relation :math:`r \in \mathcal{R}`, and
      :math:`\bigoplus` denotes the aggregation scheme :attr:`aggr` to use for
      grouping node embeddings generated by different relations
      (:obj:`"sum"`, :obj:`"mean"`, :obj:`"min"`, :obj:`"max"` or :obj:`"mul"`).
  
      Args:
          module (torch.nn.Module): The homogeneous model to transform.
          metadata (Tuple[List[str], List[Tuple[str, str, str]]]): The metadata
              of the heterogeneous graph, *i.e.* its node and edge types given
              by a list of strings and a list of string triplets, respectively.
              See :meth:`torch_geometric.data.HeteroData.metadata` for more
              information.
          aggr (str, optional): The aggregation scheme to use for grouping node
              embeddings generated by different relations
              (:obj:`"sum"`, :obj:`"mean"`, :obj:`"min"`, :obj:`"max"`,
              :obj:`"mul"`). (default: :obj:`"sum"`)
          input_map (Dict[str, str], optional): A dictionary holding information
              about the type of input arguments of :obj:`module.forward`.
              For example, in case :obj:`arg` is a node-level argument, then
              :obj:`input_map['arg'] = 'node'`, and
              :obj:`input_map['arg'] = 'edge'` otherwise.
              In case :obj:`input_map` is not further specified, will try to
              automatically determine the correct type of input arguments.
              (default: :obj:`None`)
          debug (bool, optional): If set to :obj:`True`, will perform
              transformation in debug mode. (default: :obj:`False`)
      """
      transformer = ToHeteroTransformer(
          module, metadata, aggr, input_map, debug
      )
      return transformer.transform()
  
imports: import copy
  import warnings
  from collections import defaultdict, deque
  from typing import Any, Dict, Optional, Tuple, Union
  import torch
  from torch.nn import Module
  from torch_geometric.nn.dense.linear import is_uninitialized_parameter
  from torch_geometric.nn.fx import Transformer, get_submodule
  from torch_geometric.typing import EdgeType, Metadata, NodeType
  from torch_geometric.utils.hetero import check_add_self_loops, get_unused_node_types
label_desc: Use image node_id 2 for calling a global function with example usage: to_hetero(module, metadata, aggr, input_map, debug) and returns: transformer