예제 #1
0
        /// <summary>
        /// Constructs a connection gene with the given weight and enabled.
        /// </summary>
        /// <param name="connectionGenePattern">The connection gene pattern that this connection gene implements.</param>
        /// <param name="weight">The weight of the connection.</param>
        /// <param name="enabled">Whether or not this connection is enabled.</param>
        /// <exception cref="ArgumentNullException">When the connection gene pattern is null.</exception>
        protected internal ConnectionGene(ConnectionGenePattern connectionGenePattern, double weight, bool enabled)
        {
            Helpers.ThrowOnNull(connectionGenePattern, "connectionGenePattern");


            ConnectionGenePattern = connectionGenePattern;

            Weight  = weight;
            Enabled = enabled;
        }
예제 #2
0
 /// <summary>
 /// Gets the hash code of this connection gene. Is the ConnectionGenePattern hash code as well.
 /// </summary>
 /// <returns>The hash code.</returns>
 public override int GetHashCode()
 {
     return(ConnectionGenePattern.GetHashCode());
 }
예제 #3
0
 /// <summary>
 /// Constructs a connection gene with and enabled (true), and the given weight.
 /// </summary>
 /// <param name="connectionGenePattern">The connection gene pattern that this connection gene implements.</param>
 /// <param name="weight">The weight of the connection.</param>
 /// <exception cref="ArgumentNullException">When the connection gene pattern is null.</exception>
 protected internal ConnectionGene(ConnectionGenePattern connectionGenePattern, double weight)
     : this(connectionGenePattern, weight, true)
 {
 }
예제 #4
0
 /// <summary>
 /// String representation of this connection gene.
 /// </summary>
 /// <returns>String representation of this connection gene.</returns>
 public override string ToString()
 {
     return(ConnectionGenePattern.ToString() + ", Weight: " + Weight.ToString() + ", Enabled: " + Enabled.ToString());
 }
