コード例 #1
0
        public void Mutate()
        {
            // When no genes, add gene mutation
            if (Connections.Count == 0)
            {
                AddConnection();
            }

            double chance = MyRand.UniformRnd(0, 1);

            // 80% chance to modify weight or bias
            if (chance < 0.8)
            {
                ModifyConnection();
            }

            chance = MyRand.UniformRnd(0, 1);
            // 8% chance to add new connection
            if (chance < 0.08)
            {
                AddConnection();
            }

            chance = MyRand.UniformRnd(0, 1);
            // 2% chance to add new node
            if (chance < 0.02)
            {
                AddNode();
            }

            // No mutations today
        }
コード例 #2
0
 /// <summary>
 /// Random uniform weight, and enabled
 /// </summary>
 /// <param name="node">The input node</param>
 public Connection(Node node)
 {
     INode   = node;
     Weight  = MyRand.UniformRnd(-1, 1);
     Bias    = MyRand.UniformRnd(-1, 1);
     Enabled = true;
     ONode   = null; // Output nodes are not necessary defined immediately
     InnovID = 0;    // It will be overwritten
 }
コード例 #3
0
        /// <summary>
        /// Adds a new player to the niche by crossover or cloning, could return null!
        /// </summary>
        public Player GetBaby()
        {
            // Need at least one player in this species
            if (Members.Count < 1)
            {
                return(null);
            }

            Player newPlayer = null;

            double chance = MyRand.UniformRnd(0, 1);

            // TODO opt. In this case it is unnecessary to decide which species should this belong
            // with 25% chance just clone a player || When we only have one member
            if (chance < 0.25 || Members.Count == 1)
            {
                int rndPlayer = MyRand.Next(0, Members.Count);
                newPlayer = Members[rndPlayer].DeepCopy();
                newPlayer.SetFitness(0);
                newPlayer.LifeSpawn = 0;
            }
            // Crossover 75% chance
            else
            {
                // We cant do crossover if there are less than 2 players
                if (Members.Count < 2)
                {
                    return(null);
                }

                Player parentA = null;
                Player parentB = null;
                do
                {
                    int rndPlayerNumb = MyRand.Next(0, Members.Count);
                    parentA       = Members[rndPlayerNumb];
                    rndPlayerNumb = MyRand.Next(0, Members.Count);
                    parentB       = Members[rndPlayerNumb];
                } while(parentA.ID == parentB.ID);

                if (parentA.Fitness > parentB.Fitness)
                {
                    newPlayer = parentA.Crossover(parentB);
                }
                else
                {
                    newPlayer = parentB.Crossover(parentA);
                }
            }

            return(newPlayer);
        }
コード例 #4
0
        // Crossover this and NetworkB where this is the better parent
        public Network Crossover(Network networkB)
        {
            // Create a child network, which is very similar to this network
            Network child = new Network(InputNodes,
                                        OutputNodes,
                                        OutputLayer,
                                        NodeCnt);

            // At first we should Add the nodes, but how to choose which nodes to add?
            // Chose the better parent which is this
            foreach (var nodeA in Nodes)
            {
                Node childN = nodeA.DeepCopy(nodeA.ID);
                // we will add the connections later
                childN.Connections.Clear();
                child.Nodes.Add(childN);
            }

            //Go through the genes, and decide how to use them
            foreach (var conA in Connections)
            {
                bool       enableGene = true;
                Connection gene       = null;

                //Check if both parents have this gene
                Connection conB = networkB.FindConnection(conA.InnovID);
                if (conB != null)
                {
                    //Both have this gene

                    //Check if it is disabled in any of the parent and with 75% chance
                    if ((!conA.Enabled || !conB.Enabled) &&
                        (MyRand.UniformRnd(0, 1) < Cfg.DisableUnnecessaryGene)
                        )
                    {
                        // These gene doesnt look necessary
                        enableGene = false;
                    }

                    //Decide who will give the gene
                    if (MyRand.UniformRnd(0, 1) < 0.50)
                    {
                        // Parent A
                        Node iNode = child.getNodeByID(conA.INode.ID);
                        Node oNode = child.getNodeByID(conA.ONode.ID);
                        gene = conA.DeepCopy(iNode, oNode);
                        iNode.Connections.Add(gene);
                    }
                    else
                    {
                        // Parent B
                        Node iNode = child.getNodeByID(conB.INode.ID);
                        Node oNode = child.getNodeByID(conB.ONode.ID);
                        gene = conB.DeepCopy(iNode, oNode);
                        iNode.Connections.Add(gene);
                    }
                }
                else
                {
                    //Only parentA has this gene, disjoint or excess gene
                    Node iNode = child.getNodeByID(conA.INode.ID);
                    Node oNode = child.getNodeByID(conA.ONode.ID);
                    gene = conA.DeepCopy(iNode, oNode);
                    iNode.Connections.Add(gene);
                }

                gene.Enabled = enableGene;
                child.Connections.Add(gene);
            }

            return(child);
        }
コード例 #5
0
        // Modify an existing connection, can also be turned Off or On
        public Result ModifyConnection()
        {
            // Check if we have connections or not
            if (Connections.Count == 0)
            {
                //Cannot Add new node
                return(Result.fail);
            }

            // Check if every connection is disabled, like in LoL
            bool allDisabled = true;

            foreach (var c in Connections)
            {
                if (c.Enabled)
                {
                    allDisabled = false;
                    break;
                }
            }
            if (allDisabled)
            {
                return(Result.fail);
            }

            // Select a connection which is not disabled
            Connection conn = null;

            do
            {
                int rndConNumb = MyRand.Next(0, Connections.Count);
                conn = Connections[rndConNumb];
            } while(!conn.Enabled);

            // Slightly modify this connection's weight or bias
            if (MyRand.UniformRnd(0, 1) > 0.3)
            {
                // Weight change
                conn.Weight = MyRand.NormalDist(conn.Weight, 0.1);
                // Not sure if limiting the weight is a good idea or not
                if (conn.Weight > 1.0)
                {
                    conn.Weight = 1.0;
                }
                if (conn.Weight < -1.0)
                {
                    conn.Weight = -1.0;
                }
            }
            else
            {
                // Bias change
                conn.Bias = MyRand.NormalDist(conn.Bias, 0.1);
                // Not sure if limiting the bias is a good idea or not
                if (conn.Bias > 5.0)
                {
                    conn.Bias = 5.0;
                }
                if (conn.Bias < -5.0)
                {
                    conn.Bias = -5.0;
                }
            }

            return(Result.success);
        }