'Run a step of the network.'

def step(self, sess, inp, target, do_backward_in, noise_param=None, beam_size=2, eos_id=2, eos_cost=0.0, update_mem=None, state=None):

    (batch_size, height, length) = (inp.shape[0], inp.shape[1], inp.shape[2])
    do_backward = do_backward_in
    train_mode = True
    if (do_backward_in is None):
        do_backward = False
        train_mode = False
    if (update_mem is None):
        update_mem = do_backward
    feed_in = {}
    if (state is None):
        state = np.zeros([batch_size, length, height, self.nmaps])
    feed_in[self.prev_step.name] = state
    feed_in[self.length_tensor.name] = length
    feed_in[self.noise_param.name] = (noise_param if noise_param else 0.0)
    feed_in[self.do_training.name] = (1.0 if do_backward else 0.0)
    feed_in[self.update_mem.name] = (1 if update_mem else 0)
    if (do_backward_in is False):
        feed_in[self.sampling.name] = 0.0
    index = 0
    feed_out = []
    if do_backward:
        feed_out.append(self.updates[index])
        feed_out.append(self.grad_norms[index])
    if train_mode:
        feed_out.append(self.losses[index])
    feed_in[self.input.name] = inp
    feed_in[self.target.name] = target
    feed_out.append(self.outputs[index])
    if train_mode:
        res = sess.run(([self.after_enc_step] + feed_out), feed_in)
        (after_enc_state, res) = (res[0], res[1:])
    else:
        feed_in[self.sampling.name] = 1.1
        res = sess.run(([self.after_enc_step, self.out_idx] + feed_out), feed_in)
        (after_enc_state, out_idx) = (res[0], res[1])
        res = [res[2][l] for l in xrange(length)]
        outputs = [out_idx[:, i] for i in xrange(length)]
        cost = [0.0 for _ in xrange((beam_size * batch_size))]
        seen_eos = [0 for _ in xrange((beam_size * batch_size))]
        for (idx, logit) in enumerate(res):
            best = outputs[idx]
            for b in xrange(batch_size):
                if (seen_eos[b] > 1):
                    cost[b] -= eos_cost
                else:
                    cost[b] += np.log(logit[b][best[b]])
                if (best[b] in [eos_id]):
                    seen_eos[b] += 1
        res = ([[(- c) for c in cost]] + outputs)
    offset = 0
    norm = None
    if do_backward:
        offset = 2
        norm = res[1]
    if train_mode:
        outputs = res[(offset + 1)]
        outputs = [outputs[l] for l in xrange(length)]
    return (res[offset], outputs, norm, after_enc_state)
