/// <summary>
        /// Get a list of the genes that have not been taken before. This is useful
        /// if you do not wish the same gene to appear more than once in a
        /// chromosome.
        /// </summary>
        /// <param name="source">The pool of genes to select from.</param>
        /// <param name="taken">An array of the taken genes.</param>
        /// <returns>Those genes in source that are not taken.</returns>
        private static IGene GetNotTaken(Chromosome source,
                 IList<IGene> taken)
        {
            int geneLength = source.Genes.Count;

            for (int i = 0; i < geneLength; i++)
            {
                IGene trial = source.Genes[i];

                bool found = false;
                foreach (IGene current in taken)
                {
                    if (current.Equals(trial))
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    taken.Add(trial);
                    return trial;
                }
            }

            return null;
        }
        /// <summary>
        /// Construct an innovation list. 
        /// </summary>
        /// <param name="population">The population.</param>
        /// <param name="links">The links.</param>
        /// <param name="neurons">The neurons.</param>
        public NEATInnovationList(IPopulation population, Chromosome links, Chromosome neurons)
        {

            this.population = population;
            foreach (IGene gene in neurons.Genes)
            {
                NEATNeuronGene neuronGene = (NEATNeuronGene)gene;

                NEATInnovation innovation = new NEATInnovation(neuronGene,
                       population.AssignInnovationID(), AssignNeuronID());

                Innovations.Add(innovation);

            }

            foreach (IGene gene in links.Genes)
            {
                NEATLinkGene linkGene = (NEATLinkGene)gene;
                NEATInnovation innovation = new NEATInnovation(linkGene
                        .FromNeuronID, linkGene.ToNeuronID,
                        NEATInnovationType.NewLink, this.population.AssignInnovationID());
                Innovations.Add(innovation);

            }
        }
