// train the neural network
        public void Train(double[] inputsList, double[] targetsList)
        {
            // Convert inputs and targets list (one-dimensional) to two-dimensional, one-column matrices.
            double[,] inputs = new double[inputsList.Length, 1];
            inputs.SetColumn(0, inputsList);

            // calculate signals into hidden layer
            double[,] hiddenInputs = Wih.Dot(inputs);
            // calculate the signals emerging from hidden layer
            double[,] hiddenOutputs = hiddenInputs.Apply(x => ActivationFunction(x));

            // calculate signals into final output layer
            double[,] finalInputs = Who.Dot(hiddenOutputs);
            // calculate the signals emerging from final output layer
            double[,] finalOutputs = finalInputs.Apply(x => ActivationFunction(x));

            // output layer error is the (target - actual)
            double[] outputError = targetsList.Subtract(finalOutputs.GetColumn(0));
            // hidden layer error is the output_errors, split by weights, recombined at hidden nodes
            double[] hiddenError = Who.TransposeAndDot(outputError);

            // update the weights for the links between the hidden and output layers
            UpdateWeigths(hiddenOutputs, finalOutputs, ref Who, outputError);

            // update the weights for the links between the input and hidden layers
            UpdateWeigths(inputs, hiddenOutputs, ref Wih, hiddenError);
        }
        // ----------------------------------------------------------------------------------------

        // Helper function for updating weight values during backpropagation.
        private void UpdateWeigths(double[,] layer1, double[,] layer2, ref double[,] weigths, double[] errorList)
        {
            // Convert errors list (one-dimensional) to two-dimensional, one-column matrix.
            double[,] errors = Matrix.Create <double>(errorList.Length, 1);
            errors.SetColumn(0, errorList);

            // Calculate delta matrix (differences for updating weight values).
            double[,] deltas = Elementwise.Multiply(errors, layer2.Apply(x => x * (1 - x)))
                               .Dot(layer1.Transpose())
                               .Apply(x => x * .1);

            // Apply delta matrix.
            weigths = weigths.Add(deltas);
        }
        // query the neural network
        public double[] Query(double[] inputsList)
        {
            // Convert inputs list (one-dimensional) to two-dimensional, one-column matrix.
            double[,] inputs = Matrix.Create <double>(inputsList.Length, 1);
            inputs.SetColumn(0, inputsList);

            // calculate signals into hidden layer
            double[,] hiddenInputs = Wih.Dot(inputs);
            // calculate the signals emerging from hidden layer
            double[,] hiddenOutputs = hiddenInputs.Apply(x => ActivationFunction(x));

            // calculate signals into final output layer
            double[,] finalInputs = Who.Dot(hiddenOutputs);
            // calculate the signals emerging from final output layer
            double[,] finalOutputs = finalInputs.Apply(x => ActivationFunction(x));

            // Convert output node matrix back to a 1-dimensional list of values.
            return(finalOutputs.GetColumn(0));
        }