public void Train(int iterations = 1) { while (iterations-- > 0) { List<Species> parents = Population; Population = new List<Species>(PopulationSize); Population.Add(parents.First()); //Tournament Selection while (Population.Count < PopulationSize) { Species[] pair = new Species[2]; for (int i = 0; i < 2; i++) { int[] randomIndices = new int[10]; for (int j = 0; j < randomIndices.Length; j++) randomIndices[j] = int.MaxValue; for (int j = 0; j < randomIndices.Length; j++) { int r = R.NextNot(parents.Count, randomIndices); randomIndices[j] = r; } List<Species> tournament = new List<Species>(randomIndices.Length); for (int j = 0; j < randomIndices.Length; j++) tournament.Add(parents[randomIndices[j]]); pair[i] = tournament.OrderByDescending(s => s.Fitness).First(); } //now have two parents. Species sp = ~(pair[0] ^ pair[1]); sp.Clamp(); Population.Add(sp); } List<Task> tasks = new List<Task>(); foreach (Species s in Population) { int pidd = pid++; Task t = new Task(() => { s.Fitness = FitnessFunction(s.Genome, pidd, true); }); tasks.Add(t); t.Start(); } tasks.ForEach(t => t.Wait()); Population.Sort((s, t) => t.Fitness.CompareTo(s.Fitness)); /* Console.Clear(); Console.WriteLine(BestIndividual.Fitness);*/ FitnessFunction(BestIndividual.Genome, -iterations, false); } }
public static Species operator ^(Species a, Species b) { if (a.Genome.Length != b.Genome.Length) throw new ArgumentException("Can't crossover species of different genome length"); Species result = new Species(a); int cut = R.Next(a.Genome.Length + 1); for (int i = cut; i < a.Genome.Length; i++) result.Genome[i] = b.Genome[i]; return result; }
public static Species operator ~(Species a) { Species result = new Species(a); const double scale = 10; for (int i = 0; i < a.Genome.Length; i++) if (R.NextDouble() < 0.4) a.Genome[i] = Math.Abs(a.Genome[i] + R.NextDouble() * 2 * scale - scale); return result; }
public static Species operator -(Species a) { Species result = new Species(a); for (int i = 0; i < a.Genome.Length; i++) result.Genome[i] = -a.Genome[i]; return result; }
//Vector operations: public static Species operator +(Species a, Species b) { if (a.Genome.Length != b.Genome.Length) throw new ArgumentException("Can't vector add species of different genome length"); Species result = new Species(a); for (int i = 0; i < a.Genome.Length; i++) result.Genome[i] += b.Genome[i]; return result; }
public static Species operator *(double c, Species a) { Species result = new Species(a); for (int i = 0; i < a.Genome.Length; i++) result.Genome[i] *= c; return result; }
public Species(Species s) { Genome = new double[s.Genome.Length]; for (int i = 0; i < s.Genome.Length; i++) Genome[i] = s.Genome[i]; }
public void Train(int iterations = 1) { const double beta = 0.5; const double crossoverRate = 0.5; while (iterations-- > 0) { List<Species> newPop = new List<Species>(PopulationSize); List<Task> tasks = new List<Task>(); for (int i = 0; i < PopulationSize; i++) { int ppid = pid++; int actuali = i; Task t = new Task(() => { Species xnew; Species x; lock (Population) { x = Population[actuali]; int i1 = R.NextNot(PopulationSize, actuali); int i2 = R.NextNot(PopulationSize, actuali, i1); int i3 = R.NextNot(PopulationSize, actuali, i1, i2); Species x1 = Population[i1]; Species x2 = Population[i2]; Species x3 = Population[i3]; Species u = x1 + beta * (x2 - x3); u.Clamp(); xnew = new Species(x); for (int j = 0; j < GenomeLength; j++) if (R.NextDouble() < crossoverRate) xnew.Genome[j] = u.Genome[j]; } xnew.Fitness = FitnessFunction(xnew.Genome, ppid, true); lock (newPop) { if (x.Fitness < xnew.Fitness) newPop.Add(xnew); else newPop.Add(x); } }); tasks.Add(t); t.Start(); } tasks.ForEach(t => t.Wait()); Population = newPop; Population.Sort((x, y) => y.Fitness.CompareTo(x.Fitness)); Console.Clear(); Console.WriteLine(BestIndividual.Fitness); FitnessFunction(BestIndividual.Genome, -iterations, false); } }