コード例 #1
0
ファイル: Genome.cs プロジェクト: polic72/NEAT-Tests
        /// <summary>
        /// Mutates the genome by creating a new connection.
        /// </summary>
        public void Mutate_Link()
        {
            for (int i = 0; i < NEAT.LINK_ATTEMPTS; ++i)
            {
                NodeGene nodeGene_a = Nodes.GetRandomElement();
                NodeGene nodeGene_b = Nodes.GetRandomElement();

                if (nodeGene_a.X == nodeGene_b.X)
                {
                    continue;
                }


                ConnectionGene connectionGene;

                if (nodeGene_a.X < nodeGene_b.X)
                {
                    connectionGene = new ConnectionGene(nodeGene_a, nodeGene_b, 0); //Temp innovation number.
                }
                else
                {
                    connectionGene = new ConnectionGene(nodeGene_b, nodeGene_a, 0); //Temp innovation number.
                }

                if (Connections.Contains(connectionGene))
                {
                    continue;
                }


                connectionGene        = NEAT.CreateConnection(connectionGene.From, connectionGene.To);
                connectionGene.Weight = NEAT.WEIGHT_RANDOM + (random.NextDouble() * 2 - 1);

                Connections.Add_Sorted_Gene(connectionGene);    //This needs to be sorted otherwise something breaks.

                return;
            }
        }
コード例 #2
0
ファイル: Genome.cs プロジェクト: polic72/NEAT-Tests
        /// <summary>
        /// Crosses over the two given Genomes.
        /// </summary>
        /// <param name="genome_1">The first Genome.</param>
        /// <param name="genome_2">The second Genome.</param>
        /// <param name="random">The random object to use when deciding genes.</param>
        /// <returns>The crossed-over Genome.</returns>
        public static Genome CrossOver(Genome genome_1, Genome genome_2, Random random)
        {
            if (genome_1.Connections.Size != 0 && genome_2.Connections.Size != 0)   //Fixes IndexOutOfRangeException.
            {
                if (genome_1.Connections[genome_1.Connections.Size - 1].InnovationNumber
                    < genome_2.Connections[genome_2.Connections.Size - 1].InnovationNumber)
                {
                    return(CrossOver(genome_2, genome_1, random));   //Handles excess properly.
                }
            }
            else
            {
                int first_size  = genome_1.Connections.Size;
                int second_size = genome_2.Connections.Size;

                if (first_size < second_size)
                {
                    return(CrossOver(genome_2, genome_1, random));   //Handles excess properly.
                }
            }


            Genome created_genome = genome_1.NEAT.CreateGenome();


            #region Connections

            int index_me   = 0;
            int index_them = 0;

            while (index_me < genome_1.Connections.Size && index_them < genome_2.Connections.Size)
            {
                ConnectionGene connectionGene_me   = genome_1.Connections[index_me];
                ConnectionGene connectionGene_them = genome_2.Connections[index_them];

                int inNum_me   = connectionGene_me.InnovationNumber;
                int inNum_them = connectionGene_them.InnovationNumber;


                if (inNum_me == inNum_them) //Similar genes, choose either side at random.
                {
                    index_me++;
                    index_them++;

                    if (random.NextDouble() < .5)
                    {
                        created_genome.Connections.Add(NEAT.CopyConnectionGene(connectionGene_me));
                    }
                    else
                    {
                        created_genome.Connections.Add(NEAT.CopyConnectionGene(connectionGene_them));
                    }
                }
                else if (inNum_me > inNum_them) //Disjoint gene at them, increase them.
                {
                    index_them++;

                    //This is hotly debated, but will still work without this.
                    //created_genome.Connections.Add(NEAT.CopyConnectionGene(connectionGene_them));
                }
                else    //Disjoint gene at me, increase me.
                {
                    index_me++;

                    created_genome.Connections.Add(NEAT.CopyConnectionGene(connectionGene_me));
                }
            }


            //This is why this genome must have the higher innovation number.
            while (index_me < genome_1.Connections.Size)    //Run through the excess connections and add them all.
            {
                created_genome.Connections.Add(NEAT.CopyConnectionGene(genome_1.Connections[index_me++]));
            }

            #endregion Connections


            #region Nodes

            //foreach (ConnectionGene connectionGene in created_genome.Connections)
            //TODO implement foreach functionality into RandomHashSet

            for (int i = 0; i < created_genome.Connections.Size; ++i)
            {
                ConnectionGene connectionGene = created_genome.Connections[i];

                created_genome.Nodes.Add(connectionGene.From);  //Finally making use of the uniqness in RandomHashSet.
                created_genome.Nodes.Add(connectionGene.To);
            }

            #endregion Nodes


            return(created_genome);
        }
