public OptimizationResult Optimize(InputDataEntity inputDataEntity)
        {
            InputDataEntity          = inputDataEntity;
            NumberOfBitsInChromosome = PopulationService.CalculateNumberOfBitsInChromosome(inputDataEntity.DataRange, inputDataEntity.Accuracy);
            BinaryChromosomes        = PopulationService.GeneratePopulation(inputDataEntity.PopulationAmount, NumberOfBitsInChromosome);
            // Method selection
            ISelection selectionMethod                = GetSelectionMethod(InputDataEntity.SelectionMethod, inputDataEntity);
            ICross     crossMethod                    = GetCrossMethod(InputDataEntity.CrossMethod);
            IMutation  mutationMethod                 = GetMutationMethod(InputDataEntity.MutationMethod);
            var        bestOfEachEpoch                = new List <FunctionResult>();
            List <BinaryChromosome> tmpBest           = new List <BinaryChromosome>();
            List <double>           means             = new List <double>();
            List <double>           standardDeviation = new List <double>();
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            for (int i = 0; i < InputDataEntity.EpochsAmount; i++)
            {
                List <BinaryChromosome> newPopulation = selectionMethod.ApplySelection(BinaryChromosomes, inputDataEntity.DataRange, NumberOfBitsInChromosome);
                if (i != 0)
                {
                    double newValue = GetFunctionResultForChromosomes(newPopulation[0], newPopulation[1], inputDataEntity.DataRange).FunctionValue;
                    double oldValue = GetFunctionResultForChromosomes(tmpBest[0], tmpBest[1], inputDataEntity.DataRange).FunctionValue;
                    if ((inputDataEntity.Maximize == false && newValue > oldValue) || (inputDataEntity.Maximize == true && newValue < oldValue))
                    {
                        newPopulation.InsertRange(0, tmpBest);
                    }
                    else
                    {
                        newPopulation.InsertRange(newPopulation.Count - 1, tmpBest);
                    }
                }
                bestOfEachEpoch.Add(GetFunctionResultForChromosomes(newPopulation[0], newPopulation[1], inputDataEntity.DataRange));
                tmpBest.Clear();
                for (int j = 0; j < inputDataEntity.EliteStrategyAmount * 2; j++)
                {
                    tmpBest.Add(newPopulation[j]);
                }
                means.Add(CalculateMean(newPopulation, inputDataEntity.DataRange));
                standardDeviation.Add(CalculateDeviation(newPopulation, inputDataEntity.DataRange, means[i]));
                List <BinaryChromosome> crossedPopulation        = crossMethod.Cross(newPopulation, InputDataEntity.CrossProbability);
                List <BinaryChromosome> mutatedPopulation        = mutationMethod.Mutate(crossedPopulation, InputDataEntity.MutationProbability);
                List <BinaryChromosome> populationAfterInversion = Inversion.PerformInversion(mutatedPopulation, InputDataEntity.InversionProbability);
                BinaryChromosomes = populationAfterInversion;
                if (BinaryChromosomes.Count <= 2)
                {
                    break;
                }
            }

            var    bestIndividuals = selectionMethod.ApplySelection(BinaryChromosomes, inputDataEntity.DataRange, NumberOfBitsInChromosome).Take(2).ToArray();
            double x1       = BinaryUtils.BinaryToDecimalRepresentation(bestIndividuals[0].BinaryRepresentation, inputDataEntity.DataRange, NumberOfBitsInChromosome);
            double x2       = BinaryUtils.BinaryToDecimalRepresentation(bestIndividuals[1].BinaryRepresentation, inputDataEntity.DataRange, NumberOfBitsInChromosome);
            double extremum = Function.Compute(x1, x2);

            stopwatch.Stop();
            return(new OptimizationResult
            {
                ExtremeValue = extremum,
                X1 = x1,
                X2 = x2,
                BestFromPreviousEpochs = bestOfEachEpoch,
                MeanFromPreviousEpochs = means,
                StandardDeviation = standardDeviation,
                TimeElapsed = stopwatch.ElapsedMilliseconds
            });
        }