class_docstr: Extended GAT to allow for weighted edges.
class_docstr_tok: ["Extended","GAT","to","allow","for","weighted","edges","."]
code: def edge_update(
      self,
      alpha_j: Tensor,
      alpha_i: Optional[Tensor],
      edge_attr: Optional[Tensor],
      index: Tensor,
      ptr: Optional[Tensor],
      size_i: Optional[int],
  ) -> Tensor:
      # Given edge-level attention coefficients for source and target nodes,
      # we simply need to sum them up to "emulate" concatenation:
      alpha = alpha_j if alpha_i is None else alpha_j + alpha_i
      alpha = F.leaky_relu(alpha, self.negative_slope)
  
      if edge_attr is not None:
          assert (
              edge_attr.dim() == 1
          ), "Only scalar edge weights supported"
          edge_attr = edge_attr.view(-1, 1)
          # `alpha` unchanged if edge_attr == 1 and -Inf if edge_attr == 0;
          # We choose log to counteract underflow in subsequent exp/softmax
          alpha = alpha + torch.log2(edge_attr)
  
      alpha = softmax(alpha, index, ptr, size_i)
      alpha = F.dropout(alpha, p=self.dropout, training=self.training)
      return alpha
  
imports: import copy
  import os.path
  from typing import Optional
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch.optim import Adam
  import torch_geometric.transforms
  from torch_geometric.contrib.nn import GRBCDAttack, PRBCDAttack
  from torch_geometric.datasets import Planetoid
  from torch_geometric.nn import GATConv, GCNConv
  from torch_geometric.nn.conv.gcn_conv import gcn_norm
  from torch_geometric.utils import softmax
label_desc: Use image node_id 1 for calling the WeightedGATConv obj's underlying member method code with example usage: obj.edge_update(alpha_j, alpha_i, edge_attr, index, ptr, size_i) and returns: alpha