code: def forward(self, graph, feat, get_attention=False):
      # Check in degree and generate error
      if (graph.in_degrees() == 0).any():
          raise DGLError(
              "There are 0-in-degree nodes in the graph, "
              "output for those nodes will be invalid. "
              "This is harmful for some applications, "
              "causing silent performance regression. "
              "Adding self-loop on the input graph by "
              "calling `g = dgl.add_self_loop(g)` will resolve "
              "the issue. Setting ``allow_zero_in_degree`` "
              "to be `True` when constructing this module will "
              "suppress the check and let the code run."
          )
      # projection process to get importance vector y
      graph.ndata["y"] = torch.abs(
          torch.matmul(self.p, feat.T).view(-1)
      ) / torch.norm(self.p, p=2)
      # Use edge message passing function to get the weight from src node
      graph.apply_edges(fn.copy_u("y", "y"))
      # Select Top k neighbors
      subgraph = select_topk(graph.cpu(), self.k, "y").to(graph.device)
      # Sigmoid as information threshold
      subgraph.ndata["y"] = torch.sigmoid(subgraph.ndata["y"])
      # Using vector matrix elementwise mul for acceleration
      feat = subgraph.ndata["y"].view(-1, 1) * feat
      feat = self.feat_drop(feat)
      h = self.fc(feat).view(-1, self.num_heads, self.out_feats)
      el = (h * self.attn_l).sum(dim=-1).unsqueeze(-1)
      er = (h * self.attn_r).sum(dim=-1).unsqueeze(-1)
      # Assign the value on the subgraph
      subgraph.srcdata.update({"ft": h, "el": el})
      subgraph.dstdata.update({"er": er})
      # compute edge attention, el and er are a_l Wh_i and a_r Wh_j respectively.
      subgraph.apply_edges(fn.u_add_v("el", "er", "e"))
      e = self.leaky_relu(subgraph.edata.pop("e"))
      # compute softmax
      subgraph.edata["a"] = self.attn_drop(edge_softmax(subgraph, e))
      # message passing
      subgraph.update_all(fn.u_mul_e("ft", "a", "m"), fn.sum("m", "ft"))
      rst = subgraph.dstdata["ft"]
      # activation
      if self.activation:
          rst = self.activation(rst)
      # Residual
      if self.residual:
          rst = rst + self.residual_module(feat).view(
              feat.shape[0], -1, self.out_feats
          )
  
      if get_attention:
          return rst, subgraph.edata["a"]
      else:
          return rst
  
file_path: dgl/examples/pytorch/hardgat/hgao.py
imports: from functools import partial
  import dgl
  import dgl.function
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl.base import DGLError
  from dgl.nn.pytorch import edge_softmax
  from dgl.nn.pytorch.utils import Identity
  from dgl.sampling import select_topk
label_desc: Use image node_id 3 for calling the HardGAO obj's underlying member method code with example usage: obj.forward(graph, feat, get_attention) and returns: rst,  subgraph, rst