/// <summary>
        /// Train Neural Network (N.B Do not train for just 1 example, always randomize training data)
        /// </summary>
        /// <param name="neuralNetwork">Neural Network</param>
        /// <param name="trainingData">Training Data</param>
        /// <param name="epochs">Number of Training Epochs</param>
        /// <param name="activationFn">Activation Function</param>
        /// <param name="learningRate">Learning Rate</param>
        /// <returns>Results Array</returns>
        public double[][] Train(NeuralNetwork neuralNetwork, TrainingDataDTO trainingData, int epochs, IActivationFunction activationFn, double learningRate)
        {
            // Get / create some inital vars for results obj
            int arrayWidth = trainingData.Inputs.GetLength(0) + trainingData.ExpectedResults.GetLength(0);

            double[][] results = new double[epochs * trainingData.Inputs.Length][];
            int        counter = 0;

            for (int i = 0; i < epochs; i++)
            {
                for (int j = 0; j < trainingData.Inputs.Length; j++)
                {
                    double[] inputs          = trainingData.Inputs[j];
                    double[] expectedResults = trainingData.ExpectedResults[j];
                    _neuralNetworkProcessingService.ProcessFeedForwardNeuralNetwork(neuralNetwork, inputs, activationFn);

                    BackPropagate(neuralNetwork, expectedResults, activationFn, learningRate);

                    // Populate results obj
                    results[counter] =
                        inputs.Concat(expectedResults)                           // Inputs and Expected Results
                        .Concat(neuralNetwork.OutputLayer.Select(x => x.Output)) // Actual Outputs
                        .Concat(new double[1] {
                        neuralNetwork.GlobalError
                    }).ToArray();                                                       // Overall Global Network Error

                    counter++;
                }
            }

            return(results);
        }
        /// <summary>
        /// Get Training Data AND
        /// </summary>
        /// <returns>Training Data AND</returns>
        public TrainingDataDTO GetTrainingDataAND()
        {
            var trainingDataDTO = new TrainingDataDTO();

            // Training Data
            double[] data1 = { 0, 0 };
            double[] data2 = { 0, 1 };
            double[] data3 = { 1, 0 };
            double[] data4 = { 1, 1 };

            trainingDataDTO.Inputs = new double[][] { data1, data2, data3, data4 };

            trainingDataDTO.InputTitles = new string[2] {
                "Inp1", "Inp2"
            };

            // Expected Results
            double[] result1 = { 0 };
            double[] result2 = { 0 };
            double[] result3 = { 0 };
            double[] result4 = { 1 };

            trainingDataDTO.ExpectedResults       = new double[][] { result1, result2, result3, result4 };
            trainingDataDTO.ExpectedResultsTitles = new string[1] {
                "Res1"
            };

            return(trainingDataDTO);
        }
        /// <summary>
        /// Get Training Data Garden Design
        /// </summary>
        /// <returns>Training Data Garden Design</returns>
        public TrainingDataDTO GetTrainingDataGardenDesign()
        {
            var trainingDataDTO = new TrainingDataDTO();

            // Training Data
            double[] data1 = { 0, 0, 0 };
            double[] data2 = { 0, 0, 1 };
            double[] data3 = { 0, 1, 1 };
            double[] data4 = { 1, 1, 1 };
            double[] data5 = { 0, 1, 0 };
            double[] data6 = { 1, 0, 0 };
            double[] data7 = { 1, 0, 1 };
            double[] data8 = { 1, 1, 0 };

            trainingDataDTO.Inputs = new double[][] { data1, data2, data3, data4, data5, data6, data7, data8 };

            trainingDataDTO.InputTitles = new string[8] {
                "Inp1", "Inp2", "Inp3", "Inp4", "Inp5", "Inp6", "Inp7", "Inp8"
            };

            // Expected Results
            double[] result1 = { 1, 0, 0, 0, 0 };
            double[] result2 = { 0, 0, 0, 1, 0 };
            double[] result3 = { 0, 0, 0, 0, 1 };
            double[] result4 = { 0, 0, 0, 0, 1 };
            double[] result5 = { 0, 1, 0, 0, 0 };
            double[] result6 = { 0, 0, 1, 0, 0 };
            double[] result7 = { 0, 0, 0, 0, 1 };
            double[] result8 = { 0, 0, 0, 0, 1 };

            trainingDataDTO.ExpectedResults       = new double[][] { result1, result2, result3, result4, result5, result6, result7, result8 };
            trainingDataDTO.ExpectedResultsTitles = new string[8] {
                "LowMaint", "Child", "Gen", "Gen", "Ent", "Gard", "Gen", "Gen"
            };

            return(trainingDataDTO);
        }