/// <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);
 }