code: def ctcBeamSearch(
      mat, classes, ignore_idx, lm, beamWidth=25, dict_list=[]
  ):
      "beam search as described by the paper of Hwang et al. and the paper of Graves et al."
  
      # blankIdx = len(classes)
      blankIdx = 0
      maxT, maxC = mat.shape
  
      # initialise beam state
      last = BeamState()
      labeling = ()
      last.entries[labeling] = BeamEntry()
      last.entries[labeling].prBlank = 1
      last.entries[labeling].prTotal = 1
  
      # go over all time-steps
      for t in range(maxT):
          curr = BeamState()
  
          # get beam-labelings of best beams
          bestLabelings = last.sort()[0:beamWidth]
  
          # go over best beams
          for labeling in bestLabelings:
              # probability of paths ending with a non-blank
              prNonBlank = 0
              # in case of non-empty beam
              if labeling:
                  # probability of paths with repeated last char at the end
                  prNonBlank = (
                      last.entries[labeling].prNonBlank
                      * mat[t, labeling[-1]]
                  )
  
              # probability of paths ending with a blank
              prBlank = (last.entries[labeling].prTotal) * mat[
                  t, blankIdx
              ]
  
              # add beam at current time-step if needed
              addBeam(curr, labeling)
  
              # fill in data
              curr.entries[labeling].labeling = labeling
              curr.entries[labeling].prNonBlank += prNonBlank
              curr.entries[labeling].prBlank += prBlank
              curr.entries[labeling].prTotal += prBlank + prNonBlank
              curr.entries[labeling].prText = last.entries[
                  labeling
              ].prText  # beam-labeling not changed, therefore also LM score unchanged from
              curr.entries[
                  labeling
              ].lmApplied = True  # LM already applied at previous time-step for this beam-labeling
  
              # extend current beam-labeling
              for c in range(maxC - 1):
                  # add new char to current beam-labeling
                  newLabeling = labeling + (c,)
  
                  # if new labeling contains duplicate char at the end, only consider paths ending with a blank
                  if labeling and labeling[-1] == c:
                      prNonBlank = (
                          mat[t, c] * last.entries[labeling].prBlank
                      )
                  else:
                      prNonBlank = (
                          mat[t, c] * last.entries[labeling].prTotal
                      )
  
                  # add beam at current time-step if needed
                  addBeam(curr, newLabeling)
  
                  # fill in data
                  curr.entries[newLabeling].labeling = newLabeling
                  curr.entries[newLabeling].prNonBlank += prNonBlank
                  curr.entries[newLabeling].prTotal += prNonBlank
  
                  # apply LM
                  # applyLM(curr.entries[labeling], curr.entries[newLabeling], classes, lm)
  
          # set new beam state
          last = curr
  
      # normalise LM scores according to beam-labeling-length
      last.norm()
  
      # sort by probability
      # bestLabeling = last.sort()[0] # get most probable labeling
  
      # map labels to chars
      # res = ''
      # for idx,l in enumerate(bestLabeling):
      #    if l not in ignore_idx and (not (idx > 0 and bestLabeling[idx - 1] == bestLabeling[idx])):  # removing repeated characters and blank.
      #        res += classes[l]
  
      if dict_list == []:
          bestLabeling = last.sort()[0]  # get most probable labeling
          res = ""
          for i, l in enumerate(bestLabeling):
              if l not in ignore_idx and (
                  not (i > 0 and bestLabeling[i - 1] == bestLabeling[i])
              ):  # removing repeated characters and blank.
                  res += classes[l]
      else:
          res = last.wordsearch(
              classes, ignore_idx, beamWidth, dict_list
          )
  
      return res
  
imports: import torch
  import pickle
  import numpy
label_desc: Use image node_id 3 for calling a global function with example usage: ctcBeamSearch(mat, classes, ignore_idx, lm, beamWidth, dict_list) and returns: res