public GeneSequence Clone() { var geneSequence = new GeneSequence(Genes.ToArray(), Strategy) { Fitness = Fitness }; if (_stringGenes !=null) { geneSequence._stringGenes = _stringGenes; } return geneSequence; }
private void PrintBest(int generation, GeneSequence geneSequence) { DisplayGenes(1 + generation, geneSequence.Fitness.Value, geneSequence.GetStringGenes(), geneSequence.Strategy.Description); }
private static int FitnessSort(GeneSequence x, GeneSequence y) { int result = x.Fitness.Value.CompareTo(y.Fitness.Value); if (result == 0) { result = y.Generation.CompareTo(x.Generation); } return result; }
public GeneSequence GetBestGenetically(int numberOfGenesToUse, string possibleGenes, Func<string, FitnessResult> calcFitness) { int seed = _randomSeed != 0 ? _randomSeed : (int)DateTime.Now.Ticks; Console.WriteLine("using random seed: " + seed); _random = new Random(seed); var popAlpha = new List<GeneSequence>(GaPopsize); var popBeta = new List<GeneSequence>(GaPopsize); Func<char> getRandomGene = () => possibleGenes[_random.Next(possibleGenes.Length)]; InitPopulation(UseHillClimbing ? NumberOfGenesInUnitOfMeaning : numberOfGenesToUse, popAlpha, popBeta, getRandomGene); var population = popAlpha; var spare = popBeta; var previousBests = new List<GeneSequence> { population.First() }; previousBests[0].Fitness = calcFitness(previousBests[0].GetStringGenes()); int generation = 0; var generationsBetweenImprovments = Enumerable.Repeat(_gaMaxGenerationsWithoutImprovement, 20).ToList(); if (UseHillClimbing) { int failureToImproveCount = 0; var bestEver = new GeneSequence(new char[] { }, null) { Fitness = new FitnessResult{Value = UInt32.MaxValue} }; for (int i = NumberOfGenesInUnitOfMeaning; i < numberOfGenesToUse - 1; i += NumberOfGenesInUnitOfMeaning) { GetBestGenetically(OnlyPermuteNewGenesWhileHillClimbing ? i - NumberOfGenesInUnitOfMeaning : 0, i, getRandomGene, previousBests, population, spare, calcFitness, generationsBetweenImprovments, ref generation); var incrementalBest = previousBests.First(); if (incrementalBest.Fitness.Value < bestEver.Fitness.Value) { bestEver = incrementalBest.Clone(); failureToImproveCount = 0; } else { failureToImproveCount++; if (incrementalBest.Fitness.Value > bestEver.Fitness.Value * 1.05m || failureToImproveCount >= 5) { Console.WriteLine("Fitness appears to be getting worse, returning best result: fitness " + bestEver.Fitness.Value + " in generation " + bestEver.Generation); return bestEver; } } var parents = previousBests.ToList(); population.Clear(); spare.Clear(); previousBests.Clear(); for (int j = 0; j < GaPopsize; j++) { var random = _randomStrategy.Generate(null, NumberOfGenesInUnitOfMeaning, getRandomGene, NumberOfGenesInUnitOfMeaning, _slidingMutationRate, _random.Next, 0); var newChild = new GeneSequence(parents[j % parents.Count].Genes.Concat(random.Genes).ToArray(), _mutationStrategy) { Fitness = GeneSequence.DefaultFitness }; population.Add(newChild); spare.Add(newChild.Clone()); } previousBests.AddRange(population.Select(x => { x.Fitness = calcFitness(x.GetStringGenes()); return x; }).Where(x => x.Fitness.Value < incrementalBest.Fitness.Value)); if (previousBests.Count < 100) { previousBests.AddRange(population.OrderBy(x => x.Fitness.Value).Take(100 - previousBests.Count)); } SortByFitness(previousBests); int count = 1 + (i / NumberOfGenesInUnitOfMeaning); Console.WriteLine("> " + count); if (previousBests[0].Fitness.Value < incrementalBest.Fitness.Value) { PrintBest(generation, previousBests[0]); } } return bestEver; } GetBestGenetically(0, numberOfGenesToUse, getRandomGene, previousBests, population, spare, calcFitness, generationsBetweenImprovments, ref generation); var best = previousBests.First(); return best; }