Beispiel #1
0
 /// <summary>
 /// This constructor copys a gene and then updates the inputs and outputs
 /// </summary>
 /// <param name="gene"></param>
 private Gene(Gene gene)
 {
     NodeInput = gene.NodeInput;
     NodeOutput = gene.NodeOutput;
     ConnectionEnabled = gene.ConnectionEnabled;
     ConnectionWeight = gene.ConnectionWeight;
     InnovationNumber = gene.InnovationNumber;
 }
Beispiel #2
0
        /// <summary>
        /// This method adds a single new node as a mutation and handles a connection 'split'.
        /// </summary>
        private void MutateAddNode()
        {
            // Find an available connection to modify
            // Get the list of available genes to mutate
            Gene[] availableGeneArray = Genes.Where(item => item.ConnectionEnabled).ToArray();
            if (availableGeneArray.Count() == 0)
                return;
            Gene oldGene = availableGeneArray[rng.Next(availableGeneArray.Count())];

            // Create a new node (find the maximum node value and add it)
            int newNodeIndex = Math.Max(Genes.Select(g => g.NodeInput).Union(Genes.Select(g => g.NodeOutput)).Max(), evoConfig.InputNodeCount + evoConfig.OutputNodeCount) + 1;

            // Add a new start value if it does not yet exist
            if (!startValues.ContainsKey(newNodeIndex))
                startValues.Add(newNodeIndex, 2 - evoConfig.rng.NextDouble() * 4);

            // First gene (connection) copys the original, but is given an new innovation number
            Gene g1 = (Gene) oldGene.Clone();
            g1.NodeOutput = newNodeIndex;
            g1.InnovationNumber = Innovation.NewInnovationNumber;

            // Second connection is treated as a passthrough (with a sigmoid function)
            Gene g2 = new Gene(evoConfig, newNodeIndex, oldGene.NodeOutput);

            // Disable the oldGene
            oldGene.ConnectionEnabled = false;

            // Add new genes to the list
            Genes.Add(g1);
            Genes.Add(g2);
        }
Beispiel #3
0
        /// <summary>
        /// This method adds a single new gene (connection) as a mutation.
        /// </summary>
        private void MutateAddGene(bool biasOnly = false)
        {
            IEnumerable<int> allNodes = Genes.Select(g => g.NodeInput)
                .Union(
                    Genes.Select(g => g.NodeOutput))
                    .Distinct()
                    .Where(n => !(NeuralNetwork.IsInputOutputNode(evoConfig, n)));
            List<int> availableInputNodeList = allNodes.Union(Enumerable.Range(0, evoConfig.InputNodeCount + 1)).ToList();
            List<int> availableOutputNodeList = allNodes.Union(Enumerable.Range(evoConfig.InputNodeCount + 1, evoConfig.OutputNodeCount)).ToList();

            // Select a Node
            int n1 = (biasOnly) ? evoConfig.InputNodeCount : availableInputNodeList[rng.Next(availableInputNodeList.Count())];

            // Remove this node from the list
            if (availableOutputNodeList.Contains(n1))
                availableOutputNodeList.Remove(n1);

            // Select a Node After
            int n2 = availableOutputNodeList[rng.Next(availableOutputNodeList.Count())];

            // Create new gene
            Gene newGene = new Gene(evoConfig, n1, n2);
            newGene.ConnectionWeight = 2 - evoConfig.rng.NextDouble() * 4;

            // Insert new gene
            Genes.Add(newGene);
        }