PageRenderTime 70ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/Code/GeneticEnginePrototype/GeneticEngine/GeneticEngine.cs

https://github.com/thepowersgang/cits3200
C# | 321 lines | 207 code | 36 blank | 78 comment | 25 complexity | 70c19dec14790c4120498a6b1a7ba8b6 MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using GeneticAlgorithm.Plugin;
  7. using GeneticAlgorithm.Plugin.Generic;
  8. namespace GeneticAlgorithm
  9. {
  10. /// <summary>
  11. /// Runs a genetic algorithm using the supplied plug-ins.
  12. /// </summary>
  13. public class GeneticEngine
  14. {
  15. /// <summary>
  16. /// The populator plugin
  17. /// </summary>
  18. private IPopulator populator;
  19. /// <summary>
  20. /// The evaluator plugin
  21. /// </summary>
  22. private IEvaluator evaluator;
  23. /// <summary>
  24. /// The gentic operator plugin
  25. /// </summary>
  26. private IGeneticOperator geneticOperator;
  27. /// <summary>
  28. /// The termination condition plugin
  29. /// </summary>
  30. private ITerminator terminator;
  31. /// <summary>
  32. /// The output plugin
  33. /// </summary>
  34. private IOutputter outputter;
  35. /// <summary>
  36. /// The generation factory plugin
  37. /// </summary>
  38. private IGenerationFactory generationFactory;
  39. /// <summary>
  40. /// The number of generations which have been processed
  41. /// </summary>
  42. private int generationNumber;
  43. /// <summary>
  44. /// The most recent generation
  45. /// </summary>
  46. private IGeneration generation = null;
  47. private bool run;
  48. /// <summary>
  49. /// Get the number of generations before the current generation.
  50. /// </summary>
  51. public int GenerationCount
  52. {
  53. get
  54. {
  55. return generationNumber;
  56. }
  57. }
  58. /// <summary>
  59. /// Get the current generation.
  60. /// </summary>
  61. public IGeneration Generation
  62. {
  63. get
  64. {
  65. return generation;
  66. }
  67. }
  68. /// <summary>
  69. /// Get a value indicating whether the current generation satisfies the termination condidtion.
  70. /// </summary>
  71. public bool IsComplete
  72. {
  73. get
  74. {
  75. try
  76. {
  77. return generation != null && terminator.Terminate(generation);
  78. }
  79. catch (Exception ex)
  80. {
  81. throw new GeneticEngineException(GeneticEngineException.Plugin.Terminator, "Error testing termination condition.", ex);
  82. }
  83. }
  84. }
  85. /// <summary>
  86. /// Initialise a new instance of the GeneticEngine class with the supplied plug-ins and populate the initial generation.
  87. /// </summary>
  88. /// <param name="populator">The populator plug-in. Generates the initial population.</param>
  89. /// <param name="evaluator">The evaluator plug-in. Provides the fitness function.</param>
  90. /// <param name="geneticOperator">The genetic operator plug-in. Processes one generation to produce the individuals for the next.</param>
  91. /// <param name="terminator">The terminator plug-in. Provides the termination condition.</param>
  92. /// <param name="outputter">The outputter plug-in or null for no output. Outputs each generation.</param>
  93. /// <param name="generationFactory">The generation factory plug-in or null to use the default. Creates the generation container.</param>
  94. public GeneticEngine(IPopulator populator, IEvaluator evaluator, IGeneticOperator geneticOperator, ITerminator terminator, IOutputter outputter = null, IGenerationFactory generationFactory = null)
  95. {
  96. if (populator == null)
  97. {
  98. throw new GeneticEngineException("populator must not be null");
  99. }
  100. if (evaluator == null)
  101. {
  102. throw new GeneticEngineException("pvaluator must not be null");
  103. }
  104. if (geneticOperator == null)
  105. {
  106. throw new GeneticEngineException("geneticOperator must not be null");
  107. }
  108. if (terminator == null)
  109. {
  110. throw new GeneticEngineException("terminator must not be null");
  111. }
  112. this.populator = populator;
  113. this.evaluator = evaluator;
  114. this.geneticOperator = geneticOperator;
  115. this.terminator = terminator;
  116. this.outputter = outputter;
  117. this.generationFactory = generationFactory == null ? new AATreeGenerationFactory() : generationFactory;
  118. Setup();
  119. }
  120. private void Setup()
  121. {
  122. generationNumber = -1;
  123. ArrayList individuals = new ArrayList();
  124. try
  125. {
  126. populator.Populate(individuals);
  127. }
  128. catch (Exception ex)
  129. {
  130. throw new GeneticEngineException(GeneticEngineException.Plugin.Populator, "Error generating initial population.", ex);
  131. }
  132. processIndividuals(individuals);
  133. }
  134. /// <summary>
  135. /// Reset the genetic engine by setting the generation count to 0 and using the populator plug-in
  136. /// to generate a new initial population
  137. /// </summary>
  138. public void Reset()
  139. {
  140. FinishOutput();
  141. Setup();
  142. }
  143. /// <summary>
  144. /// Call CloseOutput on the IOutputter its status is Open
  145. /// </summary>
  146. public void FinishOutput()
  147. {
  148. if (outputter != null && outputter.Status == OutputterStatus.Open)
  149. {
  150. try
  151. {
  152. outputter.CloseOutput();
  153. }
  154. catch (Exception ex)
  155. {
  156. throw new GeneticEngineException(GeneticEngineException.Plugin.Outputter, "Error closing outputter.", ex);
  157. }
  158. }
  159. }
  160. /// <summary>
  161. /// Process the current generation to produce the next.
  162. /// </summary>
  163. public void Step()
  164. {
  165. ArrayList individuals = new ArrayList();
  166. try
  167. {
  168. geneticOperator.Operate(generation, individuals);
  169. }
  170. catch (Exception ex)
  171. {
  172. throw new GeneticEngineException(GeneticEngineException.Plugin.GeneticOperator, "Error operating on generation.", ex);
  173. }
  174. processIndividuals(individuals);
  175. }
  176. /// <summary>
  177. /// Process a list of individuals.
  178. /// 1) Replace the current generation with a new empty IGeneration
  179. /// 2) Evaluate each individual and add it to the generation
  180. /// 3) Send the generation to the outputter
  181. /// </summary>
  182. /// <param name="individuals">The list of individuals</param>
  183. private void processIndividuals(ArrayList individuals)
  184. {
  185. //Get a new instance of the generation container.
  186. try
  187. {
  188. generation = generationFactory.CreateGeneration(individuals);
  189. }
  190. catch (Exception ex)
  191. {
  192. throw new GeneticEngineException(GeneticEngineException.Plugin.GenerationFactory, "Error getting empty generation.", ex);
  193. }
  194. //Inform the evaluator that an new generation has been started.
  195. try
  196. {
  197. evaluator.Initialise(generationNumber, individuals);
  198. }
  199. catch (Exception ex)
  200. {
  201. throw new GeneticEngineException(GeneticEngineException.Plugin.Evaluator, "Error initialising evaluator.", ex);
  202. }
  203. //Evaluate each individual and add it to the generation.
  204. foreach (object individual in individuals)
  205. {
  206. try
  207. {
  208. generation.Insert(individual, evaluator.Evaluate(individual));
  209. }
  210. catch (Exception ex)
  211. {
  212. throw new GeneticEngineException(GeneticEngineException.Plugin.Generation, "Error adding individual to generation.", ex);
  213. }
  214. }
  215. //Perform any preparation the generation needs before being given to the outputter or genetic operator plug-ins.
  216. try
  217. {
  218. generation.Prepare();
  219. }
  220. catch (Exception ex)
  221. {
  222. throw new GeneticEngineException(GeneticEngineException.Plugin.Generation, "Error preparing generation.", ex);
  223. }
  224. //Increment the generation counter.
  225. generationNumber++;
  226. //If an outputter plug-in has been supplied then output the new generation.
  227. if (outputter != null)
  228. {
  229. if (outputter.Status == OutputterStatus.Closed)
  230. {
  231. try
  232. {
  233. outputter.OpenOutput();
  234. }
  235. catch (Exception ex)
  236. {
  237. throw new GeneticEngineException(GeneticEngineException.Plugin.Outputter, "Error opening outputter.", ex);
  238. }
  239. }
  240. if (outputter.Status == OutputterStatus.Open)
  241. {
  242. try
  243. {
  244. outputter.OutputGeneration(generation, generationNumber);
  245. }
  246. catch (Exception ex)
  247. {
  248. throw new GeneticEngineException(GeneticEngineException.Plugin.Outputter, "Error outputting generation.", ex);
  249. }
  250. }
  251. }
  252. }
  253. /// <summary>
  254. /// Execute the genetic algorithm for a number of generations.
  255. /// </summary>
  256. /// <param name="n">The number of generations to process.</param>
  257. public void Repeat(int n)
  258. {
  259. run = true;
  260. int i = 0;
  261. while (run && i++ < n)
  262. {
  263. Step();
  264. }
  265. }
  266. /// <summary>
  267. /// Execute the genetic algorithm until the termination condition is satisfied.
  268. /// </summary>
  269. public void Run()
  270. {
  271. run = true;
  272. while (run && !IsComplete)
  273. {
  274. Step();
  275. }
  276. }
  277. /// <summary>
  278. /// Stop the GeneticEngine from starting the next generation when it is running multiple generations.
  279. /// </summary>
  280. public void Stop()
  281. {
  282. run = false;
  283. }
  284. }
  285. }