/// <summary>
        /// Performs crossover breeding between two GeneticSequences.
        /// </summary>
        /// <param name="sequence1">The first sequence.</param>
        /// <param name="sequence2">The second sequence.</param>
        /// <param name="random">The random to be used for the random crossover.</param>
        /// <returns>Returns the two new genetic sequences.</returns>
        public static GeneticSequence[] Crossover(GeneticSequence sequence1, GeneticSequence sequence2, Random random)
        {
            if (sequence1.CanBreedWith(sequence2))
            {
                int crossoverPoint = random.Next(0, sequence1.binarySequence.Length - 1);

                GeneticSequence[] parents      = { sequence1, sequence2 };
                bool[][]          newSequences = new bool[2][];

                for (int i = 0; i < newSequences.Length; i++)
                {
                    newSequences[i] = new bool[sequence1.binarySequence.Length];
                    for (int j = 0; j <= crossoverPoint; j++)
                    {
                        newSequences[i][j] = parents[i].binarySequence[j];
                    }
                    for (int j = crossoverPoint + 1; j < sequence1.binarySequence.Length; j++)
                    {
                        newSequences[i][j] = parents[(i + 1) % parents.Length].binarySequence[j];
                    }
                }

                return(new GeneticSequence[] { new GeneticSequence(newSequences[0]), new GeneticSequence(newSequences[1]) });
            }
            else
            {
                throw new Exception("Supplied sequences are not compatible.");
            }
        }
        /// <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>
        /// Creates a random genome for a set of phenotypes.
        /// </summary>
        /// <param name="phenotypes">The set of phenotypes.</param>
        /// <param name="random">The random to be used for the random generation of genetic sequences.</param>
        /// <param name="sequenceBitLength">The bit length of the random genetic sequences.</param>
        /// <returns>Returns the randomly-generated genome.</returns>
        private static GeneticSequence[] GetRandomGenome(Phenotype[] phenotypes, Random random, int sequenceBitLength)
        {
            int sequenceLength = 0;

            for (int i = 0; i < phenotypes.Length; i++)
            {
                sequenceLength += phenotypes[i].GenomeLengthRequirement;
            }

            GeneticSequence[] genome = new GeneticSequence[sequenceLength];
            for (int i = 0; i < genome.Length; i++)
            {
                genome[i] = new GeneticSequence(sequenceBitLength, random);
            }

            return(genome);
        }
        /// <summary>
        /// Assigns a genome to the ModularMember.
        /// </summary>
        /// <param name="genome">The genome to be assigned.</param>
        /// <returns>Returns whether the assignment was successful.</returns>
        public bool AssignGenome(GeneticSequence[] genome)
        {
            int sequenceLength = 0;

            for (int i = 0; i < phenotypes.Length; i++)
            {
                sequenceLength += phenotypes[i].GenomeLengthRequirement;
            }

            //Ensure correct length and not already assigned
            if (isGenomeAssigned || genome.Length != sequenceLength)
            {
                return(false);
            }
            else
            {
                int sequenceIndex = 0;

                //Assign to phenotypes
                for (int i = 0; i < phenotypes.Length; i++)
                {
                    GeneticSequence[] individualSequences = new GeneticSequence[phenotypes[i].GenomeLengthRequirement];
                    for (int j = 0; j < individualSequences.Length; j++)
                    {
                        individualSequences[j] = genome[sequenceIndex + j];
                    }

                    phenotypes[i].SetGenome(individualSequences);
                    sequenceIndex += phenotypes[i].GenomeLengthRequirement;
                }

                this.genome      = genome;
                isGenomeAssigned = true;

                return(true);
            }
        }
 /// <summary>
 /// Determines if this GeneticSequence can be bred with another sequence.
 /// </summary>
 /// <param name="partner">The other GeneticSequence.</param>
 /// <returns>Returns whether the sequences are breedable.</returns>
 public bool CanBreedWith(GeneticSequence partner)
 {
     return(binarySequence.Length == partner.binarySequence.Length);
 }