/// <summary> /// Computes the activation of node n. We initially start with output neurons, and work /// our way backward. /// </summary> private void ComputeActivation(Node n, List <Node> previousNodeRequests) { if (n.Role == NodeRole.Input || n.Role == NodeRole.Bias) { // It doesn't make sense to compute the activation of Input and Bias nodes. // The activation of the Bias node is always 1 // The activation of the input node comes from an external input vector. return; } n.IncomingActivity = 0; foreach (Link l in n.LinksIncoming.Values) { double activationContribution = 0; if (previousNodeRequests.Contains(l.NodeIn)) { // We've already asked about this node, so we must have hit a recurrent loop. // Use the previous activation, and stop asking. activationContribution = l.NodeIn.ActivationPrevious * l.Weight; } else { previousNodeRequests.Add(l.NodeIn); ComputeActivation(l.NodeIn, previousNodeRequests); // After computing, pop the last item off the list previousNodeRequests.RemoveAt(previousNodeRequests.Count - 1); activationContribution = l.NodeIn.ActivationCurrent * l.Weight; } n.IncomingActivity += activationContribution; } n.ActivationPrevious = n.ActivationCurrent; n.ActivationCurrent = ActivationFunctions.Sigmoidal_0_1(n.IncomingActivity); }