1  using System;
   2  using System.Collections.Generic;
   3  
   4  class Population {
   5  
   6      public Population() {
   7          populationDistributor_ = new PopulationDistributor(this);
   8          // (Commented out code is for single-threaded implementation.)
   9          //for(int k = 0; k<parms_.populationSize_; k++) population_.Add(new Genome());
  10          populationDistributor_.set(new CreationWork(this));
  11          populationDistributor_.doWork();
  12          population_ = populationDistributor_.transferChildren();
  13          numberOfGenomes_ = population_.Count;
  14          process();
  15          }
  16  
  17      public bool containsSolution() {return population_[0].getFitness()==0;}
  18  
  19      public void breed() {
  20          // (Commented out code is for single-threaded implementation.)
  21          //List<Genome> children = new List<Genome>();
  22  
  23          // Mutation:  Mutate the most fit genomes
  24          //for (int k = 0; k < parms_.mutationSize_; k++) children.Add(new Genome(population_[k]));
  25          populationDistributor_.set(new MutationWork(this));
  26          populationDistributor_.doWork();
  27          List<Genome> children = populationDistributor_.transferChildren();
  28  
  29          // Crossover:  Mate the most fit genomes
  30          //for (int k = 0; k < crossoverSize; k++) children.Add(new Genome(population_[k], population_[k + 1]));
  31  
  32          populationDistributor_.set(new CrossoverWork(this));
  33          populationDistributor_.doWork();
  34          children.AddRange(populationDistributor_.transferChildren());
  35  
  36          // Kill least fit reproductionSize_ individuals from previous generation:
  37          population_.RemoveRange((int)(population_.Count - parms_.reproductionSize_), parms_.reproductionSize_);
  38  
  39          population_.AddRange(children);
  40          numberOfGenomes_ += children.Count;
  41          process();
  42          }
  43  
  44      // The following three functions execute in worker threads:
  45      public List<Genome> create(int min, int max1) {
  46          List<Genome> children = new List<Genome>();
  47          for (int k = min; k < max1; k++) children.Add(new Genome());
  48          return children;
  49          }
  50  
  51      public List<Genome> mutate(int min, int max1) {
  52          List<Genome> children = new List<Genome>();
  53          for (int k = min; k < max1; k++) children.Add(new Genome(population_[k]));
  54          return children;
  55          }
  56  
  57      public List<Genome> crossover(int min, int max1) {
  58          List<Genome> children = new List<Genome>();
  59          for (int k = min; k < max1; k++) children.Add(new Genome(population_[k], population_[k + 1]));
  60          return children;
  61          }
  62  
  63      public override string ToString() {
  64          return "\t" + generation_ + "\t" + population_[0].getFitness() 
  65              + "\t" + String.Format("{0:0.0}", meanFitness()) 
  66              + "\t" + population_[population_.Count-1].getFitness() 
  67              + "\t" + String.Format("{0:0.##}", 100*inbreeding_/(float)population_.Count);
  68          }
  69  
  70      private float meanFitness() {
  71          uint fitnessSum = 0;
  72          population_.ForEach(delegate(Genome genome) { fitnessSum += genome.getFitness(); });
  73          return fitnessSum / (float)population_.Count;
  74          }
  75  
  76      private void process() {
  77          generation_++;
  78          population_.Sort();
  79  
  80          // Compute inbreeding:
  81  
  82          // Sort exactly to find duplicates:
  83          List<Genome> populationSorted = new List<Genome>();
  84          populationSorted.AddRange(population_);
  85          populationSorted.Sort(new ExactCompareGenome());
  86  
  87          inbreeding_ = 0;
  88          for(int k = 0; k < populationSorted.Count-1; k++) 
  89              if(populationSorted[k].ExactCompareTo(populationSorted[k+1])==0) inbreeding_++;
  90          maximumInbreeding_ = Math.Max(maximumInbreeding_, inbreeding_);
  91  
  92          // Blurt:
  93          if(!Program.multipleMode_) Console.WriteLine(this);
  94          if(containsSolution()) {
  95              if (Program.multipleMode_) {
  96                  double timer = timer_.getSeconds();
  97                  double numberOfGenomeBits = Genome.getNumberOfBits();
  98                  Console.WriteLine(String.Format("{0,4:0}{1,10:0.000}{2,10:###,###,##0}{3,8:###,##0}{4,11:0.0}{5,9:###,##0}"
  99                      + "{6,10:0.0}{7,11:0.0}{8,13:0.0}{9,9:###,##0}{10,11:0.000}",
 100                      Genome.N_, timer, numberOfGenomes_, generation_, meanFitness(), population_[population_.Count-1].getFitness(),
 101                      100 * inbreeding_/(float)population_.Count, 100 * maximumInbreeding_/(float)population_.Count,
 102                      1000 * timer / numberOfGenomeBits, numberOfGenomes_ / numberOfGenomeBits, generation_ / numberOfGenomeBits
 103                      ));
 104                  }
 105              else Console.Write("\n" + population_[0] 
 106                  + String.Format("\nNumber of genomes created:  {0:###,###,###,##0}\n", numberOfGenomes_));
 107              }
 108          }
 109  
 110      public void terminate() {populationDistributor_.requestWorkerTermination();}
 111  
 112      public uint getNumberOfGenerations() {return generation_;}
 113  
 114      // Statistics:
 115      private Timer timer_ = new Timer();
 116      private uint generation_ = 0;
 117      private int numberOfGenomes_;
 118      private uint inbreeding_;
 119      private uint maximumInbreeding_ = 0;
 120  
 121      private List<Genome> population_;
 122      public PopulationDistributor populationDistributor_;
 123  
 124      public static readonly GeneticAlgorithmParameters parms_ = new GeneticAlgorithmParameters(3000, 0.8f, 0.6f);
 125  }