/// <summary>Initializes a new instance of the <see cref="AdaptiveGaussKronrodIntegrator"/> class.
 /// </summary>
 /// <param name="integrationRule">The integration rule.</param>
 /// <param name="exitCondition">The exit condition.</param>
 public AdaptiveGaussKronrodIntegrator(Approach integrationRule, StoppingCriteria exitCondition)
     : base(BoundDescriptor.Closed, BoundDescriptor.Closed)
 {
     if (exitCondition == null)
     {
         throw new ArgumentNullException("exitCondition");
     }
     ExitCondition   = exitCondition;
     IntegrationRule = integrationRule;
     m_Name          = new IdentifierString(String.Format("Adaptive Gauss-Kronrod {0} Integrator", integrationRule.ToFormatString()));
 }
        /// <summary>
        /// Processes the GA to search for an optimal TSP solution until the stopping criteria is met.
        /// </summary>
        public void Compute(bool showProgression = true)
        {
            Console.ForegroundColor = ConsoleColor.White;

            Console.WriteLine($"\nStart TSP Genetic Algorithm [Starting Date Time {DateTime.Now}]");
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine($"\nTSP_Instance\n************\nName: {_tspInstance.Name}\nComment: {_tspInstance.Comment}\nDimension: {_tspInstance.Dimensions}\nEdge_Weight_Type: {_tspInstance.EdgeWeightType}");
            Console.WriteLine($"\nOptions\n*********\nPopulation: {GaOptions.PopulationSize}\nEncoding_Type: {GaOptions.EncodingType}\nSelection_Operator: {GaOptions.SelectionType}\nCrossover_Operator: {GaOptions.CrossoverType}\nMutation_Operator: {GaOptions.MutationType}" +
                              $"\nMutation_Rate: {GaOptions.MutationRate}\nElite_Rate: {GaOptions.Elitism}\n{StoppingCriteria.CriteriaToString()}\n");
            Console.ForegroundColor = ConsoleColor.White;

            CreateInitialPopulation();
            var bestIndex       = Population.HighestFitnessIndex;
            var bestChromomsome = Population.Chromosomes[bestIndex];

            Console.WriteLine($"Best initial distance: {bestChromomsome.Distance} \nComputing...");

            // stops when the stopping criteria is met
            while (!StoppingCriteria.IsCriteriaMet())
            {
                bestIndex = Population.HighestFitnessIndex;

                var currentBestChromomsome = Population.Chromosomes[bestIndex];
                if (currentBestChromomsome.Fitness > bestChromomsome.Fitness)
                {
                    bestChromomsome = currentBestChromomsome;

                    if (showProgression)
                    {
                        Console.WriteLine($"A new shorter distance was found at generation {Generation} with distance {bestChromomsome.Distance}");
                    }
                }

                CreateNextGeneration();
            }

            // since we dont have a reference to the starting and ending city [1] in the Genome we add these so we could display them,
            // as they are taken into consideration when calculating fitness and we always start and end at City with ID 1
            Console.WriteLine($"\nDistance for the most optimal tour: {bestChromomsome.Distance}");
            Console.WriteLine($"1,{string.Join(",", bestChromomsome.GetGenome())},1");
            Console.WriteLine($"\nEnd TSP Genetic Algorithm [Finished Date Time {DateTime.Now}]\n");
        }
 /// <summary>Initializes a new instance of the <see cref="AdaptiveGaussLobattoIntegrator"/> class.
 /// </summary>
 /// <param name="exitCondition">The exit condition.</param>
 public AdaptiveGaussLobattoIntegrator(StoppingCriteria exitCondition)
     : base(BoundDescriptor.Closed, BoundDescriptor.Closed)
 {
     ExitCondition = exitCondition ?? throw new ArgumentNullException(nameof(exitCondition));
     m_Name        = new IdentifierString("Adaptive Gauss-Lobatto Integrator");
 }