Exemplo n.º 1
0
        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();
        }