コード例 #1
0
        public IEnumerable <int> GetMatchedTiles()
        {
            // Cut tiles from chromosome
            var cutTiles = E2Chromosome.CutTiles(this);

            // Create a copy of the real tiles for us to work with
            var comp      = Tiles.ToList();
            var tileIndex = 0;

            foreach (var tile in cutTiles)
            {
                // Walk our own list of all the real tiles...
                for (var n = 0; n < comp.Count; n++)
                {
                    if (comp[n].Matches(tile))
                    {
                        yield return(tileIndex);

                        comp.RemoveAt(n);
                        break;
                    }
                }

                tileIndex++;
            }
        }
コード例 #2
0
 public static IEnumerable <string> CutTiles(E2Chromosome chromosome)
 {
     // generate set of strings representing the tiles cut from the candidate solution
     for (var y = 0; y < E2Chromosome.Height; y++)
     {
         for (var x = 0; x < E2Chromosome.Width; x++)
         {
             int root = y * (E2Chromosome.Width * 2 + 1) + x;
             yield return
                 ($"{(char) chromosome.GetGene(root + E2Chromosome.Width).Value}{(char) chromosome.GetGene(root).Value}{(char) chromosome.GetGene(root + E2Chromosome.Width + 1).Value}{(char) chromosome.GetGene(root + (E2Chromosome.Width * 2 + 1)).Value}");
         }
     }
 }
コード例 #3
0
        public (int, double) GetMatchedTileScore()
        {
            // Cut tiles from chromosome
            var cutTiles = E2Chromosome.CutTiles(this).ToList();

            // Create a copy of the real tiles for us to work with
            var comp        = Tiles.ToList();
            var score       = 0.0;
            var tileMatches = 0;

            foreach (var tile in cutTiles)
            {
                // Walk our own list of all the real tiles...
                for (var n = 0; n < comp.Count; n++)
                {
                    if (comp[n].Matches(tile))
                    {
                        score++;
                        tileMatches++;
                        comp.RemoveAt(n);
                        break;
                    }
                }
            }

            // Walk the list again and look for partial matches
            new int[] { 4, 3 }.Each(threshold =>
            {
                foreach (var tile in cutTiles)
                {
                    for (var n = 0; n < comp.Count; n++)
                    {
                        if (comp[n].SymbolMatches(tile) == threshold)
                        {
                            score += ((double)threshold / 24.0);
                            comp.RemoveAt(n);
                            break;
                        }
                    }
                }
            });
            return(tileMatches, score);
        }
コード例 #4
0
        public double Evaluate(IChromosome chromosome)
        {
            // Cast our chromosome to our own type
            E2Chromosome c = (E2Chromosome)chromosome;

            // Cut the chromosome into tiles, then compare those to the known set... How many match?
            var matchScore = c.GetMatchedTileScore();

            c.Matches = matchScore.Item1;
            if (c.Matches == 0)
            {
                return(0);                // No matches is a zero fit :(
            }
            // Fitness (as a 0..1 number) is the completeness of the solution
            double fitness = (double)matchScore.Item2 / (double)E2Chromosome.TileCount;

            // How valid is this solution?
            // We could have a great number of matches, but we might have built this from an invalid symbol
            // set, i.e. too many As, not enough Bs

            // Sort the symbols used in this chromosome and compare item by item with the know sorted set
            // validity is the count of matches
            string solSymbols = c.ToSortedSymbolList();
            int    validity   = Enumerable.Range(0, solSymbols.Length - 1)
                                .Count(n => solSymbols[n] == E2Chromosome.SymbolsList[n]);

            // If we have some invalidity then divide fitness significantly
            var diff = E2Chromosome.TileCount - validity;

            if (diff > 0)
            {
                fitness /= diff;
            }

            // Record fitness
            c.FitnessValue = fitness;
            return(fitness);
        }
コード例 #5
0
ファイル: Program.cs プロジェクト: tonycoupland/E2GA
        static void Main(string[] args)
        {
//            var chromosome = new E2Chromosome(5, 5);
//            Console.WriteLine(chromosome.ToString());
//
//            int n = 0;
//            foreach (var cutTile in E2Chromosome.CutTiles(chromosome))
//            {
//                Console.Write(cutTile + " ");
//                if ( ++n % 5 == 0)Console.WriteLine();
//            }
//
//            Console.ReadLine();

            // Setup problem
            E2Chromosome.Width     = 5;
            E2Chromosome.Height    = 5;
            E2Chromosome.TileCount = E2Chromosome.Width * E2Chromosome.Height;
            E2Chromosome.Tiles     = new string[]
            {
                "ABDC", "DEBF", "BGGE", "GCFF", "FEED",
                "CCBF", "BFCC", "CEGG", "GFAH", "ADDC",
                "FFAC", "ACHE", "HGBC", "BHAF", "ACHG",
                "ECFC", "FEDB", "DCGB", "GFCA", "CGFD",
                "ECBE", "BBGC", "GBCH", "CAHD", "HDCE"
            }.Select(t => new Tile(t));

            // Create chromosome and fitness
            var chromosome = new E2Chromosome();
            var fitness    = new E2Fitness();

            // This operators are classic genetic algorithm operators that lead to a good solution on TSP,
            // but you can try others combinations and see what result you get.
            var crossover  = new GeneticSharp.Domain.Crossovers.OnePointCrossover();
            var mutation   = new GeneticSharp.Domain.Mutations.PartialShuffleMutation();
            var selection  = new GeneticSharp.Domain.Selections.RouletteWheelSelection();
            var population = new GeneticSharp.Domain.Populations.Population(5000, 10000, chromosome);

            ga = new GeneticAlgorithm(population, fitness, selection, crossover, mutation);
            ga.MutationProbability = 0.1f;
            ga.Termination         = new GeneticSharp.Domain.Terminations.FitnessThresholdTermination(1.0);

            // The fitness evaluation of whole population will be running on parallel.
            ga.TaskExecutor = new ParallelTaskExecutor
            {
                MinThreads = 100,
                MaxThreads = 200
            };

            // Every time a generation ends, we log the best solution.
            int      bestMatches = 0;
            DateTime startTime   = DateTime.Now;

            ga.GenerationRan += delegate
            {
                var best    = ((E2Chromosome)ga.BestChromosome);
                var Matches = best.Matches;
                var Fitness = best.FitnessValue;

                if (Matches > bestMatches || ga.GenerationsNumber % 250 == 0)
                {
                    Console.WriteLine(
                        $"{DateTime.Now.Subtract(startTime).TotalSeconds}s Generation: {ga.GenerationsNumber} - Matches: {Matches} - Fitness: {Fitness}");

                    if (Matches > bestMatches)
                    {
                        Console.WriteLine(((E2Chromosome)ga.BestChromosome).ToStringIncludingTileMatches(true));
                    }

                    bestMatches = Matches;
                }
            };

            // Starts the genetic algorithm in a separate thread.
            gaThread = new Thread(() => ga.Start());
            gaThread.Start();


            Console.ReadLine();


            // When the script is destroyed we stop the genetic algorithm and abort its thread too.
            ga.Stop();
            gaThread.Abort();
        }