private static void RunNeat(double[][] inputs, double[][] expectedOutputs, DenormalizationVariables denormalizationVariables)
        {
            Neat neat = new Neat();

            neat.OnGenerationEnd += (a) =>
            {
                Console.WriteLine(">  Gen " + a.Generation + "\tErr: " + a.Error);
            };

            Ann ann = neat.Train(100, 100, 0.03, 2, 30, false, inputs, expectedOutputs, Crossover.TwoPointCrossover, ActivationFunction.Sigmoid);

            double finalError = neat.CalculateError(ann, inputs, expectedOutputs, true);

            Console.WriteLine("Final error: " + finalError);

            int index = 1;

            double normalizedResult = Math.Round(ann.Execute(inputs[index])[0], 2);
            double actualResult     = DataManager.DenormalizeNumeric(normalizedResult, denormalizationVariables.NormalizedFloor, denormalizationVariables.NormalizedCeiling, denormalizationVariables.NumericNormalizationMargin, denormalizationVariables.SmallestTrainingValue, denormalizationVariables.LargestTrainingValue);
            double expectedResult   = DataManager.DenormalizeNumeric(expectedOutputs[index][0], denormalizationVariables.NormalizedFloor, denormalizationVariables.NormalizedCeiling, denormalizationVariables.NumericNormalizationMargin, denormalizationVariables.SmallestTrainingValue, denormalizationVariables.LargestTrainingValue);

            Console.WriteLine($">>> Expected Normalized result: {expectedOutputs[index][0]}");
            Console.WriteLine($">>> Actual Normalized result: {normalizedResult}");
            Console.WriteLine($">>> Expected real result: {expectedResult}");
            Console.WriteLine($">>> Actual real result: {actualResult}");
            Console.WriteLine($">>> Error in USD: {actualResult - expectedResult}");
            Console.WriteLine();
        }
        private static void TestWithSingleInput()
        {
            double[][] input =
            {
                new double[] { 1 },
                new double[] { 2 },
                new double[] { 3 },
                new double[] { 4 },
            };

            double[][] expectedOutput =
            {
                new double[] { 2 },
                new double[] { 4 },
                new double[] { 6 },
                new double[] { 8 },
            };

            Console.WriteLine("Attempting to teach how to double a number.");

            Neat neat = new Neat();

            neat.OnGenerationEnd += (a) =>
            {
                Console.WriteLine(">  Gen " + a.Generation + "\tErr: " + a.Error);
            };

            Ann ann = neat.Train(100, 100, 0.1, 1, 3, false, input, expectedOutput, Crossover.TwoPointCrossover, ActivationFunction.Identity);

            double result = ann.Execute(new double[] { 5 })[0];

            Console.WriteLine("> Input of 5, expected result of 10, real result: " + result);
        }
        private void ExecuteNeat()
        {
            bool wait = false;

            int inputCount  = 2;
            int outputCount = 1;
            int delay       = 150;

            Dispatcher.Invoke(() =>
            {
                controlsToDisable.ForEach(x => x.IsEnabled = false);
                controlsToEnable.ForEach(x => x.IsEnabled  = true);
                if (CbAnimate.IsChecked == true)
                {
                    wait = true;
                }

                inputCount  = int.TryParse(TbInputs.Text, out inputCount) ? inputCount : 2;
                outputCount = int.TryParse(TbOutputs.Text, out outputCount) ? outputCount : 1;
                delay       = int.TryParse(TbDelay.Text, out delay) ? delay : 0;
            });

            Neat neat = new Neat();

            neat.OnGenerationEnd += (a) =>
            {
                Dispatcher.Invoke(() =>
                {
                    TBSynapseData.Clear();
                    a.synapses.ForEach(x =>
                    {
                        TBSynapseData.Text += "FromLayer: " + x.FromLayer + "\n";
                        TBSynapseData.Text += "Fromneuron: " + x.FromNeuron + "\n";
                        TBSynapseData.Text += "ToLayer: " + x.ToLayer + "\n";
                        TBSynapseData.Text += "ToNeuron: " + x.ToNeuron + "\n";
                        TBSynapseData.Text += "Weight: " + x.Weight + "\n";
                        TBSynapseData.Text += "\n";
                    });

                    TBNeuronData.Clear();
                    a.hiddenNeurons.ForEach(x =>
                    {
                        TBNeuronData.Text += "Layer: " + x.Layer + "\n";
                        TBNeuronData.Text += "NeuronPosition: " + x.NeuronPosition + "\n";
                        TBNeuronData.Text += "Bias: " + x.Bias + "\n";
                        TBNeuronData.Text += "\n";
                    });

                    TBOutputNeurons.Clear();
                    a.outputNeurons.ToList().ForEach(x =>
                    {
                        TBOutputNeurons.Text += "Value: " + x.Value + "\n";
                        TBOutputNeurons.Text += "\n";
                    });
                });
                if (wait)
                {
                    DrawAnn(a);
                    Thread.Sleep(delay);
                }
                while (pause)
                {
                }
                neat.LowerWaitFlag();
            };


            string[] inputColumns = new string[]
            {
                //"movie_title",
                "genres",
                "director_name",
                "budget",
            };

            string[] expectedOutputColumns = new string[]
            {
                "gross",
            };

            NormalizedDataAndDictionaries inputData  = GetDataFromDatabase(inputColumns);
            NormalizedDataAndDictionaries outputData = GetDataFromDatabase(expectedOutputColumns);

            //Ann ann = neat.Train(10000, 100, 0.1, 3, 30, wait, inputs, expectedOutputs, Crossover.TwoPointCrossover, ActivationFunction.Identity);
            //Ann ann = neat.Train(1000, 100, 0.03, 3, 30, false, inputs, expectedOutputs, Crossover.TwoPointCrossover, ActivationFunction.Identity);
            //Ann ann = neat.Train(1000, 100, 0.03, 3, 30, false, inputData.NormalizedData, outputData.NormalizedData, Crossover.BestParentClone, ActivationFunction.Sigmoid);
            Ann ann = neat.Train(1000, 100, 0.03, 3, 30, false, inputData.NormalizedData, outputData.NormalizedData, Crossover.BestParentClone, ActivationFunction.Identity);

            Dispatcher.Invoke(() =>
            {
                controlsToDisable.ForEach(x => x.IsEnabled = true);
                controlsToEnable.ForEach(x => x.IsEnabled  = false);
                SVCanvas.Background = new SolidColorBrush(Colors.Gray);
            });

            if (!wait)
            {
                DrawAnn(ann);
            }
        }