コード例 #3
0
ファイル: Genome.cs プロジェクト: polic72/NEAT-Tests
        /// <summary>
        /// Gets the distance between this Genome and the given Genome. Higher = less compatible.
        /// </summary>
        /// <param name="genome">The Genome to compare to.</param>
        /// <returns>The distance between this Genome and the given Genome.</returns>
        /// <remarks>
        /// The distance d can be measured by the following equation:
        /// <para/>
        /// d = c1(E / N) + c2(D / N) + c3 * W
        /// <para/>
        /// Where:
        ///     d = distance
        ///     E = # excess genes
        ///     D = # of disjoint genes
        ///     W = weight difference of similar genes
        ///     N = # of genes in largest genome (this or them), 1 if #genes &lt; 20
        ///     c_ = constant for adjusting
        /// </remarks>
        public double Distance(Genome genome)
        {
            if (Connections.Size != 0 && genome.Connections.Size != 0)  //Fixes IndexOutOfRangeException.
            {
                if (Connections[Connections.Size - 1].InnovationNumber
                    < genome.Connections[genome.Connections.Size - 1].InnovationNumber)
                {
                    return(genome.Distance(this));   //Handles excess properly.
                }
            }
            else
            {
                int my_size    = Connections.Size;
                int their_size = genome.Connections.Size;

                if (my_size < their_size)
                {
                    return(genome.Distance(this));   //Handles excess properly.
                }
            }


            int index_me   = 0;
            int index_them = 0;


            int num_excess   = 0;   //The number of excess genes.
            int num_disjoint = 0;   //The number of disjoint genes.

            double weight_diff = 0; //The weight difference between similar genes.
            double num_similar = 0; //The number of genes that are similar.


            bool was_skipped = true;    //The band-aid.

            while (index_me < Connections.Size && index_them < genome.Connections.Size)
            {
                was_skipped = false;

                ConnectionGene connectionGene_me   = Connections[index_me];
                ConnectionGene connectionGene_them = genome.Connections[index_them];

                int inNum_me   = connectionGene_me.InnovationNumber;
                int inNum_them = connectionGene_them.InnovationNumber;


                if (inNum_me == inNum_them) //Similar genes.
                {
                    index_me++;
                    index_them++;

                    num_similar++;
                    weight_diff += Math.Abs(connectionGene_me.Weight - connectionGene_them.Weight);
                }
                else if (inNum_me > inNum_them) //Disjoint gene at them, increase them.
                {
                    index_them++;

                    num_disjoint++;
                }
                else    //Disjoint gene at me, increase me.
                {
                    index_me++;

                    num_disjoint++;
                }
            }


            //This is why this genome must have the higher innovation number.
            num_excess = Connections.Size - index_me;


            if (was_skipped)
            {
                return(0);
            }


            weight_diff /= num_similar;


            double N = Math.Max(Connections.Size, genome.Connections.Size);

            N = (N < 20) ? 1 : N;


            return(NEAT.C1 * (num_excess / N) + NEAT.C2 * (num_disjoint / N) + (NEAT.C3 * weight_diff));
        }