'Computes the state of a layer, given the state of its incoming neighbours.
Args:
train: True if this computation is happening during training, False during
evaluation.
compute_input: If True, the state of the input layer will be computed.
Otherwise, it will be loaded as data.
step: Training step.
maxsteps: Maximum number of steps that will be taken (Some hyperparameters
may depend on this.)
use_samples: Use neighbours\' samples to update the layer\'s state.'

def ComputeUp(self, layer, train=False, compute_input=False, step=0, maxsteps=0, use_samples=False, neg_phase=False):

    if (layer.is_input and (not compute_input)):
        layer.GetData()
    else:
        for (i, edge) in enumerate(layer.incoming_edge):
            neighbour = layer.incoming_neighbour[i]
            if use_samples:
                inputs = neighbour.sample
            else:
                inputs = neighbour.state
            if (edge.node2 == layer):
                w = edge.params['weight'].T
                factor = edge.proto.up_factor
            else:
                w = edge.params['weight']
                factor = edge.proto.down_factor
            if (i == 0):
                cm.dot(w, inputs, target=layer.state)
                if (factor != 1):
                    layer.state.mult(factor)
            else:
                layer.state.add_dot(w, inputs, mult=factor)
        b = layer.params['bias']
        if (layer.replicated_neighbour is None):
            layer.state.add_col_vec(b)
        else:
            layer.state.add_dot(b, layer.replicated_neighbour.NN)
        layer.ApplyActivation()
    if layer.hyperparams.dropout:
        if (train and ((maxsteps - step) >= layer.hyperparams.stop_dropout_for_last)):
            if (not neg_phase):
                layer.mask.fill_with_rand()
                layer.mask.greater_than(layer.hyperparams.dropout_prob)
            layer.state.mult(layer.mask)
        else:
            layer.state.mult((1.0 - layer.hyperparams.dropout_prob))
