class_docstr:     The strategy for sequence decoding. Support beam seach only temporally.
  Parameters
  ----------
  beam_size: int
      The beam size for beam search.
  batch_graph: GraphData
      The input graph
  decoder: DecoderBase
      The decoder instance.
  rnn_type: str, option=["lstm", "gru"]
      The type of RNN.
  use_copy: bool, default=False
      Whether use ``copy`` mechanism. See pointer network. Note that you must use attention first.
  use_coverage: bool, default=False
      Whether use ``coverage`` mechanism. Note that you must use attention first.
  max_decoder_step: int, default=50
      The maximal decoding step.
code: def beam_search_for_tree_decoding(
      self,
      decoder_initial_state,
      decoder_initial_input,
      parent_state,
      graph_node_embedding,
      rnn_node_embedding=None,
      src_seq=None,
      oov_dict=None,
      sibling_state=None,
      device=None,
      topk=1,
      enc_batch=None,
  ):
      min_out_len = 1
      max_out_len = self.max_decoder_step
      batch_size = graph_node_embedding.size(0)
      assert batch_size == 1
      decoder_hidden = decoder_initial_state
  
      batch_results = []
      for _ in range(batch_size):
          single_graph_node_embedding = graph_node_embedding.expand(
              self.beam_size, -1, -1
          ).contiguous()
          single_parent_state = parent_state.expand(
              self.beam_size, -1
          ).contiguous()
  
          step = 0
          results, backup_results = [], []
          hypos = [
              Hypothesis(
                  tokens=[decoder_initial_input],
                  log_probs=[],
                  dec_state=decoder_hidden,
                  input_feed=None,
                  num_non_words=1,
                  enc_attn_weights=[],
                  use_coverage=self.use_coverage,
                  states_for_tree=[decoder_hidden],
              )
          ]
  
          while len(hypos) > 0 and step <= self.max_decoder_step:
              n_hypos = len(hypos)
              if n_hypos < self.beam_size:
                  hypos.extend(
                      hypos[-1] for _ in range(self.beam_size - n_hypos)
                  )  # check deep copy
              decoder_input = torch.tensor(
                  [h.tokens[-1] for h in hypos]
              ).to(graph_node_embedding.device)
              decoder_hidden = (
                  torch.cat([h.dec_state[0] for h in hypos], 0),
                  torch.cat([h.dec_state[1] for h in hypos], 0),
              )
  
              (
                  prediction,
                  decoder_hidden,
                  dec_attn_scores,
              ) = self.decoder.decode_step(
                  tgt_batch_size=self.beam_size,
                  dec_single_input=decoder_input,
                  dec_single_state=decoder_hidden,
                  memory=single_graph_node_embedding,
                  parent_state=single_parent_state,
                  oov_dict=oov_dict,
                  enc_batch=enc_batch,
              )
              prediction = torch.log(prediction + 1e-31)
              top_v, top_i = prediction.data.topk(self.beam_size)
  
              new_hypos = []
              for in_idx in range(n_hypos):
                  for out_idx in range(self.beam_size):
                      new_tok = top_i[in_idx][out_idx].item()
                      new_prob = top_v[in_idx][out_idx].item()
                      new_enc_attn_weights = (
                          dec_attn_scores[in_idx, :]
                          .unsqueeze(0)
                          .unsqueeze(0)
                      )
  
                      non_word = new_tok == self.vocab.get_symbol_idx(
                          self.vocab.end_token
                      )  # only SOS & EOS don't count
                      tmp_decoder_state = (
                          decoder_hidden[0][in_idx, :].unsqueeze(0),
                          decoder_hidden[1][in_idx, :].unsqueeze(0),
                      )
  
                      new_hypo = hypos[in_idx].create_next(
                          token=new_tok,
                          log_prob=new_prob,
                          dec_state=tmp_decoder_state,
                          input_feed=None,
                          non_word=non_word,
                          add_enc_attn_weights=new_enc_attn_weights,
                      )
                      new_hypos.append(new_hypo)
  
              new_hypos = sorted(
                  new_hypos, key=lambda h: -h.avg_log_prob
              )[: self.beam_size]
              hypos = []
              new_complete_results, new_incomplete_results = [], []
              for nh in new_hypos:
                  length = len(nh)  # Does not count SOS and EOS
                  if nh.tokens[-1] == self.vocab.get_symbol_idx(
                      self.vocab.end_token
                  ):  # a complete hypothesis
                      if (
                          len(new_complete_results) < self.beam_size
                          and min_out_len <= length <= max_out_len
                      ):
                          new_complete_results.append(nh)
                  elif (
                      len(hypos) < self.beam_size
                      and length < max_out_len
                  ):  # an incomplete hypothesis
                      hypos.append(nh)
                  elif (
                      length == max_out_len
                      and len(new_incomplete_results) < self.beam_size
                  ):
                      new_incomplete_results.append(nh)
              if new_complete_results:
                  results.extend(new_complete_results)
              elif new_incomplete_results:
                  backup_results.extend(new_incomplete_results)
              step += 1
  
          if (
              not results
          ):  # if no sequence ends with EOS within desired length, fallback to sequences
              results = backup_results  # that are "truncated" at the end to max_out_len
          batch_results.append(
              sorted(results, key=lambda h: -h.avg_log_prob)[:topk]
          )
  
      ret = torch.zeros(batch_size, topk, self.max_decoder_step).long()
      states = []
      for sent_id, each in enumerate(batch_results):
          for i in range(topk):
              ids = torch.Tensor(each[i].tokens[:])[
                  : self.max_decoder_step
              ]
              if ids.shape[0] < self.max_decoder_step:
                  pad = torch.zeros(
                      self.max_decoder_step - ids.shape[0]
                  )
                  ids = torch.cat((ids, pad), dim=0)
              ret[sent_id, i, :] = ids
              states.append(
                  each[i].states_for_tree[:][: self.max_decoder_step]
              )
      assert batch_size == 1 and topk == 1
      # for id
      output_results = [[[]]]
  
      token_id_list = ret[0][0]
      states_emb_list = states[0]
      for index in range(self.max_decoder_step):
          if token_id_list[index] != self.vocab.get_symbol_idx(
              self.vocab.pad_token
          ):
              output_results[0][0].append(
                  BeamSearchNode(
                      hiddenstate=states_emb_list[index],
                      enc_attn_weights_average=None,
                      previousNode=None,
                      wordId=token_id_list[index],
                      logProb=0,
                      length=-1,
                  )
              )
  
      return output_results
  
imports: from copy import deepcopy
  import torch
  import torch.nn
  from graph4nlp.pytorch.modules.prediction.generation.base import DecoderBase
label_desc: Use image node_id 4 for calling the DecoderStrategy obj's underlying member method code with example usage: obj.beam_search_for_tree_decoding(decoder_initial_state, decoder_initial_input, parent_state, graph_node_embedding, rnn_node_embedding, src_seq, oov_dict, sibling_state, device, topk, enc_batch) and returns: output_results