docs: def generate(oracle, seq_len, p=0.5, k=1, LRS=0, weight=None):
      """ Generate a sequence based on traversing an oracle.
  
      :param oracle: a indexed vmo object
      :param seq_len: the length of the returned improvisation sequence
      :param p: a float between (0,1) representing the probability using the forward links.
      :param k: the starting improvisation time step in oracle
      :param LRS: the length of minimum longest repeated suffixes allowed to jump
      :param weight:
              None: choose uniformly among all the possible sfx/rsfx given
                  current state.
              "max": always choose the sfx/rsfx having the longest LRS.
              "weight": choose sfx/rsfx in a way that favors longer ones than
              shorter ones.
      :return:
              s: a list containing the sequence generated, each element represents a
              state.
              kend: the ending state.
              ktrace:
      """
  
      trn = oracle.trn[:]
      sfx = oracle.sfx[:]
      lrs = oracle.lrs[:]
      rsfx = oracle.rsfx[:]
  
      s = []
      ktrace = [1]
  
      for _i in range(seq_len):
          # generate each state
          if sfx[k] != 0 and sfx[k] is not None:
              if (random.random() < p):
                  # copy forward according to transitions
                  I = trn[k]
                  if len(I) == 0:
                      # if last state, choose a suffix
                      k = sfx[k]
                      ktrace.append(k)
                      I = trn[k]
                  sym = I[int(np.floor(random.random() * len(I)))]
                  s.append(sym)  # Why (sym-1) before?
                  k = sym
                  ktrace.append(k)
              else:
                  # copy any of the next symbols
                  ktrace.append(k)
                  _k = k
                  k_vec = []
                  k_vec = _find_links(k_vec, sfx, rsfx, _k)
                  k_vec = [_i for _i in k_vec if lrs[_i] >= LRS]
                  lrs_vec = [lrs[_i] for _i in k_vec]
                  if len(k_vec) > 0:  # if a possibility found, len(I)
                      if weight == 'weight':
                          max_lrs = np.amax(lrs_vec)
                          query_lrs = max_lrs - np.floor(random.expovariate(1))
  
                          if query_lrs in lrs_vec:
                              _tmp = np.where(lrs_vec == query_lrs)[0]
                              _tmp = _tmp[int(
                                  np.floor(random.random() * len(_tmp)))]
                              sym = k_vec[_tmp]
                          else:
                              _tmp = np.argmin(abs(
                                  np.subtract(lrs_vec, query_lrs)))
                              sym = k_vec[_tmp]
                      elif weight == 'max':
                          sym = k_vec[np.argmax([lrs[_i] for _i in k_vec])]
                      else:
                          sym = k_vec[int(np.floor(random.random() * len(k_vec)))]
  
                      if sym == len(sfx) - 1:
                          sym = sfx[sym] + 1
                      else:
                          s.append(sym + 1)
                      k = sym + 1
                      ktrace.append(k)
                  else:  # otherwise continue
                      if k < len(sfx) - 1:
                          sym = k + 1
                      else:
                          sym = sfx[k] + 1
                      s.append(sym)
                      k = sym
                      ktrace.append(k)
          else:
              if k < len(sfx) - 1:
                  s.append(k + 1)
                  k += 1
                  ktrace.append(k)
              else:
                  sym = sfx[k] + 1
                  s.append(sym)
                  k = sym
                  ktrace.append(k)
          if k >= len(sfx) - 1:
              k = 0
      kend = k
      return s, kend, ktrace