예제 #1
0
        /// <summary>
        /// Construct a genome, do not provide links and neurons.
        /// </summary>
        ///
        /// <param name="id">The genome id.</param>
        /// <param name="inputCount_0">The input count.</param>
        /// <param name="outputCount_1">The output count.</param>
        public NEATGenome(long id, int inputCount_0, int outputCount_1)
        {
            GenomeID      = id;
            AdjustedScore = 0;
            inputCount    = inputCount_0;
            outputCount   = outputCount_1;
            AmountToSpawn = 0;
            speciesID     = 0;

            double inputRowSlice = 0.8d / (inputCount_0);

            neuronsChromosome = new Chromosome();
            linksChromosome   = new Chromosome();

            Chromosomes.Add(neuronsChromosome);
            Chromosomes.Add(linksChromosome);

            for (int i = 0; i < inputCount_0; i++)
            {
                neuronsChromosome.Add(new NEATNeuronGene(NEATNeuronType.Input,
                                                         i, 0, 0.1d + i * inputRowSlice));
            }

            neuronsChromosome.Add(new NEATNeuronGene(NEATNeuronType.Bias,
                                                     inputCount_0, 0, 0.9d));

            double outputRowSlice = 1 / (double)(outputCount_1 + 1);

            for (int i_2 = 0; i_2 < outputCount_1; i_2++)
            {
                neuronsChromosome.Add(new NEATNeuronGene(
                                          NEATNeuronType.Output, i_2 + inputCount_0 + 1, 1, (i_2 + 1)
                                          * outputRowSlice));
            }

            for (int i_3 = 0; i_3 < inputCount_0 + 1; i_3++)
            {
                for (int j = 0; j < outputCount_1; j++)
                {
                    linksChromosome.Add(new NEATLinkGene(
                                            ((NEATNeuronGene)neuronsChromosome.Get(i_3)).Id,
                                            ((NEATNeuronGene)Neurons.Get(
                                                 inputCount_0 + j + 1)).Id, true, inputCount_0
                                            + outputCount_1 + 1 + NumGenes,
                                            RangeRandomizer.Randomize(-1, 1), false));
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Mutate the genome by adding a neuron.
        /// </summary>
        ///
        /// <param name="mutationRate">The mutation rate.</param>
        /// <param name="numTrysToFindOldLink">The number of tries to find a link to split.</param>
        internal void AddNeuron(double mutationRate, int numTrysToFindOldLink)
        {
            // should we add a neuron?
            if (ThreadSafeRandom.NextDouble() > mutationRate)
            {
                return;
            }

            int countTrysToFindOldLink = numTrysToFindOldLink;

            // the link to split
            NEATLinkGene splitLink = null;

            int sizeBias = inputCount + outputCount + 10;

            // if there are not at least
            int upperLimit;

            if (linksChromosome.Size() < sizeBias)
            {
                upperLimit = NumGenes - 1 - (int)Math.Sqrt(NumGenes);
            }
            else
            {
                upperLimit = NumGenes - 1;
            }

            while ((countTrysToFindOldLink--) > 0)
            {
                // choose a link, use the square root to prefer the older links
                int i    = RangeRandomizer.RandomInt(0, upperLimit);
                var link = (NEATLinkGene)linksChromosome
                           .Get(i);

                // get the from neuron
                long fromNeuron = link.FromNeuronID;

                if ((link.Enabled) &&
                    (!link.Recurrent) &&
                    (((NEATNeuronGene)Neurons.Get(
                          GetElementPos(fromNeuron))).NeuronType != NEATNeuronType.Bias))
                {
                    splitLink = link;
                    break;
                }
            }

            if (splitLink == null)
            {
                return;
            }

            splitLink.Enabled = false;

            double originalWeight = splitLink.Weight;

            long from = splitLink.FromNeuronID;
            long to   = splitLink.ToNeuronID;

            var fromGene = (NEATNeuronGene)Neurons.Get(
                GetElementPos(from));
            var toGene = (NEATNeuronGene)Neurons.Get(
                GetElementPos(to));

            double newDepth = (fromGene.SplitY + toGene.SplitY) / 2;
            double newWidth = (fromGene.SplitX + toGene.SplitX) / 2;

            // has this innovation already been tried?
            NEATInnovation innovation = ((NEATTraining)GA).Innovations.CheckInnovation(from, to,
                                                                                       NEATInnovationType
                                                                                       .NewNeuron);

            // prevent chaining
            if (innovation != null)
            {
                long neuronID = innovation.NeuronID;

                if (AlreadyHaveThisNeuronID(neuronID))
                {
                    innovation = null;
                }
            }

            if (innovation == null)
            {
                // this innovation has not been tried, create it
                long newNeuronID = ((NEATTraining)GA).Innovations.CreateNewInnovation(from, to,
                                                                                      NEATInnovationType.
                                                                                      NewNeuron,
                                                                                      NEATNeuronType.
                                                                                      Hidden,
                                                                                      newWidth, newDepth);

                neuronsChromosome.Add(new NEATNeuronGene(
                                          NEATNeuronType.Hidden, newNeuronID, newDepth, newWidth));

                // add the first link
                long link1ID = (GA).Population.AssignInnovationID();

                ((NEATTraining)GA).Innovations
                .CreateNewInnovation(from, newNeuronID,
                                     NEATInnovationType.NewLink);

                var link1 = new NEATLinkGene(from, newNeuronID,
                                             true, link1ID, 1.0d, false);

                linksChromosome.Add(link1);

                // add the second link
                long link2ID = (GA).Population.AssignInnovationID();

                ((NEATTraining)GA).Innovations
                .CreateNewInnovation(newNeuronID, to,
                                     NEATInnovationType.NewLink);

                var link2 = new NEATLinkGene(newNeuronID, to, true,
                                             link2ID, originalWeight, false);

                linksChromosome.Add(link2);
            }

            else
            {
                // existing innovation
                long newNeuronID_0 = innovation.NeuronID;

                NEATInnovation innovationLink1 = ((NEATTraining)GA).Innovations.CheckInnovation(from,
                                                                                                newNeuronID_0,
                                                                                                NEATInnovationType
                                                                                                .
                                                                                                NewLink);
                NEATInnovation innovationLink2 =
                    ((NEATTraining)GA).Innovations.CheckInnovation(newNeuronID_0, to,
                                                                   NEATInnovationType.NewLink);

                if ((innovationLink1 == null) || (innovationLink2 == null))
                {
                    throw new NeuralNetworkError("NEAT Error");
                }

                var link1_1 = new NEATLinkGene(from, newNeuronID_0,
                                               true, innovationLink1.InnovationID, 1.0d, false);
                var link2_2 = new NEATLinkGene(newNeuronID_0, to, true,
                                               innovationLink2.InnovationID, originalWeight, false);

                linksChromosome.Add(link1_1);
                linksChromosome.Add(link2_2);

                var newNeuron = new NEATNeuronGene(
                    NEATNeuronType.Hidden, newNeuronID_0, newDepth, newWidth);

                neuronsChromosome.Add(newNeuron);
            }

            return;
        }