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 | }
|
---|