public CandidateSolutionItem(int capacity, ItemList list, IRandomizer randomizer)
        {
            _randomizer   = randomizer;
            CandidateItem = list;
            Capacity      = capacity;

            Genes = new List <bool>(list.Count);

            for (int i = 0; i < list.Count; i++)
            {
                Genes.Add(randomizer.GetDoubleFromZeroToOne() >= 0.5);
            }
            Repair();
            CalcFitness();
        }
        public T Run(TInput data)
        {
            CurrentGeneration = new List <ICandidateSolution <T> >(PopulationSize);
            for (int i = 0; i < PopulationSize; i++)
            {
                CurrentGeneration.Add(_generator.GenerateCandidate(data));
            }
            ICandidateSolution <T> bestSolution = null;
            int bestFitness = int.MinValue;

            var bestGen = 0;
            var gen     = 1;

            while (true)
            {
                var bestGenFitness = 0;
                var totalFitness   = 0;
                ICandidateSolution <T> bestSolutionThisGen = null;
                foreach (var candidateSolution in CurrentGeneration)
                {
                    candidateSolution.Repair();
                    totalFitness += candidateSolution.Fitness;
                    if (candidateSolution.Fitness > bestGenFitness)
                    {
                        bestGenFitness      = candidateSolution.Fitness;
                        bestSolutionThisGen = candidateSolution;
                    }
                }

                if (totalFitness > bestFitness)
                {
                    bestFitness  = totalFitness;
                    bestSolution = bestSolutionThisGen;
                    bestGen      = gen;
                }
                else
                {
                    if ((gen - bestGen) > MaxGenerationsWithNoChanges)
                    {
                        break;
                    }
                }
                var nextGen = new List <ICandidateSolution <T> >();
                while (nextGen.Count < PopulationSize)
                {
                    var parent1 = RouletteWheelSelectCandidate(totalFitness).CloneObject();
                    var parent2 = RouletteWheelSelectCandidate(totalFitness).CloneObject();
                    if (_randomizer.GetDoubleFromZeroToOne() < CrossOverRate)
                    {
                        var(child1, child2) = _generator.CrossOver(parent1, parent2, data);
                        parent1             = child1;
                        parent2             = child2;
                    }

                    if (_randomizer.GetDoubleFromZeroToOne() < MutationRate)
                    {
                        parent1 = _generator.Mutate(parent1, data, MutationRate);
                    }

                    if (_randomizer.GetDoubleFromZeroToOne() < MutationRate)
                    {
                        parent2 = _generator.Mutate(parent2, data, MutationRate);
                    }

                    nextGen.Add(parent1);
                    nextGen.Add(parent2);
                }

                gen++;
            }

            return(bestSolution?.CandidateItem);
        }