protected void PropogateSecondDerivatives(Step downstream, Step upstream, int upstreamNeuron, int inputNeuron)
{
int weightIndex = inputNeuron * OutputNeurons;
double upstreamState = upstream.Output[upstreamNeuron];
double upstreamErrorSecondDerivative = 0.0;
for (int output = 0; output < OutputNeurons; output++)
{
double downstreamErrorSecondDerivative = downstream.ErrorDerivative[output]; // (d^2)E/(dAj)^2, where Aj is the sum of inputs to this downstream unit.
// Here we calculate (d^2)Ej/(dWij)^2 by multiplying the 2nd derivative of E with respect to the sum of inputs, Aj
// by the state of Oi, the upstream unit, squared. Refer to Equation 25 in document.
// The summing happening here is described by equation 23.
double weight2ndDerivative = downstreamErrorSecondDerivative * upstreamState * upstreamState;
WeightStepSize[weightIndex] = weight2ndDerivative;
double weight = Weight[weightIndex];
// This is implementing the last sigma of Equation 27.
// This propogates error second derivatives back to previous layer, but will need to be multiplied by the second derivative
// of the activation function at the previous layer.
upstreamErrorSecondDerivative += weight * weight * downstreamErrorSecondDerivative;
weightIndex += 1;
}
upstream.ErrorDerivative[upstreamNeuron] += upstreamErrorSecondDerivative;
}