00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 using System.Text;
00005 using GEP.Core.Common;
00006 using GEP.Core.Common.GeneticOperators;
00007 using System.Threading;
00008 using System.Runtime.Serialization;
00009 using System.Runtime.Serialization.Formatters.Binary;
00010 using System.IO;
00011
00012 namespace GEP.Core.Common
00013 {
00019 public delegate void GenerationCalculatedCallback(Population population);
00020
00028 [Serializable]
00029 public abstract class Population
00030 {
00031 public GenerationCalculatedCallback _generationCalculatedCallback;
00032
00036 protected Random _random = new Random();
00040 public int _n_generations;
00046 public string _autoSaveFilePath;
00050 public int _autoSaveInterval;
00054 public DateTime _previousAutoSave = DateTime.Now;
00058 public List<Genotype> _fittestList = new List<Genotype>(20);
00059 protected Genotype _fittest;
00063 public Genotype Fittest
00064 {
00065 get
00066 {
00067 return _fittest;
00068 }
00069 }
00073 public int N_generations
00074 {
00075 get
00076 {
00077 return _n_generations;
00078 }
00079 }
00083 internal OperatorsSet _operators;
00087 public int Size
00088 {
00089 get
00090 {
00091 return _genotypes.Length;
00092 }
00093 }
00094
00095 internal double _totalMatingProbability;
00099 public double TotalMatingProbability
00100 {
00101 get
00102 {
00103 return _totalMatingProbability;
00104 }
00105 }
00106
00112 internal int[] _functionStack;
00113 internal Genotype[] _genotypes;
00122 public Genotype this[int genotypeIndex]
00123 {
00124 get
00125 {
00126 return _genotypes[genotypeIndex];
00127 }
00128 set
00129 {
00130 _genotypes[genotypeIndex] = value;
00131 }
00132 }
00133
00134 protected int _generation;
00138 public int Generation
00139 {
00140 get
00141 {
00142 return _generation;
00143 }
00144 }
00145
00146 protected Symbol _genesLinkingFunction;
00147
00153 public Symbol GenesLinkingFunction
00154 {
00155 get
00156 {
00157 return _genesLinkingFunction;
00158 }
00159 }
00160 protected Alphabet _functionsSet;
00165 public Alphabet FunctionsSet
00166 {
00167 get
00168 {
00169 return _functionsSet;
00170 }
00171 }
00172 protected Alphabet _variablesSet;
00177 public Alphabet VariablesSet
00178 {
00179 get
00180 {
00181 return _variablesSet;
00182 }
00183 }
00184 protected Alphabet _constantsSet;
00190 public Alphabet ConstantsSet
00191 {
00192 get
00193 {
00194 return _constantsSet;
00195 }
00196 }
00206 protected double[] _symbolSetsProbabilityDistribution;
00207 protected int _n_Genes;
00211 public int N_Genes
00212 {
00213 get
00214 {
00215 return _n_Genes;
00216 }
00217 }
00218 protected int _geneLength;
00222 public int GeneLength
00223 {
00224 get
00225 {
00226 return _geneLength;
00227 }
00228 }
00229 protected int _headLength;
00233 public int HeadLength
00234 {
00235 get
00236 {
00237 return _headLength;
00238 }
00239 }
00240 protected int _tailLength;
00244 public int TailLength
00245 {
00246 get
00247 {
00248 return _tailLength;
00249 }
00250 }
00251 protected int _genotypeLength;
00256 public int GenotypeLength
00257 {
00258 get
00259 {
00260 return _genotypeLength;
00261 }
00262 }
00263
00290 public Population(int n_Genes, int headLength, int n_generations, Alphabet functionsSet, Alphabet variablesSet,
00291 Alphabet constantsSet, double[] symbolSetsProbabilityDistribution, Symbol genesLinkingFunction,
00292 OperatorsSet operators)
00293
00294
00295
00296
00297
00298
00299
00300 {
00301 if (n_Genes == 0)
00302 throw new GepException("The number of genes must be greater than 1.");
00303 if (constantsSet.Length == 0 && variablesSet.Length == 0)
00304 throw new GepException("The constants' set or the variables' set must have at least 1 element.");
00305 for (int i = constantsSet.Length - 1; 0 <= i; i--)
00306 {
00307 if (constantsSet[i].N_Parameters != 0)
00308 throw new GepException("The symbols in the constants' set must accept no parameters.");
00309 }
00310 for (int i = variablesSet.Length - 1; 0 <= i; i--)
00311 {
00312 if (variablesSet[i].N_Parameters != 0)
00313 throw new GepException("The symbols in the variables' set must accept no parameters.");
00314 }
00315 if (symbolSetsProbabilityDistribution[0] > 1 || symbolSetsProbabilityDistribution[0] < 0)
00316 throw new GepException("The probability of function random generation must be between 0 and 1.");
00317 if (symbolSetsProbabilityDistribution[1] - symbolSetsProbabilityDistribution[0] > 1 ||
00318 symbolSetsProbabilityDistribution[1] - symbolSetsProbabilityDistribution[0] < 0)
00319 throw new GepException("The probability of variable random generation must be between 0 and 1.");
00320 if (1 - symbolSetsProbabilityDistribution[0] - (symbolSetsProbabilityDistribution[1] - symbolSetsProbabilityDistribution[0]) > 1 ||
00321 1 - symbolSetsProbabilityDistribution[0] - (symbolSetsProbabilityDistribution[1] - symbolSetsProbabilityDistribution[0]) < 0)
00322 throw new GepException("The probability of constant random generation must be between 0 and 1.");
00323 if (genesLinkingFunction != null && genesLinkingFunction.N_Parameters == 0)
00324 throw new GepException("The genes linking function can be either null or must accept more than 0 parameters.");
00325 if (genesLinkingFunction != null && genesLinkingFunction.N_Parameters == 1 && n_Genes != 1)
00326 throw new GepException("When the genes linking function accepts only 1 parameter, the number of genes must be 1.");
00327 else if (genesLinkingFunction != null && n_Genes != genesLinkingFunction.N_Parameters)
00328 throw new GepException("The linking function number of parameters must be equal to the number of genes.");
00329 _n_generations = n_generations;
00330 _n_Genes = n_Genes;
00331 _headLength = headLength;
00332 _tailLength = headLength * (functionsSet.MaxN_Parameters - 1) + 1;
00333 _functionsSet = functionsSet;
00334 _variablesSet = variablesSet;
00335 _constantsSet = constantsSet;
00336 _symbolSetsProbabilityDistribution = symbolSetsProbabilityDistribution;
00337 _geneLength = headLength + 2 * _tailLength;
00338 _genotypeLength = n_Genes * _geneLength;
00339 _genesLinkingFunction = genesLinkingFunction;
00340 _operators = operators;
00341 }
00342
00347 public abstract void Initialize(int populationSize);
00348
00359 public void UpdateSymbolRefereces(Alphabet functionsSet, Alphabet variablesSet, Alphabet constantsSet)
00360 {
00361 for (int i = _genotypes.Length - 1; 0 <= i; i--)
00362 {
00363 _genotypes[i].UpdateFunctionReferences(_functionsSet, functionsSet);
00364 _genotypes[i].UpdateVariableReferences(_variablesSet, variablesSet);
00365 _genotypes[i].UpdateConstantReferences(_constantsSet, constantsSet);
00366 }
00367 }
00368
00372 public void NextGeneration()
00373 {
00374 CalculateFitnessAndMatingProbabilities();
00375 Genotype fittest = _fittest;
00376 for (int i = _genotypes.Length - 1; 0 <= i; i--)
00377 {
00378 if (double.IsNaN(_genotypes[i]._fitness) || double.IsInfinity(_genotypes[i]._fitness))
00379 continue;
00380 if (_operators._matingProbabilityFunction._fitnessCloserToZeroIsBetter)
00381 {
00382 if (_genotypes[i]._fitness < _fittest._fitness)
00383 {
00384 _fittest = _genotypes[i];
00385 _fittest.CloneConstants();
00386 }
00387 }
00388 else
00389 {
00390 if (_fittest._fitness < _genotypes[i]._fitness)
00391 {
00392 _fittest = _genotypes[i];
00393 _fittest.CloneConstants();
00394 }
00395 }
00396 }
00397 if (!ReferenceEquals(fittest, _fittest))
00398 {
00399 _operators._fitnessFunction.SetFitness(_fittest, true);
00400 _fittestList.Add(_fittest);
00401 }
00402 AutoSave();
00403 if (_generationCalculatedCallback != null)
00404 _generationCalculatedCallback(this);
00405 if (_generation > _n_generations)
00406 return;
00407 _generation++;
00408 Genotype[] newGenotypes = new Genotype[_genotypes.Length];
00409 int destinationIndex = 0;
00410 int n_GeneticOperators = _operators._geneticOperators.Length;
00411 for (int i = 0; i < n_GeneticOperators; i++)
00412 {
00413 if (_operators._geneticOperators[i]._applyOnNewGeneration)
00414 continue;
00415 if (_operators._geneticOperators[i].ProducesNewOffspring)
00416 _operators._geneticOperators[i].Apply(this, newGenotypes, ref destinationIndex);
00417 else
00418 _operators._geneticOperators[i].Apply(this);
00419 }
00420 _genotypes = newGenotypes;
00421 for (int i = 0; i < n_GeneticOperators; i++)
00422 {
00423 if (!_operators._geneticOperators[i]._applyOnNewGeneration)
00424 continue;
00425 if (_operators._geneticOperators[i].ProducesNewOffspring)
00426 _operators._geneticOperators[i].Apply(this, newGenotypes, ref destinationIndex);
00427 else
00428 _operators._geneticOperators[i].Apply(this);
00429 }
00430 MutateConstants();
00431 }
00432
00437 public void CalculateFitnessAndMatingProbabilities()
00438 {
00439 for (int i = _genotypes.Length - 1; 0 <= i; i--)
00440 {
00441 _operators._fitnessFunction.SetFitness(_genotypes[i], false);
00442 }
00443 _operators._matingProbabilityFunction.SetMatingProbability(this);
00444 }
00445
00449 protected abstract void MutateConstants();
00450
00454 public void Start()
00455 {
00456 for (int i = 0; i <= _n_generations; i++)
00457 {
00458 NextGeneration();
00459 }
00460 }
00461
00469 public void AutoSave()
00470 {
00471 if (_autoSaveFilePath == null)
00472 return;
00473 if (DateTime.Now > _previousAutoSave.AddMinutes(_autoSaveInterval))
00474 {
00475 Save(_autoSaveFilePath);
00476 _previousAutoSave = _previousAutoSave.AddMinutes(_autoSaveInterval);
00477 }
00478 }
00479
00484 public void Save(string filePath)
00485 {
00486 FileStream s = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
00487 BinaryFormatter b = new BinaryFormatter();
00488 b.Serialize(s, this);
00489 s.Close();
00490 }
00491
00497 public static Population Load(string filePath)
00498 {
00499 FileStream s = new FileStream(filePath, FileMode.Open, FileAccess.Read);
00500 BinaryFormatter b = new BinaryFormatter();
00501 Population population = (Population)b.Deserialize(s);
00502 s.Close();
00503 return population;
00504 }
00505 }
00506 }