code: def in_subgraph(
      graph,
      nodes,
      *,
      relabel_nodes=False,
      store_ids=True,
      output_device=None,
  ):
      """Return the subgraph induced on the inbound edges of all the edge types of the
      given nodes.
  
      An in subgraph is equivalent to creating a new graph using the incoming edges of the
      given nodes. In addition to extracting the subgraph, DGL also copies the features of
      the extracted nodes and edges to the resulting graph. The copy is *lazy* and incurs
      data movement only when needed.
  
      If the graph is heterogeneous, DGL extracts a subgraph per relation and composes
      them as the resulting graph. Thus, the resulting graph has the same set of relations
      as the input one.
  
      Parameters
      ----------
      graph : DGLGraph
          The input graph.
      nodes : nodes or dict[str, nodes]
          The nodes to form the subgraph, which cannot have any duplicate value. The result
          will be undefined otherwise. The allowed nodes formats are:
  
          * Int Tensor: Each element is a node ID. The tensor must have the same device type
            and ID data type as the graph's.
          * iterable[int]: Each element is a node ID.
  
          If the graph is homogeneous, one can directly pass the above formats.
          Otherwise, the argument must be a dictionary with keys being node types
          and values being the node IDs in the above formats.
      relabel_nodes : bool, optional
          If True, it will remove the isolated nodes and relabel the rest nodes in the
          extracted subgraph.
      store_ids : bool, optional
          If True, it will store the raw IDs of the extracted edges in the ``edata`` of the
          resulting graph under name ``dgl.EID``; if ``relabel_nodes`` is ``True``, it will
          also store the raw IDs of the extracted nodes in the ``ndata`` of the resulting
          graph under name ``dgl.NID``.
      output_device : Framework-specific device context object, optional
          The output device.  Default is the same as the input graph.
  
      Returns
      -------
      DGLGraph
          The subgraph.
  
      Notes
      -----
  
      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
      --------
      The following example uses PyTorch backend.
  
      >>> import dgl
      >>> import torch
  
      Extract a subgraph from a homogeneous graph.
  
      >>> g = dgl.graph(([0, 1, 2, 3, 4], [1, 2, 3, 4, 0]))  # 5-node cycle
      >>> g.edata['w'] = torch.arange(10).view(5, 2)
      >>> sg = dgl.in_subgraph(g, [2, 0])
      >>> sg
      Graph(num_nodes=5, num_edges=2,
            ndata_schemes={}
            edata_schemes={'w': Scheme(shape=(2,), dtype=torch.int64),
                           '_ID': Scheme(shape=(), dtype=torch.int64)})
      >>> sg.edges()
      (tensor([1, 4]), tensor([2, 0]))
      >>> sg.edata[dgl.EID]  # original edge IDs
      tensor([1, 4])
      >>> sg.edata['w']  # also extract the features
      tensor([[2, 3],
              [8, 9]])
  
      Extract a subgraph with node labeling.
  
      >>> sg = dgl.in_subgraph(g, [2, 0], relabel_nodes=True)
      >>> sg
      Graph(num_nodes=4, num_edges=2,
            ndata_schemes={'_ID': Scheme(shape=(), dtype=torch.int64}
            edata_schemes={'w': Scheme(shape=(2,), dtype=torch.int64),
                           '_ID': Scheme(shape=(), dtype=torch.int64)})
      >>> sg.edges()
      (tensor([1, 3]), tensor([2, 0]))
      >>> sg.edata[dgl.EID]  # original edge IDs
      tensor([1, 4])
      >>> sg.ndata[dgl.NID]  # original node IDs
      tensor([0, 1, 2, 4])
  
      Extract a subgraph from a heterogeneous graph.
  
      >>> g = dgl.heterograph({
      ...     ('user', 'plays', 'game'): ([0, 1, 1, 2], [0, 0, 2, 1]),
      ...     ('user', 'follows', 'user'): ([0, 1, 1], [1, 2, 2])})
      >>> sub_g = g.in_subgraph({'user': [2], 'game': [2]})
      >>> sub_g
      Graph(num_nodes={'game': 3, 'user': 3},
            num_edges={('user', 'plays', 'game'): 1, ('user', 'follows', 'user'): 2},
            metagraph=[('user', 'game', 'plays'), ('user', 'user', 'follows')])
  
      See also
      --------
      out_subgraph
      """
      if graph.is_block:
          raise DGLError(
              "Extracting subgraph of a block graph is not allowed."
          )
      if not isinstance(nodes, dict):
          if len(graph.ntypes) > 1:
              raise DGLError(
                  "Must specify node type when the graph is not homogeneous."
              )
          nodes = {graph.ntypes[0]: nodes}
      nodes = utils.prepare_tensor_dict(graph, nodes, "nodes")
      device = context_of(nodes)
      nodes_all_types = [
          F.to_dgl_nd(
              nodes.get(
                  ntype, F.copy_to(F.tensor([], graph.idtype), device)
              )
          )
          for ntype in graph.ntypes
      ]
  
      sgi = _CAPI_DGLInSubgraph(
          graph._graph, nodes_all_types, relabel_nodes
      )
      induced_nodes_or_device = (
          sgi.induced_nodes if relabel_nodes else device
      )
      induced_edges = sgi.induced_edges
      subg = _create_hetero_subgraph(
          graph,
          sgi,
          induced_nodes_or_device,
          induced_edges,
          store_ids=store_ids,
      )
      return subg if output_device is None else subg.to(output_device)
  
file_path: dgl/python/dgl/subgraph.py
imports: from collections.abc import Mapping
  from .None import backend, graph_index, heterograph_index, utils
  from ._ffi.function import _init_api
  from .base import DGLError
  from .heterograph import DGLGraph
  from .utils import context_of, recursive_apply
label_desc: Use image node_id 3 for calling a global function with example usage: in_subgraph(graph, nodes) and returns: unknown