//  [python]
def table_sample_sequence_beam_search(*, hparams, beam_width, length, context=None, tables=None, keras_layers=[], temperature=1, top_k=0, top_p=0.0):
    beam_width_max = beam_width
    
    def step(hparams, tokens, past=None):
        beam_width = tokens.shape[0]
        lm_output = table_model.model(hparams=hparams, X=tokens, T=tables, keras_layers=keras_layers, past=past, reuse=tf.AUTO_REUSE)

        logits = lm_output['logits'][:, :, :hparams.n_vocab]
        presents = lm_output['present']
        shape = table_model.past_shape(hparams=hparams, batch_size=beam_width)
        presents.set_shape(shape)
        return {
            'logits': logits,
            'presents': presents,
        }
    def raw_body(past, prev, output):
            next_outputs = step(hparams, prev, past=past)
            logits = next_outputs['logits'][:, -1, :]  / tf.to_float(temperature)
            if top_p > 0.0:
                logits = top_p_logits(logits, p=top_p)
            else:
                logits = top_k_logits(logits, k=top_k)
            samples = tf.random.categorical(logits, num_samples=1)
            return [
                next_outputs['presents'] if past is None else tf.concat([past, next_outputs['presents']], axis=-2),
                samples,
                tf.concat([output, samples], axis=1)
            ]
    def init_body(past, prev, beam_width, log_beam_probs, beam_results):
        
        next_outputs = step(hparams, prev, past=past)
        #outputs['logits']: [batch, sequence, hparams.n_vocab]
        logits = next_outputs['logits'][:, -1, :]
        '''
        #得到beam_width个序列的下一个词的概率分布
        if top_p > 0.0:
            logits = top_p_logits(logits, p=top_p)
        else:
            logits = top_k_logits(logits, k=top_k)
        '''
        probs = tf.log(tf.nn.softmax(logits) + 1e-12)
        #取log，方便后续计算
        best_probs, indices = tf.nn.top_k(probs, beam_width)
        indices = tf.reshape(tf.stop_gradient(indices), [beam_width, -1])
        best_probs = tf.reshape(tf.stop_gradient(best_probs), [beam_width, -1])
        symbols = indices
        beam_parent = tf.constant([[0], [0], [0], [0], [0]])

        #解码到<EOS>符号，终止解码
        partition = tf.cast(tf.cast(symbols-hparams.n_vocab+1, tf.bool), tf.int32)

        prob_group = tf.dynamic_partition(best_probs, partition, 2)
        symbols_group = tf.dynamic_partition(symbols, partition, 2)
        parent_group = tf.dynamic_partition(beam_parent, partition, 2)
        new_indices = parent_group[1]
        
        #取出含<EOS>符号的beam，并保存对应结果
        #eos_prev = symbols_group[0]
        #eos_output = tf.concat([tf.gather(output, parent_group[0]), eos_prev], axis=1)
        #new_beam_results_eos = tf.reshape(symbols_group[0], eos_num)

        #不含<EOS>符号的beam, 找到对应的之前的序列，拼接符号序列以及对应的概率
        
        eos_num = tf.shape(prob_group[0])
        beam_width -= eos_num

        new_past = tf.gather(next_outputs['presents'], new_indices)
        
        new_prev = tf.reshape(symbols_group[1], [-1, 1])
        
        new_beam_results_eos = tf.reshape(symbols_group[0], beam_width_max-beam_width)
        new_beam_results = tf.concat([symbols_group[1], new_beam_results_eos], 0)


        new_log_beam_probs_eos = tf.reshape(prob_group[0], beam_width_max-beam_width)
        new_log_beam_probs = tf.concat([prob_group[1], new_log_beam_probs_eos], 0)

        log_beam_probs = tf.reshape(new_log_beam_probs, [-1, 1])
        beam_results = tf.reshape(new_beam_results, [-1, 1])

        

        # 否则，则更新上面的值，进入下个循环 

        # Note that gradients will not propagate through the second parameter of
        # embedding_lookup.
        '''
        emb_prev = embedding_ops.embedding_lookup(embedding, _symbols)
        emb_prev = tf.reshape(emb_prev,[beam_size,embedding_size])
        # emb_prev = embedding_ops.embedding_lookup(embedding, symbols)
        if not update_embedding:
            emb_prev = array_ops.stop_gradient(emb_prev)
        return emb_prev
        '''
        #samples = tf.multinomial(logits, num_samples=1, output_dtype=tf.int32)
        return [
            new_past,
            new_prev,
            beam_width,
            log_beam_probs,
            beam_results
        ]
    
    def body(past, prev, beam_width, log_beam_probs, beam_results):
        beam_results_eos = beam_results[beam_width[0]:,:]
        next_outputs = step(hparams, prev, past=past)
        #outputs['logits']: [batch, sequence, hparams.n_vocab]
        #logits = next_outputs['logits'][:, -1, :]  / tf.to_float(temperature)
        logits = next_outputs['logits'][:, -1, :]
        '''
        if top_p > 0.0:
            logits = top_p_logits(logits, p=top_p)
        else:
            logits = top_k_logits(logits, k=top_k)
        '''
        probs = tf.log(tf.nn.softmax(logits) + 1e-12)

        probs = tf.reshape(probs + tf.reshape(log_beam_probs[:beam_width[0],-1],[beam_width[0],-1]), [-1, beam_width[0] * hparams.n_vocab])
        best_probs, indices = tf.nn.top_k(probs, beam_width[0])
        indices = tf.stop_gradient(indices)
        best_probs = tf.stop_gradient(best_probs)
        symbols = indices % (hparams.n_vocab)
        beam_parent = indices // (hparams.n_vocab)


        partition = tf.cast(tf.cast(symbols-hparams.n_vocab+1, tf.bool), tf.int32)

        prob_group = tf.dynamic_partition(best_probs, partition, 2)
        symbols_group = tf.dynamic_partition(symbols, partition, 2)
        parent_group = tf.dynamic_partition(beam_parent, partition, 2)
        beam_width = tf.shape(prob_group[1])

        new_indices = parent_group[1]
        new_beam_results = tf.reshape(symbols_group[1], [beam_width[0], -1])

        eos_num = beam_width_max - tf.shape(prob_group[1])[0]
        
        
        new_beam_results_eos = tf.fill([eos_num, 1], hparams.n_vocab-1)
        new_beam_results = tf.concat([new_beam_results, new_beam_results_eos], 0)
            
        
        new_past = tf.gather(tf.concat([past, next_outputs['presents']], axis=-2), new_indices)
        new_prev = tf.reshape(symbols_group[1], [beam_width[0], -1])
        
        new_log_eos = tf.fill([eos_num, 1], -math.inf)
        best_probs = tf.transpose(best_probs)
        new_log_beam_probs = tf.gather(best_probs, new_indices)
        
        new_log_beam_probs = tf.concat([new_log_beam_probs, new_log_eos], 0)
        log_beam_probs = tf.concat([log_beam_probs, new_log_beam_probs], -1)

        beam_eos = tf.concat([tf.gather(beam_results, parent_group[0]), beam_results_eos], 0)
        #new_beam_eos = tf.concat([beam_eos, tf.fill([eos_num, 1], hparams.n_vocab-1)], -1)

        new_beam = tf.concat([tf.gather(beam_results, new_indices), beam_eos], 0)

        beam_results = tf.concat([new_beam, new_beam_results], -1)

        # Note that gradients will not propagate through the second parameter of
        # embedding_lookup.
        '''
        emb_prev = embedding_ops.embedding_lookup(embedding, _symbols)
        emb_prev = tf.reshape(emb_prev,[beam_size,embedding_size])
        # emb_prev = embedding_ops.embedding_lookup(embedding, symbols)
        if not update_embedding:
            emb_prev = array_ops.stop_gradient(emb_prev)
        return emb_prev
        '''
        #samples = tf.multinomial(logits, num_samples=1, output_dtype=tf.int32)
        return [
            new_past,
            new_prev,
            beam_width,
            tf.reshape(log_beam_probs, [beam_width_max, -1]),
            tf.reshape(beam_results, [beam_width_max, -1])
        ]
        #context = tf.tile(context, [beam_width, -1])
        #log_beam_probs, beam_results, out = raw_body(None, context, context)
    past, prev, beam_width, log_beam_probs, beam_results = init_body(None, context, tf.constant(beam_width), None, None)
    '''
    for i in range(99):
        if beam_width[0] == 0:
            break
        past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    '''
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #past, prev, beam_width, log_beam_probs, beam_results = body(past, prev, beam_width, log_beam_probs, beam_results)
    #return log_beam_probs, beam_results

    def cond(past,
            prev,
            beam_width, log_beam_probs, beam_results):
        return (beam_width[0] > 0)
    #'''
    _, _, beam_width, log_beam_probs, beam_results = tf.while_loop(
        cond=cond, body=body,
        maximum_iterations=length - 1,
        loop_vars=[
            past,
            prev,
            beam_width, log_beam_probs,  beam_results
        ],
        shape_invariants=[
            tf.TensorShape(table_model.past_shape(hparams=hparams, batch_size=None)),
            tf.TensorShape([None, None]),
            tf.TensorShape([1]),
            tf.TensorShape([beam_width_max, None]),
            tf.TensorShape([beam_width_max, None]),
        ],
        back_prop=False,
    )
    #'''
    
    return log_beam_probs, beam_results