예제 #1
0
 private void InitInnovation(Genome basicGenome)
 {
     if (basicGenome.ConnectionGenes.Count > 0)
     {
         Innovation.SetCurrentID(basicGenome.ConnectionGenes[basicGenome.ConnectionGenes.Count - 1].Innovation);
     }
     else
     {
         Innovation.SetCurrentID(0);
     }
 }
예제 #2
0
        // Mutation that creates new node in the genome.
        public void AddNodeMutation(List <Innovation> innovations)
        {
            if (innovations == null)
            {
                throw new ArgumentNullException(nameof(innovations));
            }

            // If there are no genes at all, return
            if (connectionGenes.Count == 0)
            {
                return;
            }

            bool found           = false;
            int  connectionIndex = -1;

            found = this.FindConnectionGeneToSplit(out connectionIndex);

            // We haven't found any proper gene to split, so exit
            if (!found)
            {
                return;
            }

            ConnectionGene oldConnection = this.connectionGenes[connectionIndex];

            oldConnection.IsEnabled = false;

            // Check if this is new innovation, or whether it already exists somewhere in the population
            bool           innovationFound = false;
            Node           newNode         = null;
            ConnectionGene newGene1        = null;
            ConnectionGene newGene2        = null;

            foreach (Innovation innov in innovations)
            {
                if (innov.InnovationType == Innovation.EInnovationType.NEWNODE &&
                    innov.InNode.ID == oldConnection.InNodeGene.ID &&
                    innov.OutNode.ID == oldConnection.OutNodeGene.ID &&
                    oldConnection.Innovation == innov.OldID)
                {
                    innovationFound = true;

                    newNode = new Node(Node.ENodeType.HIDDEN, innov.NewNode.ID);

                    newGene1 = new ConnectionGene(oldConnection.InNodeGene, newNode, oldConnection.IsRecurrent, 1.0f, true, innov.ID);
                    newGene2 = new ConnectionGene(newNode, oldConnection.OutNodeGene, false, oldConnection.Weight, true, innov.ID2);

                    break;
                }
            }

            // Create new hidden node between old nodes and link it with the network
            if (!innovationFound)
            {
                newNode = new Node(Node.ENodeType.HIDDEN, this.nodes.Count + 1);
                int id1 = Innovation.GetNextID();
                int id2 = Innovation.GetNextID();

                Innovation newInnov = new Innovation(Innovation.EInnovationType.NEWNODE, oldConnection.InNodeGene, oldConnection.OutNodeGene, newNode, id1, id2, 0.0f, oldConnection.Innovation);
                innovations.Add(newInnov);

                newGene1 = new ConnectionGene(oldConnection.InNodeGene, newNode, oldConnection.IsRecurrent, 1.0f, true, id1);
                newGene2 = new ConnectionGene(newNode, oldConnection.OutNodeGene, false, oldConnection.Weight, true, id2);
            }

            this.AddNode(newNode);
            this.AddConnectionGene(newGene1);
            this.AddConnectionGene(newGene2);

            this.phenotypeChanged = true;
        }
예제 #3
0
        // Mutation that creates new connection between 2 nodes.
        public void AddConnectionMutation(List <Innovation> innovations)
        {
            if (innovations == null)
            {
                throw new ArgumentNullException(nameof(innovations));
            }

            // Find first non-sensor node, so the target is never a sensor
            int minTargetNode = this.FindFirstNonInputNode();

            bool doRecurrency = this.random.NextDouble() < this.ParentSimulation.Parameters.RecurrencyProbability;
            bool recurFlag = false;
            bool found = false;
            Node node1 = null, node2 = null;

            if (doRecurrency)
            {
                int counter = 0;
                while (counter++ < maxTries && !found)
                {
                    bool recurrentLoop = this.random.NextDouble() > 0.5;

                    int startNode  = this.random.Next(0, this.nodes.Count);
                    int targetNode = recurrentLoop ? startNode : this.random.Next(minTargetNode, this.nodes.Count);


                    // Check if connection exists between the nodes
                    int i = 0;
                    node1 = this.nodes[startNode];
                    node2 = this.nodes[targetNode];
                    for (i = 0; i < this.connectionGenes.Count; ++i)
                    {
                        if ((node2.NodeType == Node.ENodeType.SENSOR || node2.NodeType == Node.ENodeType.BIAS) ||
                            (connectionGenes[i].InNodeGene.ID == node1.ID && connectionGenes[i].OutNodeGene.ID == node2.ID && connectionGenes[i].IsRecurrent))
                        {
                            break;
                        }
                    }
                    if (i == this.connectionGenes.Count)
                    {
                        recurFlag = this.IsRecurrentConnectioBetweenNodes(node1, node2);

                        if (!recurFlag)
                        {
                            continue;
                        }
                        else
                        {
                            found = true;
                        }
                    }
                }
            }
            else
            {
                int counter = 0;
                while (counter++ < maxTries && !found)
                {
                    int startNode  = this.random.Next(0, this.nodes.Count);
                    int targetNode = this.random.Next(minTargetNode, this.nodes.Count);

                    if (startNode != targetNode)
                    {
                        // Check if connection exists between the nodes
                        int i = 0;
                        node1 = this.nodes[startNode];
                        // Don't allow recurrencies for now
                        if (node1.NodeType == Node.ENodeType.OUTPUT)
                        {
                            continue;
                        }
                        node2 = this.nodes[targetNode];
                        for (i = 0; i < this.connectionGenes.Count; ++i)
                        {
                            if (connectionGenes[i].InNodeGene.ID == node1.ID && connectionGenes[i].OutNodeGene.ID == node2.ID && !connectionGenes[i].IsRecurrent)
                            {
                                break;
                            }
                        }
                        if (i == this.connectionGenes.Count)
                        {
                            recurFlag = this.IsRecurrentConnectioBetweenNodes(node1, node2);

                            if (recurFlag)
                            {
                                continue;
                            }
                            else
                            {
                                found = true;
                            }
                        }
                    }
                }
            }

            // Check if this is new innovation, or if it already existed somewhere in the population
            if (found)
            {
                if (doRecurrency)
                {
                    recurFlag = true;
                }

                bool           innovationFound = false;
                ConnectionGene newGene         = null;
                foreach (Innovation innov in innovations)
                {
                    if (innov.InnovationType == Innovation.EInnovationType.NEWLINK && innov.InNode.ID == node1.ID && innov.OutNode.ID == node2.ID)
                    {
                        innovationFound = true;
                        newGene         = new ConnectionGene(innov.InNode, innov.OutNode, recurFlag, innov.Weight, true, innov.ID);
                        break;
                    }
                }

                // This is completely new innovation
                if (!innovationFound)
                {
                    float      newRandomWeight = (float)(this.random.NextDouble() * 2.0f - 1.0f);
                    Innovation newInnov        = new Innovation(Innovation.EInnovationType.NEWLINK, node1, node2, null, Innovation.GetNextID(), 0, newRandomWeight, 0);
                    innovations.Add(newInnov);

                    newGene = new ConnectionGene(node1, node2, recurFlag, newRandomWeight, true, newInnov.ID);
                }

                this.AddConnectionGene(newGene);

                this.phenotypeChanged = true;
            }
        }