Example #1
0
        /// <summary>
        /// Create a default minimal genome that describes a NN with the given number of inputs and outputs.
        /// </summary>
        /// <returns></returns>
        public static IGenome CreateGenome(NeatParameters neatParameters, IdGenerator idGenerator, int inputNeuronCount, int outputNeuronCount, float connectionProportion)
        {
            IActivationFunction actFunct;
            NeuronGene          neuronGene;                                  // temp variable.
            NeuronGeneList      inputNeuronGeneList  = new NeuronGeneList(); // includes bias neuron.
            NeuronGeneList      outputNeuronGeneList = new NeuronGeneList();
            NeuronGeneList      neuronGeneList       = new NeuronGeneList();
            ConnectionGeneList  connectionGeneList   = new ConnectionGeneList();

            // IMPORTANT NOTE: The neurons must all be created prior to any connections. That way all of the genomes
            // will obtain the same innovation ID's for the bias,input and output nodes in the initial population.
            // Create a single bias neuron.
            //TODO: DAVID proper activation function change to NULL?
            actFunct   = ActivationFunctionFactory.GetActivationFunction("BipolarSigmoid");
            neuronGene = new NeuronGene(idGenerator.NextInnovationId, NeuronType.Bias, actFunct);
            inputNeuronGeneList.Add(neuronGene);
            neuronGeneList.Add(neuronGene);

            // Create input neuron genes.
            //actFunct = ActivationFunctionFactory.GetRandomActivationFunction(neatParameters);
            for (int i = 0; i < inputNeuronCount; i++)
            {
                //TODO: DAVID proper activation function change to NULL?
                neuronGene = new NeuronGene(idGenerator.NextInnovationId, NeuronType.Input, actFunct);
                inputNeuronGeneList.Add(neuronGene);
                neuronGeneList.Add(neuronGene);
            }

            // Create output neuron genes.
            //actFunct = ActivationFunctionFactory.GetActivationFunction("NullFn");
            for (int i = 0; i < outputNeuronCount; i++)
            {
                //actFunct = ActivationFunctionFactory.GetRandomActivationFunction(neatParameters);
                neuronGene = new NeuronGene(idGenerator.NextInnovationId, NeuronType.Output, actFunct);
                //TODO: DAVID proper activation function
                //neuronGene = new NeuronGene(idGenerator.NextInnovationId, NeuronType.Output, actFunct);
                outputNeuronGeneList.Add(neuronGene);
                neuronGeneList.Add(neuronGene);
            }

            // Loop over all possible connections from input to output nodes and create a number of connections based upon
            // connectionProportion.
            foreach (NeuronGene targetNeuronGene in outputNeuronGeneList)
            {
                foreach (NeuronGene sourceNeuronGene in inputNeuronGeneList)
                {
                    // Always generate an ID even if we aren't going to use it. This is necessary to ensure connections
                    // between the same neurons always have the same ID throughout the generated population.
                    uint connectionInnovationId = idGenerator.NextInnovationId;

                    if (Utilities.NextDouble() < connectionProportion)
                    {                           // Ok lets create a connection.
                        connectionGeneList.Add(new ConnectionGene(connectionInnovationId,
                                                                  sourceNeuronGene.InnovationId,
                                                                  targetNeuronGene.InnovationId,
                                                                  (Utilities.NextDouble() * neatParameters.connectionWeightRange) - neatParameters.connectionWeightRange / 2.0)); // Weight 0 +-5
                    }
                }
            }

            // Don't create any hidden nodes at this point. Fundamental to the NEAT way is to start minimally!
            return(new NeatGenome(idGenerator.NextGenomeId, neuronGeneList, connectionGeneList, inputNeuronCount, outputNeuronCount));
        }