public Genome()
 {
     this.Phenotype       = null;
     this.GenomeID        = 0;
     this.Fitness         = 0;
     this.AdjustedFitness = 0;
     this.NumberOfInputs  = 0;
     this.NumberOfOutputs = 0;
     this.AmountToSpawn   = 0;
     this.Species         = 0;
 }
        /// <summary>
        /// Creates a neural network based upon the information in the genome.
        /// The method that actually creates all the SLinks and SNeurons required for a phenotype
        /// is Genome::CreatePhenotype.This function iterates through the genome and
        /// creates any appropriate neurons and all the required links required for pointing to
        /// those neurons.It then creates an instance of the CNeuralNet class.
        /// </summary>
        /// <param name="depth">Returns a pointer to the newly created ANN </param>
        /// <returns></returns>
        public NeuralNet CreatePhenotype(int depth)
        {
            //first make sure there is no existing phenotype for this genome
            DeletePhenotype();

            //this will hold all the neurons required for the phenotype
            List <Neuron> phenotypeNeurons = new List <Neuron>();

            //first, create all the required neurons
            for (int i = 0; i < this.Neurons.Count; i++)
            {
                Neuron neuron = new Neuron(this.Neurons[i].NeuronType,
                                           this.Neurons[i].ID,
                                           this.Neurons[i].SplitY,
                                           this.Neurons[i].SplitX,
                                           this.Neurons[i].ActivationResponse);

                phenotypeNeurons.Add(neuron);
            }

            //now to create the links.
            for (int cGene = 0; cGene < this.Links.Count; ++cGene)
            {
                //make sure the link gene is enabled before the connection is created
                if (this.Links[cGene].Enabled)
                {
                    //get the pointers to the relevant neurons
                    int    element    = GetElementPosition(this.Links[cGene].FromNeuron);
                    Neuron FromNeuron = phenotypeNeurons[element];

                    element = GetElementPosition(this.Links[cGene].ToNeuron);
                    Neuron ToNeuron = phenotypeNeurons[element];

                    //create a link between those two neurons and assign the weight stored
                    //in the gene
                    Link tmpLink = new Link(this.Links[cGene].Weight,
                                            FromNeuron,
                                            ToNeuron,
                                            this.Links[cGene].Recurrent);

                    //add new links to neuron
                    FromNeuron.LinksOut.Add(tmpLink);
                    ToNeuron.LinksIn.Add(tmpLink);
                }
            }

            //now the neurons contain all the connectivity information, a neural
            //network may be created from them.
            Phenotype = new NeuralNet(phenotypeNeurons, depth);

            return(Phenotype);
        }
 /// <summary>
 /// this constructor creates a genome from a vector of LinkGenes a vector of NeuronGenes and an ID number
 /// </summary>
 /// <param name="id"></param>
 /// <param name="neurons"></param>
 /// <param name="genes"></param>
 /// <param name="inputs"></param>
 /// <param name="outputs"></param>
 public Genome(int id, List <NeuronGene> neurons, List <LinkGene> genes, int inputs, int outputs)
 {
     this.Phenotype       = null;
     this.GenomeID        = id;
     this.Fitness         = 0;
     this.AdjustedFitness = 0;
     this.NumberOfInputs  = inputs;
     this.NumberOfOutputs = outputs;
     this.AmountToSpawn   = 0;
     this.Species         = 0;
     this.Links           = genes;
     this.Neurons         = neurons;
 }
        /// <summary>
        /// iterates through the population and creates the phenotypes
        /// cycles through all the members of the population and creates their
        ///  phenotypes. Returns a vector containing pointers to the new phenotypes
        /// </summary>
        /// <returns></returns>
        public List <NeuralNet> CreatePhenotypes()
        {
            List <NeuralNet> networks = new List <NeuralNet>();

            for (int i = 0; i < this.PopSize; i++)
            {
                //calculate max network depth
                int depth = CalculateNetDepth(Genomes[i]);

                //create new phenotype
                NeuralNet net = Genomes[i].CreatePhenotype(depth);

                networks.Add(net);
            }

            return(networks);
        }
        /// <summary>
        /// this constructor creates a minimal genome where there are output & input neurons and every input neuron is connected to each output neuron
        /// </summary>
        /// <param name="id"></param>
        /// <param name="inputs"></param>
        /// <param name="outputs"></param>
        public Genome(int id, int inputs, int outputs)
        {
            this.Phenotype       = null;
            this.GenomeID        = id;
            this.Fitness         = 0;
            this.AdjustedFitness = 0;
            this.NumberOfInputs  = inputs;
            this.NumberOfOutputs = outputs;
            this.AmountToSpawn   = 0;
            this.Species         = 0;
            this.Neurons         = new List <NeuronGene>();
            this.Links           = new List <LinkGene>();

            //create the input neurons
            double InputRowSlice = 1 / (double)(inputs + 2);

            for (int i = 0; i < inputs; i++)
            {
                this.Neurons.Add(new NeuronGene(NeuronType.Input, i, 0, (i + 2) * InputRowSlice));
            }

            //create the bias
            this.Neurons.Add(new NeuronGene(NeuronType.Bias, inputs, 0, InputRowSlice));

            //create the output neurons
            double OutputRowSlice = 1 / (double)(outputs + 1);

            for (int i = 0; i < outputs; i++)
            {
                this.Neurons.Add(new NeuronGene(NeuronType.Output, i + inputs + 1, 1, (i + 1) * OutputRowSlice));
            }

            //create the link genes, connect each input neuron to each output neuron and
            //assign a random weight -1 < w < 1
            for (int i = 0; i < inputs + 1; i++)
            {
                for (int j = 0; j < outputs; j++)
                {
                    this.Links.Add(new LinkGene(this.Neurons[i].ID,
                                                this.Neurons[inputs + j + 1].ID,
                                                true,
                                                inputs + outputs + 1 + this.GetNumGenes(),
                                                RandomProvider.RandomClamped()));
                }
            }
        }
        /// <summary>
        /// This function performs one epoch of the genetic algorithm and returns a vector of pointers to the new phenotypes
        /// </summary>
        /// <param name="FitnessScores"></param>
        /// <returns></returns>
        public List <NeuralNet> Epoch(List <double> FitnessScores)
        {
            // 21.10.2015 TODO: IF THE FITNESS IF ZERO THE GA WILL NOT WORK AND BEHAVE UN EXPECTEDLY THIS NEEDS FAIL SAFE MACHANISM
            //first check to make sure we have the correct amount of fitness scores
            if (FitnessScores.Count != this.Genomes.Length)
            {
                Debug.Log("Cga::Epoch(scores/ genomes mismatch)!");
            }
            //Debug.Log(" Befiore ResetAndKill");
            //reset appropriate values and kill off the existing phenotypes and
            //any poorly performing species
            ResetAndKill();

            //Debug.Log("ResetAndKill");

            /*
             * First of all, any phenotypes created during the previous generation are deleted. The
             * program then examines each species in turn and deletes all of its members apart
             * from the best performing one. (You use this individual as the genome to be tested
             * against when the compatibility distances are calculated). If a species hasn’t made
             * any fitness improvement in CParams::iNumGensAllowedNoImprovement generations, the
             * species is killed off.*/
            //update the genomes with the fitnesses scored in the last run
            // BUG HERE WITH C# value not set???
            for (int gen = 0; gen < this.Genomes.Length; ++gen)
            {
                this.Genomes[gen].SetFitness(FitnessScores[gen]);
            }


            //sort genomes and keep a record of the best performers
            SortAndRecord();

            //separate the population into species of similar topology, adjust
            //fitnesses and calculate spawn levels
            SpeciateAndCalculateSpawnLevels();

            //Debug.Log("SpeciateAndCalculateSpawnLevels");

            /*
             * SpeciateAndCalculateSpawnLevels commences by calculating the compatibility distance
             * of each genome against the representative genome from each live species. If the
             * value is within a set tolerance, the individual is added to that species. If no species
             * match is found, then a new species is created and the genome added to that.
             * When all the genomes have been assigned to a species
             * SpeciateAndCalculateSpawnLevels calls the member function AdjustSpeciesFitnesses to
             * adjust and share the fitness scores as discussed previously.
             *
             * Next, SpeciateAndCalculateSpawnLevels calculates how many offspring each individual
             * is predicted to spawn into the new generation. This is a floating-point value calculated
             * by dividing each genome’s adjusted fitness score with the average adjusted
             * fitness score for the entire population. For example, if a genome had an adjusted
             * fitness score of 4.4 and the average is 8.0, then the genome should spawn 0.525
             * offspring. Of course, it’s impossible for an organism to spawn a fractional part of
             * itself, but all the individual spawn amounts for the members of each species are
             * summed to calculate an overall spawn amount for that species. Table 11.3 may help
             * clear up any confusion you may have with this process. It shows typical spawn values
             * for a small population of 20 individuals. The epoch function can now simply iterate
             * through each species and spawn the required amount of offspring.
             */

            //this will hold the new population of genomes
            Genome[] NewPop = new Genome[this.PopSize];
            int      currentNewGenomeIndex = 0;

            //request the offspring from each species. The number of children to
            //spawn is a double which we need to convert to an int.
            int NumSpawnedSoFar = 0;

            Genome baby = null;

            //now to iterate through each species selecting offspring to be mated and
            //mutated
            for (int spc = 0; spc < this.Species.Count; ++spc)
            {
                //because of the number to spawn from each species is a double
                //rounded up or down to an integer it is possible to get an overflow
                //of genomes spawned. This statement just makes sure that doesn't
                //happen
                if (NumSpawnedSoFar < NeuralNetworkParams.UnityInstantiatedNumSweepers)
                {
                    //this is the amount of offspring this species is required to
                    // spawn. Rounded simply rounds the double up or down.
                    int NumToSpawn = Mathf.RoundToInt((float)this.Species[spc].NumToSpawn());

                    bool bChosenBestYet = false;

                    while (NumToSpawn-- > 0)
                    {
                        //first grab the best performing genome from this species and transfer
                        //to the new population without mutation. This provides per species
                        //elitism
                        if (!bChosenBestYet)
                        {
                            baby = this.Species[spc].GetLeader();

                            bChosenBestYet = true;
                        }

                        else
                        {
                            //if the number of individuals in this species is only one
                            //then we can only perform mutation
                            if (this.Species[spc].NumMembers() == 1)
                            {
                                //spawn a child
                                baby = this.Species[spc].Spawn();
                            }

                            //if greater than one we can use the crossover operator
                            else
                            {
                                //spawn1
                                Genome g1 = this.Species[spc].Spawn();

                                if (RandomProvider.RandomFloat() < NeuralNetworkParams.CrossoverRate)
                                {
                                    //spawn2, make sure it's not the same as g1
                                    Genome g2 = this.Species[spc].Spawn();

                                    //number of attempts at finding a different genome
                                    int NumAttempts = 5;

                                    while ((g1.GetID() == g2.GetID()) && (NumAttempts-- >= 0))
                                    {
                                        g2 = this.Species[spc].Spawn();
                                    }

                                    if (g1.GetID() != g2.GetID())
                                    {
                                        baby = Crossover(g1, g2);
                                    }

                                    /*Because the number of individuals in a species may be small and because only the
                                     * best 20% (default value) are retained to be parents, it is sometimes impossible (or
                                     * slow) to find a second genome to mate with. The code shown here tries five times to
                                     * find a different genome and then aborts.*/
                                }

                                else
                                {
                                    baby = g1;
                                }
                            }



                            ++this.NextGenomeID;

                            baby.SetID(this.NextGenomeID);

                            //now we have a spawned child lets mutate it! First there is the
                            //chance a neuron may be added
                            if (baby.GetNumNeurons() < NeuralNetworkParams.MaxPermittedNeurons)
                            {
                                baby.AddNeuron(NeuralNetworkParams.ChanceAddNode,
                                               Innovation,
                                               NeuralNetworkParams.NumTrysToFindOldLink);
                            }

                            ////now there's the chance a link may be added
                            baby.AddLink(NeuralNetworkParams.ChanceAddLink,
                                         NeuralNetworkParams.ChanceAddRecurrentLink,
                                         Innovation,
                                         NeuralNetworkParams.NumTrysToFindLoopedLink,
                                         NeuralNetworkParams.NumAddLinkAttempts);

                            //mutate the weights
                            baby.MutateWeights(NeuralNetworkParams.MutationRate,
                                               NeuralNetworkParams.ProbabilityWeightReplaced,
                                               NeuralNetworkParams.MaxWeightPerturbation);

                            baby.MutateActivationResponse(NeuralNetworkParams.ActivationMutationRate,
                                                          NeuralNetworkParams.MaxActivationPerturbation);
                        }

                        //sort the babies genes by their innovation numbers
                        baby.SortLinkGenes();

                        //add to new pop
                        NewPop[currentNewGenomeIndex] = baby;
                        currentNewGenomeIndex++;

                        ++NumSpawnedSoFar;

                        if (NumSpawnedSoFar == NeuralNetworkParams.UnityInstantiatedNumSweepers)
                        {
                            NumToSpawn = 0;
                        }
                    } //end while
                }     //end if
            }         //next species
             //Debug.Log("SPECIES COMPLETE");

            //if there is an underflow due to the rounding error and the amount
            //of offspring falls short of the population size additional children
            //need to be created and added to the new population. This is achieved
            //simply, by using tournament selection over the entire population.
            if (NumSpawnedSoFar < NeuralNetworkParams.UnityInstantiatedNumSweepers)
            {
                //calculate amount of additional children required
                int Rqd = NeuralNetworkParams.UnityInstantiatedNumSweepers - NumSpawnedSoFar;

                //grab them
                while (Rqd-- > 0)
                {
                    NewPop[currentNewGenomeIndex] = TournamentSelection(this.PopSize / 5);
                    currentNewGenomeIndex++;
                }
            }

            //Debug.Log("numspawned");

            //replace the current population with the new one
            // BUG HERE
            //this.Genomes = NewPop.ToArray();

            //create the new phenotypes
            List <NeuralNet> new_phenotypes = new List <NeuralNet>();

            for (int gen = 0; gen < this.Genomes.Length; ++gen)
            {
                //calculate max network depth
                int depth = CalculateNetDepth(this.Genomes[gen]);

                NeuralNet phenotype = this.Genomes[gen].CreatePhenotype(depth);

                new_phenotypes.Add(phenotype);
            }


            //Debug.Log("before gen counter");
            //increase generation counter
            ++this.Generation;

            return(new_phenotypes);
        }
 /// <summary>
 /// delete the neural network
 /// </summary>
 public void DeletePhenotype()
 {
     this.Phenotype = null;
 }