/// <summary> /// This is the method that invokes the operator. This should not normally be called explicitly. /// </summary> /// <param name="currentPopulation"></param> /// <param name="newPopulation"></param> /// <param name="fitnessFunctionDelegate"></param> public new virtual void Invoke(Population currentPopulation, ref Population newPopulation, FitnessFunction fitnessFunctionDelegate) { if (currentPopulation.Solutions == null || currentPopulation.Solutions.Count == 0) { throw new ArgumentException("There are no Solutions in the current Population."); } if (newPopulation == null) { newPopulation = currentPopulation.CreateEmptyCopy(); } CurrentPopulation = currentPopulation; NewPopulation = newPopulation; FitnessFunction = fitnessFunctionDelegate; if (!Enabled) { return; } //TODO: Investigate this bizare code!!! //need to store this as we cannot handle a change until once this generation has started //_replacementMethodS = ReplacementMethod; int maxLoop = 100; int eliteCount = 0; //reset the number of evaluations _evaluations = 0; //now that we know how many children we are to be creating, in the case of 'Delete Last' //we copy the current generation across and add new children where they are greater than //the worst solution. if (_replacementMethodS == ReplacementMethod.DeleteLast) { //copy everything accross including the elites NewPopulation.Solutions.Clear(); NewPopulation.Solutions.AddRange(CurrentPopulation.Solutions); } else { //just copy the elites, this will take all elites //TODO: Sort out what we do if we overfill the population with elites var elites = CurrentPopulation.GetElites(); eliteCount = elites.Count(); if (elites != null && eliteCount > 0) { NewPopulation.Solutions.AddRange(elites); } } _currentPopulationSize = CurrentPopulation.Solutions.Count; _numberOfChildrenToGenerate = _currentPopulationSize - eliteCount; while (_numberOfChildrenToGenerate > 0) { //emergency exit if (maxLoop <= 0) { throw new ChromosomeException("Unable to create a suitable child. If duplicates have been disallowed then consider increasing the chromosome length or increasing the number of elites."); } //these will hold the children Chromosome c1 = null; Chromosome c2 = null; //select some parents var parents = CurrentPopulation.SelectParents(); var p1 = parents [0]; var p2 = parents [1]; //crossover var crossoverData = CreateCrossoverData(p1.Genes.Count, CrossoverType); PerformCrossover(p1, p2, crossoverData, out c1, out c2); //pass the children out to derived classes //(e.g. CrossoverMutate class uses this to perform mutation) if (OnCrossoverComplete != null) { var eventArgs = new CrossoverEventArgs(crossoverData, p1, p2, c1, c2); OnCrossoverComplete(this, eventArgs); } if (AddChild(c1)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } //see if we can add the secomd if (_numberOfChildrenToGenerate > 0) { if (AddChild(c2)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } } } //TODO: Test this, we shouldn't need it. newPopulation = NewPopulation; }
/// <summary> /// Main process loop for performing a crossover on a population. /// </summary> protected void Process() { int maxLoop = 100; int eliteCount = 0; //reset the number of evaluations _evaluations = 0; //now that we know how many children we are to be creating, in the case of 'Delete Last' //we copy the current generation across and add new children where they are greater than //the worst solution. if (_replacementMethodS == ReplacementMethod.DeleteLast) { //copy everything accross including the elites _newPopulation.Solutions.Clear(); _newPopulation.Solutions.AddRange(_currentPopulation.Solutions); } else { //just copy the elites, this will take all elites //TODO: Sort out what we do if we overfill the population with elites var elites = _currentPopulation.GetElites(); eliteCount = elites.Count(); if (elites != null && eliteCount > 0) { _newPopulation.Solutions.AddRange(elites); } } _currentPopulationSize = _currentPopulation.Solutions.Count; _numberOfChildrenToGenerate = _currentPopulationSize - eliteCount; while (_numberOfChildrenToGenerate > 0) { //emergency exit if (maxLoop <= 0) { throw new ChromosomeException("Unable to create a suitable child. If duplicates have been disallowed then consider increasing the chromosome length or increasing the number of elites."); } //these will hold the children Chromosome c1 = null; Chromosome c2 = null; //select some parents var parents = _currentPopulation.SelectParents(); var p1 = parents [0]; var p2 = parents [1]; //crossover var crossoverData = CreateCrossoverData(p1.Genes.Count, CrossoverType); var crossoverResult = PerformCrossover(p1, p2, CrossoverProbability, CrossoverType, crossoverData, out c1, out c2); //pass the children out to derived classes //(e.g. CrossoverMutate class uses this to perform mutation) if (OnCrossoverComplete != null) { var eventArgs = new CrossoverEventArgs(crossoverResult, p1, p2, c1, c2); OnCrossoverComplete(this, eventArgs); } if (AddChild(c1)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } //see if we can add the secomd if (_numberOfChildrenToGenerate > 0) { if (AddChild(c2)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } } } }