class_docstr: Path Encoder, as introduced in Edge Encoding of
  `Do Transformers Really Perform Bad for Graph Representation?
  <https://proceedings.neurips.cc/paper/2021/file/f1c1592588411002af340cbaedd6fc33-Paper.pdf>`__
  
  This module is a learnable path embedding module and encodes the shortest
  path between each pair of nodes as attention bias.
  
  Parameters
  ----------
  max_len : int
      Maximum number of edges in each path to be encoded.
      Exceeding part of each path will be truncated, i.e.
      truncating edges with serial number no less than :attr:`max_len`.
  feat_dim : int
      Dimension of edge features in the input graph.
  num_heads : int, optional
      Number of attention heads if multi-head attention mechanism is applied.
      Default : 1.
  
  Examples
  --------
  >>> import torch as th
  >>> import dgl
  >>> from dgl.nn import PathEncoder
  >>> from dgl import shortest_dist
  
  >>> g = dgl.graph(([0,0,0,1,1,2,3,3], [1,2,3,0,3,0,0,1]))
  >>> edata = th.rand(8, 16)
  >>> # Since shortest_dist returns -1 for unreachable node pairs,
  >>> # edata[-1] should be filled with zero padding.
  >>> edata = th.cat(
          (edata, th.zeros(1, 16)), dim=0
      )
  >>> dist, path = shortest_dist(g, root=None, return_paths=True)
  >>> path_data = edata[path[:, :, :2]]
  >>> path_encoder = PathEncoder(2, 16, num_heads=8)
  >>> out = path_encoder(dist.unsqueeze(0), path_data.unsqueeze(0))
  >>> print(out.shape)
  torch.Size([1, 4, 4, 8])
class_docstr_tok: ["Path","Encoder",",","as","introduced","in","Edge","Encoding","of","`","Do","Transformers","Really","Perform","Bad","for","Graph","Representation","?","<","https",":","\/\/proceedings.neurips.cc\/paper\/2021\/file\/f1c1592588411002af340cbaedd6fc33-Paper.pdf",">","`","__","This","module","is","a","learnable","path","embedding","module","and","encodes","the","shortest","path","between","each","pair","of","nodes","as","attention","bias",".","Parameters","--","--","--","--","--","max_len",":","int","Maximum","number","of","edges","in","each","path","to","be","encoded",".","Exceeding","part","of","each","path","will","be","truncated",",","i.e",".","truncating","edges","with","serial","number","no","less","than",":","attr",":","`","max_len","`",".","feat_dim",":","int","Dimension","of","edge","features","in","the","input","graph",".","num_heads",":","int",",","optional","Number","of","attention","heads","if","multi-head","attention","mechanism","is","applied",".","Default",":","1",".","Examples","--","--","--","--",">",">",">","import","torch","as","th",">",">",">","import","dgl",">",">",">","from","dgl.nn","import","PathEncoder",">",">",">","from","dgl","import","shortest_dist",">",">",">","g","=","dgl.graph","(","(","[","0,0,0,1,1,2,3,3","]",",","[","1,2,3,0,3,0,0,1","]",")",")",">",">",">","edata","=","th.rand","(","8",",","16",")",">",">",">","#","Since","shortest_dist","returns","-1","for","unreachable","node","pairs",",",">",">",">","#","edata","[","-1","]","should","be","filled","with","zero","padding",".",">",">",">","edata","=","th.cat","(","(","edata",",","th.zeros","(","1",",","16",")",")",",","dim=0",")",">",">",">","dist",",","path","=","shortest_dist","(","g",",","root=None",",","return_paths=True",")",">",">",">","path_data","=","edata","[","path","[",":",",",":",",",":2","]","]",">",">",">","path_encoder","=","PathEncoder","(","2",",","16",",","num_heads=8",")",">",">",">","out","=","path_encoder","(","dist.unsqueeze","(","0",")",",","path_data.unsqueeze","(","0",")",")",">",">",">","print","(","out.shape",")","torch.Size","(","[","1",",","4",",","4",",","8","]",")"]
code: def __init__(self, max_len, feat_dim, num_heads=1):
      super().__init__()
      self.max_len = max_len
      self.feat_dim = feat_dim
      self.num_heads = num_heads
      self.embedding_table = nn.Embedding(max_len * num_heads, feat_dim)
  
imports: import torch
  import torch.nn
label_desc: Use image node_id 1 to create a new PathEncoder object from inherited base classes: nn with example: obj = PathEncoder(max_len, feat_dim, num_heads)