public static List <TGene> Tournament(CreateDelegate fnGenerateParent, CrossoverDelegate fnCrossover, CompeteDelegate fnCompete, TournamentDisplayDelegate fnDisplay, SortKeyDelegate fnSortKey, int numParents = 10, int maxGenerations = 100) { var pool = Enumerable.Range(0, 1 + numParents * numParents) .Select(x => new Tuple <List <TGene>, int[]>(fnGenerateParent(), new[] { 0, 0, 0 })).ToList(); var best = pool[0].Item1; var bestScore = pool[0].Item2; int GetSortKey(Tuple <List <TGene>, int[]> x) => fnSortKey(x.Item1, x.Item2[(int)CompetitionResult.Win], x.Item2[(int)CompetitionResult.Tie], x.Item2[(int)CompetitionResult.Loss]); for (var generation = 0; generation < maxGenerations; generation++) { for (var i = 0; i < pool.Count; i++) { for (var j = 0; j < pool.Count; j++) { if (i == j) { continue; } var playerA = pool[i].Item1; var scoreA = pool[i].Item2; var playerB = pool[j].Item1; var scoreB = pool[j].Item2; var result = (int)fnCompete(playerA, playerB); scoreA[result]++; scoreB[2 - result]++; } } pool = pool.OrderByDescending(GetSortKey).ToList(); if (GetSortKey(pool[0]) > GetSortKey(new Tuple <List <TGene>, int[]>(best, bestScore))) { best = pool[0].Item1; bestScore = pool[0].Item2; fnDisplay(best, bestScore[(int)CompetitionResult.Win], bestScore[(int)CompetitionResult.Tie], bestScore[(int)CompetitionResult.Loss], generation); } var parents = Enumerable.Range(0, numParents).Select(i => pool[i].Item1).ToList(); pool = (from i in Enumerable.Range(0, parents.Count) from j in Enumerable.Range(0, parents.Count) where i != j select new Tuple <List <TGene>, int[]>(fnCrossover(parents[i], parents[j]), new[] { 0, 0, 0 })) .ToList(); pool.AddRange(parents.Select(parent => new Tuple <List <TGene>, int[]>(parent, new[] { 0, 0, 0 }))); pool.Add(new Tuple <List <TGene>, int[]>(fnGenerateParent(), new[] { 0, 0, 0 })); } return(best); }
private static Chromosome <TGene, TFitness> Crossover(IReadOnlyList <TGene> parentGenes, int index, IList <Chromosome <TGene, TFitness> > parents, GetFitnessDelegate getFitness, CrossoverDelegate crossover, MutateChromosomeDelegate mutate, GenerateParentDelegate generateParent) { var donorIndex = Rand.Random.Next(0, parents.Count); if (donorIndex == index) { donorIndex = (donorIndex + 1) % parents.Count; } var childGenes = crossover(parentGenes, parents[donorIndex].Genes); if (childGenes == null) { // parent and donor are indistinguishable parents[donorIndex] = generateParent(); return(mutate(parents[index])); } var fitness = getFitness(childGenes); return(new Chromosome <TGene, TFitness>(childGenes, fitness, Strategy.Crossover)); }
public static Chromosome <TGene, TFitness> GetBest(GetFitnessDelegate getFitness, int targetLen, TFitness optimalFitness, IReadOnlyList <TGene> geneSet, DisplayDelegate display, MutateGeneDelegate customMutate = null, CreateDelegate customCreate = null, int?maxAge = null, int poolSize = 1, CrossoverDelegate crossover = null, int?maxSeconds = null) { Chromosome <TGene, TFitness> FnMutate(Chromosome <TGene, TFitness> parent) => customMutate == null ? Mutate(parent, geneSet, getFitness) : MutateCustom(parent, customMutate, getFitness); Chromosome <TGene, TFitness> FnGenerateParent() { if (customCreate == null) { return(GenerateParent(targetLen, geneSet, getFitness)); } var genes = customCreate(); return(new Chromosome <TGene, TFitness>(genes, getFitness(genes), Strategy.Create)); } var strategyLookup = new Dictionary <Strategy, StrategyDelegate> { { Strategy.Create, (parentGenes, index, parents) => FnGenerateParent() }, { Strategy.Mutate, (parentGenes, index, parents) => FnMutate(parentGenes) }, { Strategy.Crossover, (parentGenes, index, parents) => Crossover(parentGenes.Genes, index, parents, getFitness, crossover, FnMutate, FnGenerateParent) } }; var usedStrategies = new List <StrategyDelegate> { strategyLookup[Strategy.Mutate] }; if (crossover != null) { usedStrategies.Add(strategyLookup[Strategy.Crossover]); } Chromosome <TGene, TFitness> FnNewChild(Chromosome <TGene, TFitness> parent, int index, List <Chromosome <TGene, TFitness> > parents) => crossover != null ? Rand.SelectItem(usedStrategies)(parent, index, parents) : FnMutate(parent); try { foreach (var improvement in GetImprovement(FnNewChild, FnGenerateParent, maxAge, poolSize, maxSeconds)) { display(improvement); var f = strategyLookup[improvement.Strategy]; usedStrategies.Add(f); if (optimalFitness.CompareTo(improvement.Fitness) <= 0) { return(improvement); } } } catch (SearchTimeoutException exception) { display(exception.Improvement); return(exception.Improvement); } throw new UnauthorizedAccessException(); }