code: def compute_attention(self, query, key, value):
      # query: [*, query_entries, dim_k]
      # key: [*, key_entries, dim_k]
      # value: [*, key_entries, dim_v]
      # Output: [*, query_entries, dim_v]
  
      assert query.dim() == key.dim() == value.dim() >= 2
      assert query.size(-1) == key.size(-1)
      assert key.size(-2) == value.size(-2)
  
      # Score: [*, query_entries, key_entries]
      score = torch.matmul(query, key.transpose(-2, -1))
      score = score / math.sqrt(key.size(-1))
      score = restricted_softmax(score, dim=-1)
      score = F.dropout(score, p=self.dropout, training=self.training)
  
      return torch.matmul(score, value)
  
imports: import math
  from typing import Optional
  import torch
  import torch.nn.functional
  from torch import Tensor
  from torch.nn import Parameter
  from torch_geometric.nn.conv import MessagePassing
  from torch_geometric.nn.conv.gcn_conv import gcn_norm
  from torch_geometric.nn.inits import kaiming_uniform, uniform
  from torch_geometric.typing import Adj, OptPairTensor, OptTensor, SparseTensor
label_desc: Use image node_id 3 for calling the Attention obj's underlying member method code with example usage: obj.compute_attention(query, key, value) and returns: torch