class_docstr: Gated Graph Convolution layer from paper `Gated Graph Sequence
  Neural Networks <https://arxiv.org/pdf/1511.05493.pdf>`__.
  
  .. math::
     h_{i}^{0} = [ x_i \| \mathbf{0} ]
  
     a_{i}^{t} = \sum_{j\in\mathcal{N}(i)} W_{e_{ij}} h_{j}^{t}
  
     h_{i}^{t+1} = \mathrm{GRU}(a_{i}^{t}, h_{i}^{t})
  
  Parameters
  ----------
  input_size: int
      Input feature size.
  output_size: int
      Output feature size.
  num_layers: int
      Number of GGNN layers. Default: 1.
  n_etypes: int
      Number of edge types. Default: 1.
  bias: bool
      If True, adds a learnable bias to the output. Default: True.
docstr: Compute Gated Graph Convolution layer.
  Parameters
  ----------
  graph : DGLGraph
      The graph.
  feat : torch.Tensor
      The input feature of shape :math:`(N, D_{in})` where :math:`N`
      is the number of nodes of the graph and :math:`D_{in}` is the
      input feature size.
  etypes : torch.LongTensor
      The edge type tensor of shape :math:`(E,)` where :math:`E` is
      the number of edges of the graph.
  edge_weight: torch.Tensor
      The shape of edge_weight is :math:`(N_E, 1)`. N_E is the number of edges in graph.
  Returns
  -------
  torch.Tensor
      The output feature of shape :math:`(N, D_{out})` where
      :math:`D_{out}` is size of output feature.
docstr_tok: ["Compute","Gated","Graph","Convolution","layer",".","Parameters","--","--","--","--","--","graph",":","DGLGraph","The","graph",".","feat",":","torch.Tensor","The","input","feature","of","shape",":","math",":","`","(","N",",","D_","{","in","}",")","`","where",":","math",":","`","N","`","is","the","number","of","nodes","of","the","graph","and",":","math",":","`","D_","{","in","}","`","is","the","input","feature","size",".","etypes",":","torch.LongTensor","The","edge","type","tensor","of","shape",":","math",":","`","(","E",",",")","`","where",":","math",":","`","E","`","is","the","number","of","edges","of","the","graph",".","edge_weight",":","torch.Tensor","The","shape","of","edge_weight","is",":","math",":","`","(","N_E",",","1",")","`",".","N_E","is","the","number","of","edges","in","graph",".","Returns","--","--","--","-","torch.Tensor","The","output","feature","of","shape",":","math",":","`","(","N",",","D_","{","out","}",")","`","where",":","math",":","`","D_","{","out","}","`","is","size","of","output","feature","."]
code: def forward(self, graph, feat, etypes=None, edge_weight=None):
      """Compute Gated Graph Convolution layer.
      Parameters
      ----------
      graph : DGLGraph
          The graph.
      feat : torch.Tensor
          The input feature of shape :math:`(N, D_{in})` where :math:`N`
          is the number of nodes of the graph and :math:`D_{in}` is the
          input feature size.
      etypes : torch.LongTensor
          The edge type tensor of shape :math:`(E,)` where :math:`E` is
          the number of edges of the graph.
      edge_weight: torch.Tensor
          The shape of edge_weight is :math:`(N_E, 1)`. N_E is the number of edges in graph.
      Returns
      -------
      torch.Tensor
          The output feature of shape :math:`(N, D_{out})` where
          :math:`D_{out}` is size of output feature.
      """
      if dgl.__version__ < "0.5":
          assert (
              graph.is_homograph()
          ), "not a homograph; convert it with to_homo and pass in the edge type as argument"
      else:
          assert (
              graph.is_homogeneous
          ), "not a homograph; convert it with to_homo and pass in the edge type as argument"
      graph = graph.local_var()
      zero_pad = feat.new_zeros(
          (feat.shape[0], self._out_feats - feat.shape[1])
      )
      feat = torch.cat([feat, zero_pad], -1)
  
      for _ in range(self._num_layers):
          graph.ndata["h"] = feat
          for i in range(self._n_etypes):
              eids = (etypes == i).nonzero(as_tuple=False).view(-1)
              if len(eids) > 0:
                  if edge_weight is None:
                      graph.apply_edges(
                          lambda edges: {
                              "W_e*h": self.linears[i](edges.src["h"])
                          },
                          eids,
                      )
                  else:
                      graph.apply_edges(
                          lambda edges: {
                              "W_e*h": self.linears[i](edges.src["h"])
                              * edge_weight.view(-1).unsqueeze(1)
                          },
                          eids,
                      )
          graph.update_all(fn.copy_e("W_e*h", "m"), fn.sum("m", "a"))
          a = graph.ndata.pop("a")  # (N, D)
          feat = self.gru(a, feat)
      return feat
  
imports: import dgl
  import dgl.function
  import torch
  import torch.nn
  from torch.nn import init
  from ...data.data import GraphData
  from .base import GNNBase, GNNLayerBase
label_desc: Use image node_id 3 for calling the UndirectedGGNNLayerConv obj's underlying member method code with example usage: obj.forward(graph, feat, etypes, edge_weight) and returns: feat