/// <summary> /// Method to Mutate the specified child in derived classes. The method would not normally /// be called directly. It will be called by the framework as required. /// </summary> /// <param name="child"></param> protected override void Mutate(Chromosome child) { // this method calls the base class later which handles elites // duplicates are handled here Chromosome childToMutate = null; if (AllowDuplicates) { childToMutate = child; } else { //We have to clone the chromosome before we mutate it as it may //not be usable i.e. if it is a duplicate if we didn't clone it //and we created a duplicate through mutation we would have to //undo the mutation. This way is easier. childToMutate = child.DeepClone(); } //call the default mutation behaviour, this will inturn call the abstract //class 'MutateGene' implemented in this class below. base.Mutate(childToMutate); //only add the mutated chromosome if it does not exist otherwise do nothing if (!AllowDuplicates && !NewPopulation.SolutionExists(childToMutate)) { //swap existing genes for the mutated onese child.Genes = childToMutate.Genes; } }
/// <summary> /// Adds a child to the new population depending upon the criteria set in relation to replacement /// method and duplicate handling. The method updates the evaluation count and returns true if a /// child was added to the new population. /// </summary> /// <param name="child"></param> /// <returns></returns> private bool AddChild(Chromosome child) { var result = false; if (_replacementMethodS == ReplacementMethod.DeleteLast) { child.Evaluate(FitnessFunction); _evaluations++; if (child.Genes != null && child.Fitness > CurrentPopulation.MinimumFitness) { //add the child if there is still space if (AllowDuplicates || !NewPopulation.SolutionExists(child)) { //add the new child and remove the last NewPopulation.Solutions.Add(child); if (NewPopulation.Solutions.Count > _currentPopulationSize) { NewPopulation.Solutions.Sort(); NewPopulation.Solutions.RemoveAt(_currentPopulationSize - 1); result = true; } else { //we return true whether we actually added or not what we are effectively //doing here is adding the original child from the current solution result = true; } } } } else { //we need to cater for the user switching from delete last to Generational Replacement //in this scenrio we will have a full population but with still some children to generate if (NewPopulation.Solutions.Count + _numberOfChildrenToGenerate > _currentPopulationSize) { //assume all done for this generation _numberOfChildrenToGenerate = 0; return(false); } if (child.Genes != null) { //add the child if there is still space if (this.AllowDuplicates || !NewPopulation.SolutionExists(child)) { NewPopulation.Solutions.Add(child); result = true; } } } return(result); }