anchor.diff:                    N ! {fire, Self, Output, Token}
                   end, Outputs),
     {Output, [Output]};
  -fire_neuron(Inputs, Outputs, _, _, Token) ->
  +fire_neuron(Inputs, Outputs, _, _, Token, Activation) ->
     % -- hidden layer neuron
     Self = self(),
     Input = [receive {fire, Pid, In, Token} -> {Weight * In, In} end || {Pid, Weight} <- Inputs],
  -  Output = activation(sum_tuples(Input)),
  +  Output = activation(Activation, sum_tuples(Input)),
     lists:foreach(fun(Pid) ->
                     Pid ! {fire, Self, Output, Token}
                   end, Outputs),
  
positive.code:   [Weight | layer_weights(Outputs)].
  
  % -- learning
  learn_neuron([], Outputs, LearningRate, Main, Token) ->
    % -- bias neuron
    fire_neuron([], Outputs, {back_prop, LearningRate, Token}, Main, Token),
    [receive {delta, Pid, _, Token} -> ignore end || Pid <- Outputs],
    [];
  learn_neuron(Inputs, [], LearningRate, Main, Token) ->
    % -- output neuron
    {Output, Outs} = fire_neuron(Inputs, [], output_layer_fire, Main, Token),
    receive {target, Target, Token} -> Target end,
    Delta = (Output - Target) * output_activation_gradient(Output),
    update_weights(Inputs, Outs, Delta, LearningRate, Token);
  learn_neuron([{Pid, Weight}], Outputs, _, Main, Token) when Pid == Main ->
    % -- input layer neuron
    fire_neuron([{Pid, Weight}], Outputs, input_layer_fire, Main, Token),
    [receive {delta, N, InDelta, Token} -> InDelta end || N <- Outputs],
    [{Pid, Weight}];
  learn_neuron(Inputs, Outputs, LearningRate, Main, Token) ->
    % -- hidden layer neuron
    {Output, Outs} = fire_neuron(Inputs, Outputs, hidden_layer_fire, Main, Token),
    Delta = lists:sum([receive {delta, Pid, InDelta, Token} -> InDelta end || Pid <- Outputs]) * activation_gradient(Output),
    update_weights(Inputs, Outs, Delta, LearningRate, Token).
  
  update_weights(Inputs, Outs, Delta, LearningRate, Token) ->
  
negative.code:   Weights = random_weigths(compute_neurons(Layers)),
    create_neural_network(Layers, Weights).
  
  create_neural_network(Layers, Weights) when is_list(Weights) ->
    create_neural_network(Layers, Weights, sigmoid);
  create_neural_network(Layers, Activation) when is_atom(Activation) ->
    Weights = random_weigths(compute_neurons(Layers)),
    create_neural_network(Layers, Weights, Activation).
  
  create_neural_network(Layers, Weights, Activation) when length(Layers) > 1 ->
    Neurons = [[run_neuron(Activation) || _ <- lists:seq(1, InLayer)] || InLayer <- modify_layers(Layers)],
    full_mesh_connect(Neurons, Weights),
    NN = spawn_link(ann, neural_network, [
                      tl(hd(Neurons)),                                          % InputLayer
  