class_docstr: Implement a graph wrapper that user can use their own data holder. 
  And this graph wrapper support multiple graphs which is benefit for data parallel algorithms.
  
  Args:
      num_nodes (int32 or int64): Shape [ num_graph ]. 
  
      num_edges (int32 or int64): Shape [ num_graph ]. 
  
      edges (int32 or int64): Shape [ total_num_edges_in_the_graphs, 2 ] 
                                or Tuple with (src, dst).
  
      node_feats: A dictionary for node features. Each value should be tensor
                  with shape [ total_num_nodes_in_the_graphs, feature_size]
  
      edge_feats: A dictionary for edge features. Each value should be tensor
                  with shape [ total_num_edges_in_the_graphs, feature_size]
class_docstr_tok: ["Implement","a","graph","wrapper","that","user","can","use","their","own","data","holder",".","And","this","graph","wrapper","support","multiple","graphs","which","is","benefit","for","data","parallel","algorithms",".","Args",":","num_nodes","(","int32","or","int64",")",":","Shape","[","num_graph","]",".","num_edges","(","int32","or","int64",")",":","Shape","[","num_graph","]",".","edges","(","int32","or","int64",")",":","Shape","[","total_num_edges_in_the_graphs",",","2","]","or","Tuple","with","(","src",",","dst",")",".","node_feats",":","A","dictionary","for","node","features",".","Each","value","should","be","tensor","with","shape","[","total_num_nodes_in_the_graphs",",","feature_size","]","edge_feats",":","A","dictionary","for","edge","features",".","Each","value","should","be","tensor","with","shape","[","total_num_edges_in_the_graphs",",","feature_size","]"]
docstr: Merge subgraph edges. 
          
docstr_tok: ["Merge","subgraph","edges","."]
code: def __build_edges(self, edges, node_shift, edge_lod, edge_feats):
      """Merge subgraph edges."""
      if isinstance(edges, tuple):
          src, dst = edges
      else:
          src = edges[:, 0]
          dst = edges[:, 1]
  
      src = L.reshape(src, [-1])
      dst = L.reshape(dst, [-1])
      src = paddle_helper.ensure_dtype(src, dtype="int32")
      dst = paddle_helper.ensure_dtype(dst, dtype="int32")
      # preprocess edges
      lod_dst = L.lod_reset(dst, edge_lod)
      node_shift = L.reshape(node_shift, [-1, 1])
      node_shift = L.sequence_expand_as(node_shift, lod_dst)
      node_shift = L.reshape(node_shift, [-1])
      src = src + node_shift
      dst = dst + node_shift
      # sort edges
      self._edges_dst, index = L.argsort(dst)
      self._edges_src = L.gather(src, index, overwrite=False)
  
      # assign edge features
      if edge_feats is not None:
          for key, efeat in edge_feats.items():
              self.edge_feat_tensor_dict[key] = L.gather(
                  efeat, index, overwrite=False
              )
  
imports: import warnings
  import numpy
  import paddle.fluid
  import paddle.fluid.layers
  from pgl.utils import op
  from pgl.utils import paddle_helper
  from pgl.utils.logger import log
label_desc: Use image node_id 3 for calling the BatchGraphWrapper obj's underlying member method code with example usage: obj.__build_edges(edges, node_shift, edge_lod, edge_feats) without return types