'Constructs the computational graph of this layer.
If the input is ints, we assume is an index, otherwise we assume is
a set of floats.'

def fprop(self, state_below, use_noise=True, no_noise_bias=False, first_only=False):

    if (self.weight_noise and use_noise and self.noise_params):
        W_ems = [(x + y) for (x, y) in zip(self.W_ems, self.nW_ems)]
        if (not no_noise_bias):
            b_ems = [(x + y) for (x, y) in zip(self.b_ems, self.nb_ems)]
        else:
            b_ems = self.b_ems
    else:
        W_ems = self.W_ems
        b_ems = self.b_ems
    if self.rank_n_approx:
        if first_only:
            emb_val = self.rank_n_activ(utils.dot(state_below, W_ems[0]))
            self.out = emb_val
            return emb_val
        emb_val = TT.dot(self.rank_n_activ(utils.dot(state_below, W_ems[0])), W_ems[1])
        if b_ems:
            emb_val += b_ems[0]
        st_pos = 1
    else:
        emb_val = utils.dot(state_below, W_ems[0])
        if b_ems:
            emb_val += b_ems[0]
        st_pos = 0
    emb_val = self.activation[0](emb_val)
    if (self.dropout < 1.0):
        if use_noise:
            emb_val = (emb_val * self.trng.binomial(emb_val.shape, n=1, p=self.dropout, dtype=emb_val.dtype))
        else:
            emb_val = (emb_val * self.dropout)
    for dx in xrange(1, self.n_layers):
        emb_val = utils.dot(emb_val, W_ems[(st_pos + dx)])
        if b_ems:
            emb_val = self.activation[dx]((emb_val + b_ems[dx]))
        else:
            emb_val = self.activation[dx](emb_val)
        if (self.dropout < 1.0):
            if use_noise:
                emb_val = (emb_val * self.trng.binomial(emb_val.shape, n=1, p=self.dropout, dtype=emb_val.dtype))
            else:
                emb_val = (emb_val * self.dropout)
    self.out = emb_val
    return emb_val
