/// <summary>
        /// and a neuron. This is used in the structural mutation of NEAT
        /// </summary>
        /// <param name="MutationRate"></param>
        /// <param name="innovation"></param>
        /// <param name="NumTrysToFindOldLink"></param>
        public void AddNeuron(double MutationRate, Innovation innovation, int NumTrysToFindOldLink)
        {
            //just return dependent on mutation rate
            if (RandomProvider.RandomFloat() > MutationRate)
            {
                return;
            }

            //if a valid link is found into which to insert the new neuron
            //this value is set to true.
            bool bDone = false;

            //this will hold the index into m_vecLinks of the chosen link gene
            int ChosenLink = 0;

            //first a link is chosen to split. If the genome is small the code makes
            //sure one of the older links is split to ensure a chaining effect does
            //not occur. Here, if the genome contains less than 5 hidden neurons it
            //is considered to be too small to select a link at random
            int SizeThreshold = this.NumberOfInputs + this.NumberOfOutputs + 5;

            if (this.Links.Count < SizeThreshold)
            {
                while (NumTrysToFindOldLink-- > 0)
                {
                    //choose a link with a bias towards the older links in the genome
                    ChosenLink = RandomProvider.RND.Next(0, GetNumGenes() - 1 - (int)Mathf.Sqrt(GetNumGenes()));

                    //make sure the link is enabled and that it is not a recurrent link
                    //or has a bias input
                    int FromNeuron = this.Links[ChosenLink].FromNeuron;

                    if ((this.Links[ChosenLink].Enabled) &&
                        (!this.Links[ChosenLink].Recurrent) &&
                        (this.Neurons[GetElementPosition(FromNeuron)].NeuronType != NeuronType.Bias))
                    {
                        bDone = true;

                        NumTrysToFindOldLink = 0;
                    }
                }

                if (!bDone)
                {
                    //failed to find a decent link
                    return;
                }
            }

            /*
             *  Early on in the development of the networks, a problem can occur where the same
             *  link is split repeatedly creating a chaining effect.
             *
             *  Obviously, this is undesirable, so the following code checks the number of neurons
             *  in the genome to see if the structure is below a certain size threshold. If it is, measures
             *  are taken to ensure that older links are selected in preference to newer ones.
             */
            else
            {
                int maxExitCounter = this.Links.Count + NeuralNetworkParams.NumTicks;
                int exitCounter    = 0;
                //the genome is of sufficient size for any link to be acceptable
                // 20.10.2015 also there is an exit counter to exit the loop if nothing is found in a certain amount of time. This can happen with very low ticks, the neural network gets to messed up. Reason unknown at the moment
                while (!bDone && exitCounter < maxExitCounter)
                {
                    ChosenLink = RandomProvider.RND.Next(0, GetNumGenes() - 1);

                    //make sure the link is enabled and that it is not a recurrent link
                    //or has a BIAS input
                    int FromNeuron = this.Links[ChosenLink].FromNeuron;

                    if ((this.Links[ChosenLink].Enabled) &&
                        (!this.Links[ChosenLink].Recurrent) &&
                        (this.Neurons[GetElementPosition(FromNeuron)].NeuronType != NeuronType.Bias))
                    {
                        bDone = true;
                    }

                    exitCounter++;
                }
                if (exitCounter >= maxExitCounter)
                {
                    Debug.Log("No proper links where found!");
                }
            }

            //disable this gene
            this.Links[ChosenLink].Enabled = false;

            //grab the weight from the gene (we want to use this for the weight of
            //one of the new links so that the split does not disturb anything the
            //NN may have already learned...
            double OriginalWeight = this.Links[ChosenLink].Weight;

            /*
             *  When a link is disabled and two new links are created, the old weight from the
             *  disabled link is used as the weight for one of the new links, and the weight for the
             *  other link is set to 1. In this way, the addition of a neuron creates as little disruption
             *  as possible to any existing learned behavior
             */

            //identify the neurons this link connects
            int from = this.Links[ChosenLink].FromNeuron;
            int to   = this.Links[ChosenLink].ToNeuron;

            //calculate the depth and width of the new neuron. We can use the depth
            //to see if the link feeds backwards or forwards
            double NewDepth = (this.Neurons[GetElementPosition(from)].SplitY +
                               this.Neurons[GetElementPosition(to)].SplitY) / 2;

            double NewWidth = (this.Neurons[GetElementPosition(from)].SplitX +
                               this.Neurons[GetElementPosition(to)].SplitX) / 2;

            //Now to see if this innovation has been created previously by
            //another member of the population
            int id = innovation.CheckInnovation(from,
                                                to,
                                                InnovationType.NewNeuron);



            /*it is possible for NEAT to repeatedly do the following:
             *
             *  1. Find a link. Lets say we choose link 1 to 5
             *  2. Disable the link,
             *  3. Add a new neuron and two new links
             *  4. The link disabled in Step 2 maybe re-enabled when this genome
             *     is recombined with a genome that has that link enabled.
             *  5  etc etc
             *
             * Therefore, this function must check to see if a neuron ID is already
             * being used. If it is then the function creates a new innovation
             * for the neuron. */


            if (id >= 0)
            {
                int NeuronID = innovation.GetNeuronID(id);

                if (AlreadyHaveThisNeuronID(NeuronID))
                {
                    id = -1;
                }
            }

            /*
             *  AlreadyHaveThisNeuronID returns true if (you guessed it) the genome already has a
             *  neuron with an identical ID. If this is the case, then a new innovation needs to be
             *  created, so id is reset to -1.
             */
            if (id < 0)
            {
                //add the innovation for the new neuron
                int NewNeuronID = innovation.CreateNewInnovation(from,
                                                                 to,
                                                                 InnovationType.NewNeuron,
                                                                 NeuronType.Hidden,
                                                                 NewWidth,
                                                                 NewDepth);

                //create the new neuron gene and add it.
                this.Neurons.Add(new NeuronGene(NeuronType.Hidden,
                                                NewNeuronID,
                                                NewDepth,
                                                NewWidth));

                //Two new link innovations are required, one for each of the
                //new links created when this gene is split.

                //-----------------------------------first link

                //get the next innovation ID
                int idLink1 = innovation.NextNumber();

                //create the new innovation
                innovation.CreateNewInnovation(from,
                                               NewNeuronID,
                                               InnovationType.NewLink);

                //create the new link gene
                LinkGene link1 = new LinkGene(from,
                                              NewNeuronID,
                                              true,
                                              idLink1,
                                              1.0);

                this.Links.Add(link1);

                //-----------------------------------second link

                //get the next innovation ID
                int idLink2 = innovation.NextNumber();

                //create the new innovation
                innovation.CreateNewInnovation(NewNeuronID,
                                               to,
                                               InnovationType.NewLink);

                //create the new gene
                LinkGene link2 = new LinkGene(NewNeuronID,
                                              to,
                                              true,
                                              idLink2,
                                              OriginalWeight);

                this.Links.Add(link2);
            }

            else
            {
                //this innovation has already been created so grab the relevant neuron
                //and link info from the innovation database
                int NewNeuronID = innovation.GetNeuronID(id);

                //get the innovation IDs for the two new link genes.
                int idLink1 = innovation.CheckInnovation(from, NewNeuronID, InnovationType.NewLink);
                int idLink2 = innovation.CheckInnovation(NewNeuronID, to, InnovationType.NewLink);

                //this should never happen because the innovations *should* have already
                //occurred
                if ((idLink1 < 0) || (idLink2 < 0))
                {
                    Debug.Log("Error in CGenome::AddNeuron, Problem!");

                    return;
                }

                //now we need to create 2 new genes to represent the new links
                LinkGene link1 = new LinkGene(from, NewNeuronID, true, idLink1, 1.0);
                LinkGene link2 = new LinkGene(NewNeuronID, to, true, idLink2, OriginalWeight);

                this.Links.Add(link1);
                this.Links.Add(link2);

                //create the new neuron
                NeuronGene NewNeuron = new NeuronGene(NeuronType.Hidden, NewNeuronID, NewDepth, NewWidth);

                //and add it
                this.Neurons.Add(NewNeuron);
            }

            return;
        }