def forward(self, inputs=None, encoder_hidden=None, encoder_outputs=None, function=F.log_softmax, teacher_forcing_ratio=0):
    ret_dict = dict()
    if self.use_attention:
        ret_dict[DecoderRNN.KEY_ATTN_SCORE] = list()
    (inputs, batch_size, max_length) = self._validate_args(inputs, encoder_hidden, encoder_outputs, function, teacher_forcing_ratio)
    decoder_hidden = self._init_state(encoder_hidden)
    use_teacher_forcing = (True if (random.random() < teacher_forcing_ratio) else False)
    decoder_outputs = []
    sequence_symbols = []
    lengths = np.array(([max_length] * batch_size))

    def decode(step, step_output, step_attn):
        decoder_outputs.append(step_output)
        if self.use_attention:
            ret_dict[DecoderRNN.KEY_ATTN_SCORE].append(step_attn)
        symbols = decoder_outputs[(- 1)].topk(1)[1]
        sequence_symbols.append(symbols)
        eos_batches = symbols.data.eq(self.eos_id)
        if (eos_batches.dim() > 0):
            eos_batches = eos_batches.cpu().view((- 1)).numpy()
            update_idx = (((lengths > step) & eos_batches) != 0)
            lengths[update_idx] = len(sequence_symbols)
        return symbols
    if use_teacher_forcing:
        decoder_input = inputs[:, :(- 1)]
        (decoder_output, decoder_hidden, attn) = self.forward_step(decoder_input, decoder_hidden, encoder_outputs, function=function)
        for di in range(decoder_output.size(1)):
            step_output = decoder_output[:, di, :]
            if (attn is not None):
                step_attn = attn[:, di, :]
            else:
                step_attn = None
            decode(di, step_output, step_attn)
    else:
        decoder_input = inputs[:, 0].unsqueeze(1)
        for di in range(max_length):
            (decoder_output, decoder_hidden, step_attn) = self.forward_step(decoder_input, decoder_hidden, encoder_outputs, function=function)
            step_output = decoder_output.squeeze(1)
            symbols = decode(di, step_output, step_attn)
            decoder_input = symbols
    ret_dict[DecoderRNN.KEY_SEQUENCE] = sequence_symbols
    ret_dict[DecoderRNN.KEY_LENGTH] = lengths.tolist()
    return (decoder_outputs, decoder_hidden, ret_dict)
def forward(self, inputs=None, encoder_hidden=None, encoder_outputs=None, function=F.log_softmax, teacher_forcing_ratio=0):
    ret_dict = dict()
    if self.use_attention:
        ret_dict[DecoderRNN.KEY_ATTN_SCORE] = list()
    (inputs, batch_size, max_length) = self._validate_args(inputs, encoder_hidden, encoder_outputs, function, teacher_forcing_ratio)
    decoder_hidden = self._init_state(encoder_hidden)
    use_teacher_forcing = (True if (random.random() < teacher_forcing_ratio) else False)
    decoder_outputs = []
    sequence_symbols = []
    lengths = np.array(([max_length] * batch_size))

    def decode(step, step_output, step_attn):
        decoder_outputs.append(step_output)
        if self.use_attention:
            ret_dict[DecoderRNN.KEY_ATTN_SCORE].append(step_attn)
        symbols = decoder_outputs[(- 1)].topk(1)[1]
        sequence_symbols.append(symbols)
        eos_batches = symbols.data.eq(self.eos_id)
        if (eos_batches.dim() > 0):
            eos_batches = eos_batches.cpu().view((- 1)).numpy()
            update_idx = (((lengths > step) & eos_batches) != 0)
            lengths[update_idx] = len(sequence_symbols)
        return symbols
    if use_teacher_forcing:
        decoder_input = inputs[:, :(- 1)]
        (decoder_output, decoder_hidden, attn) = self.forward_step(decoder_input, decoder_hidden, encoder_outputs, function=function)
        for di in range(decoder_output.size(1)):
            step_output = decoder_output[:, di, :]
            if (attn is not None):
                step_attn = attn[:, di, :]
            else:
                step_attn = None
            decode(di, step_output, step_attn)
    else:
        decoder_input = inputs[:, 0].unsqueeze(1)
        for di in range(max_length):
            (decoder_output, decoder_hidden, step_attn) = self.forward_step(decoder_input, decoder_hidden, encoder_outputs, function=function)
            step_output = decoder_output.squeeze(1)
            symbols = decode(di, step_output, step_attn)
            decoder_input = symbols
    ret_dict[DecoderRNN.KEY_SEQUENCE] = sequence_symbols
    ret_dict[DecoderRNN.KEY_LENGTH] = lengths.tolist()
    return (decoder_outputs, decoder_hidden, ret_dict)