[11514] | 1 | using System;
|
---|
| 2 | using System.Linq;
|
---|
| 3 |
|
---|
| 4 | public class OSGARastriginScript : HeuristicLab.Scripting.CSharpScriptBase {
|
---|
| 5 | public override void Main() {
|
---|
| 6 | int N = vars.N.Value;
|
---|
| 7 | double minX = vars.minX.Value;
|
---|
| 8 | double maxX = vars.maxX.Value;
|
---|
| 9 | int seed = vars.seed.Value;
|
---|
| 10 | var rand = new Random(seed);
|
---|
| 11 |
|
---|
| 12 | var result = OSGA(rand, popSize: 1000, iterations: 5000, maxSelPres: 1000, mutationRate: 0.1,
|
---|
| 13 | obj: Rastrigin,
|
---|
| 14 | // x ~(i.i.d) U(0,1) * 10.24 - 5.12
|
---|
| 15 | creator: () => Enumerable.Range(1, N).Select(_ => rand.NextDouble() * (maxX - minX) + minX).ToArray(),
|
---|
| 16 | // random parent selection
|
---|
| 17 | selector: (f) => rand.Next(f.Length),
|
---|
| 18 | // single point crossover
|
---|
| 19 | crossover: (p0, p1, cand) => {
|
---|
| 20 | int cut = rand.Next(cand.Length);
|
---|
| 21 | Array.Copy(p0, cand, cut);
|
---|
| 22 | Array.Copy(p1, cut, cand, cut, cand.Length - cut);
|
---|
| 23 | },
|
---|
| 24 | // single point manipulation
|
---|
| 25 | manipulator: (p) => p[rand.Next(N)] = rand.NextDouble() * (maxX - minX) + minX,
|
---|
| 26 | output: true
|
---|
| 27 | );
|
---|
| 28 |
|
---|
| 29 | double bestFit = result.Item2;
|
---|
| 30 | vars.bestFitness = bestFit;
|
---|
| 31 | Console.WriteLine("best fitness: {0}", bestFit);
|
---|
| 32 | }
|
---|
| 33 |
|
---|
| 34 | private double Rastrigin(double[] x) {
|
---|
| 35 | return 10.0 * x.Length + x.Sum(xi => xi * xi - 10.0 * Math.Cos(2.0 * Math.PI * xi));
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | private Tuple<T, double> OSGA<T>(Random rand, int popSize, int iterations, double maxSelPres, double mutationRate, Func<T, double> obj,
|
---|
| 39 | Func<T> creator, Func<double[], int> selector, Action<T, T, T> crossover, Action<T> manipulator,
|
---|
| 40 | bool output = false)
|
---|
| 41 | where T : ICloneable {
|
---|
| 42 | // generate random pop
|
---|
| 43 | T[] pop = Enumerable.Range(0, popSize).Select(_ => creator()).ToArray();
|
---|
| 44 | // evaluate initial pop
|
---|
| 45 | double[] fit = pop.Select(p => obj(p)).ToArray();
|
---|
| 46 |
|
---|
| 47 | // arrays for next pop (clone current pop because solutions are reused)
|
---|
| 48 | T[] popNew = pop.Select(pi => (T)pi.Clone()).ToArray();
|
---|
| 49 | double[] fitNew = new double[popSize];
|
---|
| 50 |
|
---|
| 51 | var bestSolution = (T)pop.First().Clone(); // take a random solution (don't care)
|
---|
| 52 | double bestFit = fit.First();
|
---|
| 53 |
|
---|
| 54 | // run generations
|
---|
| 55 | double curSelPres = 0;
|
---|
| 56 | for (int g = 0; g < iterations && curSelPres < maxSelPres; g++) {
|
---|
| 57 | // keep the first element as elite
|
---|
| 58 | int i = 1;
|
---|
| 59 | int genEvals = 0;
|
---|
| 60 | do {
|
---|
| 61 | var p1Idx = selector(fit);
|
---|
| 62 | var p2Idx = selector(fit);
|
---|
| 63 |
|
---|
| 64 | var p1 = pop[p1Idx];
|
---|
| 65 | var p2 = pop[p2Idx];
|
---|
| 66 | var f1 = fit[p1Idx];
|
---|
| 67 | var f2 = fit[p2Idx];
|
---|
| 68 |
|
---|
| 69 | // generate candidate solution (reuse old solutions)
|
---|
| 70 | crossover(p1, p2, popNew[i]);
|
---|
| 71 | // optional mutation
|
---|
| 72 | if (rand.NextDouble() < mutationRate) {
|
---|
| 73 | manipulator(popNew[i]);
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | double f = obj(popNew[i]);
|
---|
| 77 | genEvals++;
|
---|
| 78 | // if child is better than best (strict offspring selection)
|
---|
| 79 | if (f < Math.Min(f1, f2)) {
|
---|
| 80 | // update best fitness
|
---|
| 81 | if (f < bestFit) {
|
---|
| 82 | bestFit = f;
|
---|
| 83 | bestSolution = (T)popNew[i].Clone(); // overall best
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | // keep
|
---|
| 87 | fitNew[i] = f;
|
---|
| 88 | i++;
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | curSelPres = genEvals / (double)popSize;
|
---|
| 92 | } while (i < popNew.Length && curSelPres < maxSelPres);
|
---|
| 93 |
|
---|
| 94 | Console.WriteLine("generation {0} obj {1:0.000} sel. pres. {2:###.0}", g, bestFit, curSelPres);
|
---|
| 95 |
|
---|
| 96 | // swap
|
---|
| 97 | var tmpPop = pop;
|
---|
| 98 | var tmpFit = fit;
|
---|
| 99 | pop = popNew;
|
---|
| 100 | fit = fitNew;
|
---|
| 101 | popNew = tmpPop;
|
---|
| 102 | fitNew = tmpFit;
|
---|
| 103 |
|
---|
| 104 | // keep elite
|
---|
| 105 | popNew[0] = (T)bestSolution.Clone();
|
---|
| 106 | fitNew[0] = bestFit;
|
---|
| 107 | }
|
---|
| 108 |
|
---|
| 109 | return Tuple.Create(bestSolution, bestFit);
|
---|
| 110 | }
|
---|
| 111 | } |
---|