class_docstr: The graph attentional operator from the `"Graph Attention Networks"
  <https://arxiv.org/abs/1710.10903>`_ paper.
  
  .. math::
      \mathbf{x}^{\prime}_i = \alpha_{i,i}\mathbf{\Theta}\mathbf{x}_{i} +
      \sum_{j \in \mathcal{N}(i)} \alpha_{i,j}\mathbf{\Theta}\mathbf{x}_{j},
  
  where the attention coefficients :math:`\alpha_{i,j}` are computed as
  
  .. math::
      \alpha_{i,j} =
      \frac{
      \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top}
      [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_j]
      \right)\right)}
      {\sum_{k \in \mathcal{N}(i) \cup \{ i \}}
      \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top}
      [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_k]
      \right)\right)}.
  
  If the graph has multi-dimensional edge features :math:`\mathbf{e}_{i,j}`,
  the attention coefficients :math:`\alpha_{i,j}` are computed as
  
  .. math::
      \alpha_{i,j} =
      \frac{
      \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top}
      [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_j
      \, \Vert \, \mathbf{\Theta}_{e} \mathbf{e}_{i,j}]\right)\right)}
      {\sum_{k \in \mathcal{N}(i) \cup \{ i \}}
      \exp\left(\mathrm{LeakyReLU}\left(\mathbf{a}^{\top}
      [\mathbf{\Theta}\mathbf{x}_i \, \Vert \, \mathbf{\Theta}\mathbf{x}_k
      \, \Vert \, \mathbf{\Theta}_{e} \mathbf{e}_{i,k}]\right)\right)}.
  
  Args:
      in_channels (int or tuple): Size of each input sample, or :obj:`-1` to
          derive the size from the first input(s) to the forward method.
          A tuple corresponds to the sizes of source and target
          dimensionalities.
      out_channels (int): Size of each output sample.
      heads (int, optional): Number of multi-head-attentions.
          (default: :obj:`1`)
      concat (bool, optional): If set to :obj:`False`, the multi-head
          attentions are averaged instead of concatenated.
          (default: :obj:`True`)
      negative_slope (float, optional): LeakyReLU angle of the negative
          slope. (default: :obj:`0.2`)
      edge_dim (int, optional): Edge feature dimensionality (in case
          there are any). (default: :obj:`None`)
      bias (bool, optional): If set to :obj:`False`, the layer will not learn
          an additive bias. (default: :obj:`True`)
code: def __init__(
      self,
      in_channels: Union[int, Tuple[int, int]],
      out_channels: int,
      heads: int = 1,
      concat: bool = True,
      negative_slope: float = 0.2,
      edge_dim: Optional[int] = None,
      bias: bool = True,
  ):
      super().__init__()
  
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.heads = heads
      self.concat = concat
      self.negative_slope = negative_slope
      self.edge_dim = edge_dim
  
      Linear = torch_geometric.nn.Linear
  
      if isinstance(in_channels, int):
          self.lin = Linear(
              in_channels,
              heads * out_channels,
              bias=False,
              weight_initializer="glorot",
          )
      else:
          self.lin_src = Linear(
              in_channels[0],
              heads * out_channels,
              bias=False,
              weight_initializer="glorot",
          )
          self.lin_dst = Linear(
              in_channels[1],
              heads * out_channels,
              bias=False,
              weight_initializer="glorot",
          )
  
      if edge_dim is not None:
          self.lin_edge = Linear(
              edge_dim,
              heads * out_channels,
              bias=False,
              weight_initializer="glorot",
          )
          self.att = nn.Parameter(
              torch.Tensor(3 * heads * out_channels)
          )
      else:
          self.register_parameter("lin_edge", None)
          self.att = nn.Parameter(
              torch.Tensor(2 * heads * out_channels)
          )
  
      if bias and concat:
          self.bias = nn.Parameter(torch.Tensor(heads * out_channels))
      elif bias and not concat:
          self.bias = nn.Parameter(torch.Tensor(out_channels))
      else:
          self.register_parameter("bias", None)
  
      self.reset_parameters()
  
file_path: cugraph/python/cugraph-pyg/cugraph_pyg/nn/conv/gat_conv.py
imports: from typing import Optional, Tuple, Union
  from cugraph.utilities.utils import import_optional
  from pylibcugraphops.pytorch.operators import mha_gat_n2n
  from .base import BaseConv
label_desc: Use image node_id 1 to create a new GATConv object from inherited base classes: BaseConv with example: obj = GATConv(in_channels, out_channels, heads, concat, negative_slope, edge_dim, bias)