/// <summary> /// Sets the ModularMember (used for breeding). /// </summary> /// <param name="modularMember">The ModularMember to be set.</param> private void SetModularMember(ModularMember modularMember) { if (!modularMember.IsGenomeAssigned) { throw new Exception("Genome has not been assigned to modular member!"); } this.modularMember = modularMember; }
/// <summary> /// Evolves a generation of FitnessEvolvers. /// </summary> /// <typeparam name="T">The type of FitnessEvolvers to be evolved.</typeparam> /// <param name="generation">The generation of FitnessEvolvers.</param> /// <param name="selectionPercentage">The percentage of the fittest within the generation that will be selected for breeding in the next generation.</param> /// <param name="mutationRate">The mutation rate to be used while breeding the next generation.</param> /// <param name="fittestMember">The fittest member of the evaluated generation.</param> /// <param name="random">The random to be used for breeding and selection.</param> /// <param name="multithreaded">Whether the evaluation processes should happen on multiple threads.</param> /// <returns>Returns the evolved generation.</returns> public static T[] EvolveGeneration <T>(T[] generation, double selectionPercentage, double mutationRate, out MemberEvaluation <T, D> fittestMember, Random random, bool multithreaded = false) where T : FitnessEvolver <D>, new() { //Evaluate members MemberEvaluation <T, D>[] memberEvaluations = new MemberEvaluation <T, D> [generation.Length]; if (multithreaded) { Parallel.For(0, generation.Length, (i) => { memberEvaluations[i] = new MemberEvaluation <T, D>(generation[i], generation[i].DetermineFitness()); }); } else { for (int i = 0; i < generation.Length; i++) { memberEvaluations[i] = new MemberEvaluation <T, D>(generation[i], generation[i].DetermineFitness()); } } //Sort members Array.Sort(memberEvaluations, delegate(MemberEvaluation <T, D> x, MemberEvaluation <T, D> y) { return(y.Fitness.CompareTo(x.Fitness)); }); //Select top int numToSelect = (int)Math.Ceiling(selectionPercentage * generation.Length); MemberEvaluation <T, D>[] selectedMembers = new MemberEvaluation <T, D> [numToSelect]; for (int i = 0; i < numToSelect; i++) { selectedMembers[i] = memberEvaluations[i]; } fittestMember = memberEvaluations[0]; //Breed remaining List <T> newGeneration = new List <T>(generation.Length); for (int i = 0; i < selectedMembers.Length; i++) { newGeneration.Add(selectedMembers[i].FitnessMember); } while (newGeneration.Count < generation.Length) { T parent1 = WeightedSelect(selectedMembers, random); T parent2 = WeightedSelect(selectedMembers, random); D parent1Data = parent1.GetData(); D parent2Data = parent2.GetData(); ModularMember[] childGenomes = ModularMember.BreedMembers(parent1.ModularMember, parent2.ModularMember, mutationRate, random); for (int i = 0; i < childGenomes.Length && newGeneration.Count < generation.Length; i++) { T child = new T(); child.SetModularMember(childGenomes[i]); child.SetData(parent1Data, parent2Data); newGeneration.Add(child); } } return(newGeneration.ToArray()); }
/// <summary> /// Breeds two ModularMembers and produces two children. /// </summary> /// <param name="parent1">The first parent.</param> /// <param name="parent2">The second parent.</param> /// <param name="mutationRate">The mutation rate during breeding.</param> /// <param name="random">The random to be used while breeding.</param> /// <returns>Returns the two children.</returns> public static ModularMember[] BreedMembers(ModularMember parent1, ModularMember parent2, double mutationRate, Random random) { //Ensure breedable if (parent1.CanBreedWith(parent2)) { GeneticSequence[] child1Genome = new GeneticSequence[parent1.genome.Length]; GeneticSequence[] child2Genome = new GeneticSequence[parent1.genome.Length]; for (int i = 0; i < parent1.genome.Length; i++) { GeneticSequence[] crossoverSequences = GeneticSequence.Crossover(parent1.genome[i], parent2.genome[i], random); child1Genome[i] = crossoverSequences[0]; child2Genome[i] = crossoverSequences[1]; } //Mutate each genome for (int i = 0; i < child1Genome.Length; i++) { child1Genome[i] = child1Genome[i].BitwiseMutate(mutationRate, random); } for (int i = 0; i < child2Genome.Length; i++) { child2Genome[i] = child2Genome[i].BitwiseMutate(mutationRate, random); } ModularMember[] parents = new ModularMember[] { parent1, parent2 }; GeneticSequence[][] childSequences = new GeneticSequence[][] { child1Genome, child2Genome }; ModularMember[] children = new ModularMember[2]; for (int i = 0; i < children.Length; i++) { Phenotype[] phenotypes = new Phenotype[parents[i].phenotypes.Length]; for (int j = 0; j < phenotypes.Length; j++) { phenotypes[j] = parents[i].phenotypes[j].Clone(parents[(i + 1) % parents.Length].phenotypes[j]); } children[i] = new ModularMember(phenotypes); children[i].AssignGenome(childSequences[i]); } return(children); } else { throw new Exception("Provided parents are not breedable."); } }
/// <summary> /// Determines if two ModularMembers can breed. /// </summary> /// <param name="member">The other ModularMember.</param> /// <returns>Returns whether the ModularMembers are breedable.</returns> public bool CanBreedWith(ModularMember member) { //Compare lengths if (phenotypes.Length != member.phenotypes.Length || genome.Length != member.genome.Length || genome[0].BinarySequence.Length != member.genome[0].BinarySequence.Length) { return(false); } else { //Compare phenotypes for (int i = 0; i < phenotypes.Length; i++) { if (!phenotypes[i].Equals(member.phenotypes[i])) { return(false); } } return(true); } }
/// <summary> /// Creates a fitness evolver with a specified ModularMember. /// </summary> /// <param name="modularMember">The ModularMember to be used.</param> public FitnessEvolver(ModularMember modularMember) { SetModularMember(modularMember); }