Exemple #3
0
        /// <summary>
        /// Assuming this chromosome is the "mother" mate with the passed in
        /// "father". 
        /// </summary>
        /// <param name="mother">The mother.</param>
        /// <param name="father">The father.</param>
        /// <param name="offspring1">The first offspring.</param>
        /// <param name="offspring2">The second offspring.</param>
        public void Mate(Chromosome mother, Chromosome father,
                 Chromosome offspring1, Chromosome offspring2)
        {
            int geneLength = mother.Genes.Count;

            // the chromosome must be cut at two positions, determine them
            int cutpoint1 = (int)(ThreadSafeRandom.NextDouble() * (geneLength - cutLength));
            int cutpoint2 = cutpoint1 + cutLength;

            // handle cut section
            for (int i = 0; i < geneLength; i++)
            {
                if (!((i < cutpoint1) || (i > cutpoint2)))
                {
                    offspring1.Genes[i].Copy(father.Genes[i]);
                    offspring2.Genes[i].Copy(mother.Genes[i]);
                }
            }

            // handle outer sections
            for (int i = 0; i < geneLength; i++)
            {
                if ((i < cutpoint1) || (i > cutpoint2))
                {
                    offspring1.Genes[i].Copy(mother.Genes[i]);
                    offspring2.Genes[i].Copy(father.Genes[i]);
                }
            }
        }
 /// <summary>
 /// Perform a perturb mutation on the specified chromosome.
 /// </summary>
 /// <param name="chromosome">The chromosome to mutate.</param>
 public void PerformMutation(Chromosome chromosome)
 {
     foreach (IGene gene in chromosome.Genes)
     {
         if (gene is DoubleGene)
         {
             DoubleGene doubleGene = (DoubleGene)gene;
             double value = doubleGene.Value;
             value += (perturbAmount - (ThreadSafeRandom.NextDouble()) * perturbAmount * 2);
             doubleGene.Value = value;
         }
     }
 }
        /// <summary>
        /// Construct a neural network genome.
        /// </summary>
        /// <param name="nga">The neural genetic algorithm.</param>
        /// <param name="network">The network.</param>
        public NeuralGenome(NeuralGeneticAlgorithm nga, BasicNetwork network)
            : base(nga.Helper)
        {
            this.Organism = network;
            this.networkChromosome = new Chromosome();

            // create an array of "double genes"
            int size = network.Structure.CalculateSize();
            for (int i = 0; i < size; i++)
            {
                IGene gene = new DoubleGene();
                this.networkChromosome.Genes.Add(gene);
            }

            this.Chromosomes.Add(this.networkChromosome);

            Encode();
        }
        /// <summary>
        /// Perform a shuffle mutation.
        /// </summary>
        /// <param name="chromosome">The chromosome to mutate.</param>
        public void PerformMutation(Chromosome chromosome)
        {
            int length = chromosome.Genes.Count;
            int iswap1 = (int)(ThreadSafeRandom.NextDouble() * length);
            int iswap2 = (int)(ThreadSafeRandom.NextDouble() * length);

            // can't be equal
            if (iswap1 == iswap2)
            {
                // move to the next, but
                // don't go out of bounds
                if (iswap1 > 0)
                {
                    iswap1--;
                }
                else
                {
                    iswap1++;
                }

            }

            // make sure they are in the right order
            if (iswap1 > iswap2)
            {
                int temp = iswap1;
                iswap1 = iswap2;
                iswap2 = temp;
            }

            IGene gene1 = chromosome.Genes[iswap1];
            IGene gene2 = chromosome.Genes[iswap2];

            // remove the two genes
            chromosome.Genes.Remove(gene1);
            chromosome.Genes.Remove(gene2);

            // insert them back in, reverse order
            chromosome.Genes.Insert(iswap1, gene2);
            chromosome.Genes.Insert(iswap2, gene1);
        }
        /// <summary>
        /// Construct a genome, do not provide links and neurons. 
        /// </summary>
        /// <param name="training">The owner object.</param>
        /// <param name="id">The genome id.</param>
        /// <param name="inputCount">The input count.</param>
        /// <param name="outputCount">The output count.</param>
        public NEATGenome(NEATTraining training, long id,
                int inputCount, int outputCount)
            : base(training)
        {

            GenomeID = id;
            AdjustedScore = 0;
            this.inputCount = inputCount;
            this.outputCount = outputCount;
            AmountToSpawn = 0;
            speciesID = 0;

            double inputRowSlice = 0.8 / (inputCount);
            neuronsChromosome = new Chromosome();
            linksChromosome = new Chromosome();

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

            neuronsChromosome.Genes.Add(new NEATNeuronGene(NEATNeuronType.Bias,
                    inputCount, 0, 0.9));

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

            for (int i = 0; i < outputCount; i++)
            {
                neuronsChromosome.Genes.Add(new NEATNeuronGene(NEATNeuronType.Output, i
                        + inputCount + 1, 1, (i + 1) * outputRowSlice));
            }

            for (int i = 0; i < inputCount + 1; i++)
            {
                for (int j = 0; j < outputCount; j++)
                {
                    linksChromosome.Genes.Add(new NEATLinkGene(
                            ((NEATNeuronGene)neuronsChromosome.Genes[i]).Id,
                            ((NEATNeuronGene)Neurons.Genes[inputCount + j + 1])
                                    .Id, true, inputCount + outputCount + 1
                                    + NumGenes, RangeRandomizer.Randomize(-1,
                                    1), false));
                }
            }

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

        }
        /// <summary>
        /// Create a NEAT gnome. 
        /// </summary>
        /// <param name="training">The owner object.</param>
        /// <param name="genomeID">The genome id.</param>
        /// <param name="neurons">The neurons.</param>
        /// <param name="links">The links.</param>
        /// <param name="inputCount">The input count.</param>
        /// <param name="outputCount">The output count.</param>
        public NEATGenome(NEATTraining training, long genomeID,
                Chromosome neurons, Chromosome links,
                int inputCount, int outputCount)
            : base(training)
        {
            GenomeID = genomeID;
            linksChromosome = links;
            neuronsChromosome = neurons;
            AmountToSpawn = 0;
            AdjustedScore = 0;
            this.inputCount = inputCount;
            this.outputCount = outputCount;

            this.Chromosomes.Add(neuronsChromosome);
            this.Chromosomes.Add(linksChromosome);
        }
        /// <summary>
        /// Construct a genome by copying another. 
        /// </summary>
        /// <param name="other">The other genome.</param>
        public NEATGenome(NEATGenome other)
            : base(other.GA)
        {

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

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

            GenomeID = other.GenomeID;
            networkDepth = other.networkDepth;
            Score = other.Score;
            AdjustedScore = other.AdjustedScore;
            AmountToSpawn = other.AmountToSpawn;
            inputCount = other.inputCount;
            outputCount = other.outputCount;
            speciesID = other.speciesID;

            // copy neurons
            foreach (IGene gene in other.Neurons.Genes)
            {
                NEATNeuronGene oldGene = (NEATNeuronGene)gene;
                NEATNeuronGene newGene = new NEATNeuronGene(oldGene.NeuronType
                   , oldGene.Id, oldGene.SplitX,
                       oldGene.SplitY, oldGene.Recurrent, oldGene
                               .ActivationResponse);
                this.neuronsChromosome.Genes.Add(newGene);
            }

            // copy links
            foreach (IGene gene in other.Links.Genes)
            {
                NEATLinkGene oldGene = (NEATLinkGene)gene;
                NEATLinkGene newGene = new NEATLinkGene(oldGene
                        .FromNeuronID, oldGene.ToNeuronID, oldGene
                        .Enabled, oldGene.InnovationId, oldGene
                        .Weight, oldGene.IsRecurrent);
                Links.Genes.Add(newGene);
            }

        }
        /// <summary>
        /// Assuming this chromosome is the "mother" mate with the passed in
        /// "father".
        /// </summary>
        /// <param name="mother">The mother.</param>
        /// <param name="father">The father.</param>
        /// <param name="offspring1">The first offspring.</param>
        /// <param name="offspring2">The second offspring.</param>
        public void Mate(Chromosome mother, Chromosome father,
                Chromosome offspring1, Chromosome offspring2)
        {
            int geneLength = father.Genes.Count;

            // the chromosome must be cut at two positions, determine them
            int cutpoint1 = (int)(ThreadSafeRandom.NextDouble() * (geneLength - cutLength));
            int cutpoint2 = cutpoint1 + cutLength;

            // keep track of which genes have been taken in each of the two
            // offspring, defaults to false.
            IList<IGene> taken1 = new List<IGene>();
            IList<IGene> taken2 = new List<IGene>();

            // handle cut section
            for (int i = 0; i < geneLength; i++)
            {
                if (!((i < cutpoint1) || (i > cutpoint2)))
                {
                    offspring1.Genes[i].Copy(father.Genes[i]);
                    offspring2.Genes[i].Copy(mother.Genes[i]);
                    taken1.Add(offspring1.Genes[i]);
                    taken2.Add(offspring2.Genes[i]);
                }
            }

            // handle outer sections
            for (int i = 0; i < geneLength; i++)
            {
                if ((i < cutpoint1) || (i > cutpoint2))
                {

                    offspring1.Genes[i].Copy(
                            SpliceNoRepeat.GetNotTaken(mother, taken1));
                    offspring2.Genes[i].Copy(
                            SpliceNoRepeat.GetNotTaken(father, taken2));

                }
            }
        }
        /// <summary>
        /// Perform the crossover. 
        /// </summary>
        /// <param name="mom">The mother.</param>
        /// <param name="dad">The father.</param>
        /// <returns>The child.</returns>
        public NEATGenome PerformCrossover(NEATGenome mom, NEATGenome dad)
        {
            NEATParent best;

            // first determine who is more fit, the mother or the father?
            if (mom.Score == dad.Score)
            {
                if (mom.NumGenes == dad.NumGenes)
                {
                    if (ThreadSafeRandom.NextDouble() > 0)
                    {
                        best = NEATParent.Mom;
                    }
                    else
                    {
                        best = NEATParent.Dad;
                    }
                }

                else
                {
                    if (mom.NumGenes < dad.NumGenes)
                    {
                        best = NEATParent.Mom;
                    }

                    else
                    {
                        best = NEATParent.Dad;
                    }
                }
            }

            else
            {
                if (Comparator.IsBetterThan(mom.Score, dad.Score))
                {
                    best = NEATParent.Mom;
                }

                else
                {
                    best = NEATParent.Dad;
                }
            }

            Chromosome babyNeurons = new Chromosome();
            Chromosome babyGenes = new Chromosome();

            List<long> vecNeurons = new List<long>();

            int curMom = 0;
            int curDad = 0;

            NEATLinkGene momGene;
            NEATLinkGene dadGene;

            NEATLinkGene selectedGene = null;

            while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
            {

                if (curMom < mom.NumGenes)
                {
                    momGene = (NEATLinkGene)mom.Links.Genes[curMom];
                }
                else
                {
                    momGene = null;
                }

                if (curDad < dad.NumGenes)
                {
                    dadGene = (NEATLinkGene)dad.Links.Genes[curDad];
                }
                else
                {
                    dadGene = null;
                }

                if ((momGene == null) && (dadGene != null))
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if ((dadGene == null) && (momGene != null))
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (momGene.InnovationId < dadGene.InnovationId)
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (dadGene.InnovationId < momGene.InnovationId)
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if (dadGene.InnovationId == momGene.InnovationId)
                {
                    if (ThreadSafeRandom.NextDouble() < 0.5f)
                    {
                        selectedGene = momGene;
                    }

                    else
                    {
                        selectedGene = dadGene;
                    }
                    curMom++;
                    curDad++;

                }

                if (babyGenes.Genes.Count == 0)
                {
                    babyGenes.Genes.Add(selectedGene);
                }

                else
                {
                    if (babyGenes.Genes[babyGenes.Genes.Count - 1]
                            .InnovationId != selectedGene.InnovationId)
                    {
                        babyGenes.Genes.Add(selectedGene);
                    }
                }

                // Check if we already have the nodes referred to in SelectedGene.
                // If not, they need to be added.
                AddNeuronID(selectedGene.FromNeuronID, vecNeurons);
                AddNeuronID(selectedGene.ToNeuronID, vecNeurons);

            }

            // now create the required nodes. First sort them into order
            vecNeurons.Sort();

            for (int i = 0; i < vecNeurons.Count; i++)
            {
                babyNeurons.Genes.Add(this.Innovations.CreateNeuronFromID(
                        vecNeurons[i]));
            }

            // finally, create the genome
            NEATGenome babyGenome = new NEATGenome(this, Population
                    .AssignGenomeID(), babyNeurons, babyGenes, mom.InputCount,
                    mom.OutputCount);

            return babyGenome;
        }