예제 #5
0
        /// <summary>
        /// Crosses over this genome with the given genome.
        /// </summary>
        /// <param name="my_score">Score of this genome. See remarks.</param>
        /// <param name="genome">The genome to cross over with.</param>
        /// <param name="their_score">Score of the given genome. See remarks.</param>
        /// <param name="random">The random object for the created genome.</param>
        /// <returns>The crossed-over genome.</returns>
        /// <remarks>
        /// When the given scores are equal, use the following rules:
        /// <list type="bullet">
        /// <item>On similar connection genes: See <see cref="NEAT.Genetic.Tracker.Pedigree.UniformCrossover"/>.</item>
        /// <item>On disjoint connection genes: Adds all to the created genome.</item>
        /// <item>On excess connection genes: Adds all to the created genome.</item>
        /// </list>
        ///
        /// When the given scores are not equal, use the following rules:
        /// <list type="bullet">
        /// <item>On similar connection genes: See <see cref="NEAT.Genetic.Tracker.Pedigree.UniformCrossover"/>.</item>
        /// <item>On disjoint connection genes: Adds genes from parent with higher score.</item>
        /// <item>On excess connection genes: Adds genes from parent with higher score.</item>
        /// </list>
        /// </remarks>
        /// <exception cref="ArgumentNullException">When the genome or random is null.</exception>
        public Genome Crossover(double my_score, Genome genome, double their_score, Random random)
        {
            Helpers.ThrowOnNull(genome, "genome");
            Helpers.ThrowOnNull(random, "random");


            Genome created_genome = new Genome(Pedigree, random);


            #region ConnectionGenes

            SortedDictionary <int, ConnectionGene> .ValueCollection.Enumerator enumerator_me   = ConnectionGenes.Values.GetEnumerator();
            SortedDictionary <int, ConnectionGene> .ValueCollection.Enumerator enumerator_them = genome.ConnectionGenes.Values.GetEnumerator();

            enumerator_me.MoveNext();   //Preps for first current.
            enumerator_them.MoveNext();


            //Step through both genomes and cross them over randomly.
            while (enumerator_me.Current != null && enumerator_them.Current != null)
            {
                ConnectionGene connectionGene_me   = enumerator_me.Current;
                ConnectionGene connectionGene_them = enumerator_them.Current;

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


                if (inNum_me == inNum_them) //Similar genes, choose either side at random.
                {
                    enumerator_me.MoveNext();
                    enumerator_them.MoveNext();

                    if (Pedigree.UniformCrossover)
                    {
                        if (random.NextDouble() < .5)
                        {
                            created_genome.ConnectionGenes.Add(inNum_me, Pedigree.Copy_ConnectionGene(connectionGene_me));
                        }
                        else
                        {
                            created_genome.ConnectionGenes.Add(inNum_them, Pedigree.Copy_ConnectionGene(connectionGene_them));
                        }
                    }
                    else
                    {
                        created_genome.ConnectionGenes.Add(inNum_me, Pedigree.Create_ConnectionGene(connectionGene_me.ConnectionGenePattern,
                                                                                                    (connectionGene_me.Weight + connectionGene_them.Weight) / 2,
                                                                                                    (random.NextDouble() < .5) ? connectionGene_me.Enabled : connectionGene_them.Enabled));
                    }
                }
                else if (inNum_me > inNum_them) //Disjoint gene at them, add this gene if allowed.
                {
                    enumerator_them.MoveNext();

                    if (Math.Abs(my_score - their_score) < Pedigree.Crossover_ScoreDelta || their_score > my_score)
                    {
                        created_genome.ConnectionGenes.Add(inNum_them, Pedigree.Copy_ConnectionGene(connectionGene_them));
                    }
                }
                else    //Disjoint gene at me, add this gene if allowed.
                {
                    enumerator_me.MoveNext();

                    if (Math.Abs(my_score - their_score) < Pedigree.Crossover_ScoreDelta || my_score > their_score)
                    {
                        created_genome.ConnectionGenes.Add(inNum_me, Pedigree.Copy_ConnectionGene(connectionGene_me));
                    }
                }
            }


            //Run through the excess connections and add them all if allowed.
            if (enumerator_me.Current != null)                                                                  //We have leftover genes, add ours if allowed.
            {
                if (Math.Abs(my_score - their_score) < Pedigree.Crossover_ScoreDelta || my_score > their_score) //Check legality.
                {
                    do
                    {
                        created_genome.ConnectionGenes.Add(enumerator_me.Current.ConnectionGenePattern.InnovationNumber,
                                                           Pedigree.Copy_ConnectionGene(enumerator_me.Current));
                    }while (enumerator_me.MoveNext());
                }
            }
            else if (enumerator_them.Current != null)                                                           //They have leftover genes, add theirs if allowed.
            {
                if (Math.Abs(my_score - their_score) < Pedigree.Crossover_ScoreDelta || their_score > my_score) //Check legality.
                {
                    do
                    {
                        created_genome.ConnectionGenes.Add(enumerator_them.Current.ConnectionGenePattern.InnovationNumber,
                                                           Pedigree.Copy_ConnectionGene(enumerator_them.Current));
                    }while (enumerator_them.MoveNext());
                }
            }
            //There is no else because if they have the same number of genes, there is no excess, so don't do anything.

            #endregion ConnectionGenes


            #region NodeGenes

            //Input/Output nodes and bias node.
            for (int i = 1; i <= Pedigree.Num_InputNodes + Pedigree.Num_OutputNodes + 1; ++i)   //The +1 handles the bias node.
            {
                created_genome.NodeGenes.Add(i, NodeGenes[i]);
            }


            //Every other relavent node.
            foreach (ConnectionGene connectionGene in created_genome.ConnectionGenes.Values)
            {
                ConnectionGenePattern pattern = connectionGene.ConnectionGenePattern;

                if (!created_genome.NodeGenes.ContainsKey(pattern.From.InnovationNumber))
                {
                    NodeGene nodeGene_toCopy;

                    try
                    {
                        nodeGene_toCopy = NodeGenes[pattern.From.InnovationNumber];
                    }
                    catch (KeyNotFoundException)
                    {
                        nodeGene_toCopy = genome.NodeGenes[pattern.From.InnovationNumber];
                    }

                    created_genome.NodeGenes.Add(pattern.From.InnovationNumber, Pedigree.Copy_NodeGene(nodeGene_toCopy));
                }

                if (!created_genome.NodeGenes.ContainsKey(pattern.To.InnovationNumber))
                {
                    NodeGene nodeGene_toCopy;

                    try
                    {
                        nodeGene_toCopy = NodeGenes[pattern.To.InnovationNumber];
                    }
                    catch (KeyNotFoundException)
                    {
                        nodeGene_toCopy = genome.NodeGenes[pattern.To.InnovationNumber];
                    }

                    created_genome.NodeGenes.Add(pattern.To.InnovationNumber, Pedigree.Copy_NodeGene(nodeGene_toCopy));
                }
            }

            #endregion NodeGenes


            return(created_genome);
        }