-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGeneticAlgorithm.cs
145 lines (123 loc) · 4.62 KB
/
GeneticAlgorithm.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.Data;
using System.Xml.Serialization;
using System.IO;
namespace Georgia
{
[Serializable]
public abstract class GeneticAlgorithm
{
[XmlElement]
public int CurrentGeneration { get; set; }
[XmlElement]
public ReproductionFacade Reproduction { get; set; }
[XmlElement]
public SelectionFacade Selection { get; set; }
[XmlElement]
protected List<IChromosome> Population { get; set; }
[XmlElement]
protected int PopulationSize { get; set; }
[XmlElement]
public double CrossoverRate { get; set; }
public GeneticAlgorithm()
{
Population = new List<IChromosome>();
CurrentGeneration = 1;
}
public GeneticAlgorithm(int pSize)
{
CurrentGeneration = 1;
Population = new List<IChromosome>(pSize);
PopulationSize = pSize;
}
public GeneticAlgorithm(int pSize, double cRate)
: this(pSize)
{
CrossoverRate = cRate;
}
public GeneticAlgorithm(int pSize, double cRate, SelectionFacade sf, ReproductionFacade rf)
: this(pSize, cRate)
{
Selection = sf;
Reproduction = rf;
}
public abstract void InitPopulation();
/// <summary>
/// Process a single generation of the population
/// </summary>
public void DoGeneration()
{
Trace.WriteLine("BEGIN: GeneticAlgorithm.DoGeneration():");
Trace.Indent();
List<IChromosome> newPopulation = new List<IChromosome>();
int matingPoolSize = (int)Math.Floor(PopulationSize * CrossoverRate);
Trace.WriteLine(String.Format("matingPoolSize = {0}", matingPoolSize));
for (int i = 0; i < matingPoolSize; i++)
{
// Select and remove the parents from the gene pool
IList<IChromosome> parents = Selection.Select(Population, 2);
Trace.WriteLine("Selected two parents for crossover.");
Trace.WriteLine(String.Format("parents[0] = {0}", parents[0]));
Trace.WriteLine(String.Format("parents[1] = {0}", parents[1]));
// Reproduce and add children to gene pool
IList<IChromosome> children = Reproduction.Reproduce(parents);
Trace.WriteLine("Children:");
foreach (IChromosome child in children)
{
Trace.WriteLine(String.Format("{0}", child));
}
Trace.WriteLine("Reproduction complete.");
newPopulation.Add(children[0]);
}
if (newPopulation.Count < PopulationSize)
{
Trace.WriteLine(String.Format("Re-using {0} individuals from previous generation.",
PopulationSize - newPopulation.Count));
Population.Sort();
// Why sort in ascending order?! :(
int carry = 1;
while (newPopulation.Count < PopulationSize)
{
newPopulation.Add(Population[Population.Count - carry]);
carry++;
}
}
else if (newPopulation.Count > PopulationSize)
{
Console.WriteLine("Great, Scott! How did we get here?");
Console.WriteLine("In GeneticAlgorithm.DoGeneration(): newPopulation.Count > populationSize");
Environment.Exit(-1);
}
Population = newPopulation;
UpdateFitnessAll();
Trace.Unindent();
Trace.WriteLine("END: GeneticAlgorithm.DoGeneration()");
CurrentGeneration++;
}
public void UpdateFitnessAll()
{
Selection.UpdateFitnessAll(Population);
}
public double GetAverageFitness()
{
return Population.Average(c => { if (c.Fitness.HasValue) { return c.Fitness.Value; } else { return 0; } });
}
public IChromosome GetMostFit()
{
return Population.Max();
}
public IChromosome GetLeastFit()
{
return Population.Min();
}
public List<IChromosome> GetPopulation()
{
return this.Population;
}
}
}