Beispiel #1
0
        /// <summary>
        /// This is a hyper neat implementation
        /// </summary>
        /// <remarks>
        /// This is built from these two sources:
        /// http://www.nashcoding.com/2010/10/29/tutorial-%E2%80%93-evolving-neural-networks-with-sharpneat-2-part-3/
        /// SharpNeat.Domains.BoxesVisualDiscrimination.BoxesVisualDiscriminationExperiment.CreateGenomeDecoder()
        /// </remarks>
        public IGenomeDecoder <NeatGenome, IBlackBox> CreateGenomeDecoder(HyperNEAT_Args args)
        {
            if (!IsHyperNEAT)
            {
                throw new InvalidOperationException("This HyperNEAT overload can't be used when the experiment is for NEAT");
            }

            return(CreateGenomeDecoder_Finish(args, _activationSchemeCppn, _activationScheme));
        }
Beispiel #2
0
        public static IGenomeFactory <NeatGenome> CreateGenomeFactory(HyperNEAT_Args args, ExperimentInitArgs_Activation activation)
        {
            // The cppn gets handed pairs of points, and there is an extra neuron for something.  See Substrate.CreateNetworkDefinition()
            // Adding 1 to the dimension because a pair of points needs an extra dimension to separate them (2 2D squares would have Z=-1 and 1)
            // Multiplying by 2 because a pair of points is loaded into the cppn at a time
            // Adding the final 1 to store the pair's connection length
            int inputCount = ((args.InputShapeDimensions + 1) * 2) + 1;

            int outputCount = args.OutputShapeDimensions;

            //NOTE: Can't use args.NeuronCount_Input and args.NeuronCount_Output.  This genome factory is for the CPPN which
            //uses the dimensions of the positions as input/output size
            return(new NeatGenomeFactory(inputCount, outputCount, DefaultActivationFunctionLibrary.CreateLibraryCppn(), GetNewNeatGenomeParameters(activation)));
        }
Beispiel #3
0
        /// <summary>
        /// This is a helper method that returns a neural net based on the genome
        /// </summary>
        public IBlackBox GetBlackBox(NeatGenome genome, HyperNEAT_Args hyperneatArgs = null)
        {
            IGenomeDecoder <NeatGenome, IBlackBox> decoder = null;

            if (hyperneatArgs == null)
            {
                decoder = CreateGenomeDecoder();
            }
            else
            {
                decoder = CreateGenomeDecoder(hyperneatArgs);
            }

            return(decoder.Decode(genome));
        }
Beispiel #4
0
        private static List <NeatGenome> LoadPopulation_static(XmlReader xr, ExperimentInitArgs_Activation activation, HyperNEAT_Args hyperneatArgs)
        {
            NeatGenomeFactory genomeFactory = (NeatGenomeFactory)CreateGenomeFactory(hyperneatArgs, activation);

            return(NeatGenomeXmlIO.ReadCompleteGenomeList(xr, false, genomeFactory));
        }
Beispiel #5
0
        private NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm_private(IGenomeFactory <NeatGenome> genomeFactory, List <NeatGenome> genomeList, HyperNEAT_Args args = null)
        {
            // Create distance metric. Mismatched genes have a fixed distance of 10; for matched genes the distance is their weigth difference.
            IDistanceMetric distanceMetric = new ManhattanDistanceMetric(1, 0, 10);
            ISpeciationStrategy <NeatGenome> speciationStrategy = new ParallelKMeansClusteringStrategy <NeatGenome>(distanceMetric, _parallelOptions);

            // Create complexity regulation strategy.
            IComplexityRegulationStrategy complexityRegulationStrategy = ExperimentUtils.CreateComplexityRegulationStrategy(_complexityRegulationStr, _complexityThreshold);

            // Create the evolution algorithm.
            NeatEvolutionAlgorithm <NeatGenome> retVal = new NeatEvolutionAlgorithm <NeatGenome>(NeatEvolutionAlgorithmParameters, speciationStrategy, complexityRegulationStrategy);

            // Genome Decoder
            IGenomeDecoder <NeatGenome, IBlackBox> genomeDecoder = null;

            if (args == null)
            {
                genomeDecoder = CreateGenomeDecoder();
            }
            else
            {
                genomeDecoder = CreateGenomeDecoder(args);
            }

            // Create a genome list evaluator. This packages up the genome decoder with the genome evaluator.
            IGenomeListEvaluator <NeatGenome> genomeEvaluator = null;

            if (_phenomeEvaluator != null)
            {
                IGenomeListEvaluator <NeatGenome> innerEvaluator = new ParallelGenomeListEvaluator <NeatGenome, IBlackBox>(genomeDecoder, _phenomeEvaluator, _parallelOptions);

                // Wrap the list evaluator in a 'selective' evaluator that will only evaluate new genomes. That is, we skip re-evaluating any genomes
                // that were in the population in previous generations (elite genomes). This is determined by examining each genome's evaluation info object.
                genomeEvaluator = new SelectiveGenomeListEvaluator <NeatGenome>(
                    innerEvaluator,
                    SelectiveGenomeListEvaluator <NeatGenome> .CreatePredicate_OnceOnly());
            }
            else if (_phenomeEvaluators != null)
            {
                // Use the multi tick evaluator
                genomeEvaluator = new TickGenomeListEvaluator <NeatGenome, IBlackBox>(genomeDecoder, _phenomeEvaluators, _phenometickeval_roundRobinManager, _phenometickeval_worldTick);
            }
            else
            {
                throw new ApplicationException("One of the phenome evaluators needs to be populated");
            }

            // Initialize the evolution algorithm.
            retVal.Initialize(genomeEvaluator, genomeFactory, genomeList);

            // Finished. Return the evolution algorithm
            return(retVal);
        }
Beispiel #6
0
 public List <NeatGenome> LoadPopulation(XmlReader xr, HyperNEAT_Args hyperneatArgs)
 {
     return(LoadPopulation_static(xr, _activationDefinition, hyperneatArgs));
 }
Beispiel #7
0
        public static List <NeatGenome> LoadPopulation(string xml, ExperimentInitArgs_Activation activation, HyperNEAT_Args hyperneatArgs)
        {
            List <NeatGenome> retVal = null;

            using (XmlReader xr = XmlReader.Create(new MemoryStream(Encoding.Unicode.GetBytes(xml))))
            {
                retVal = LoadPopulation_static(xr, activation, hyperneatArgs);
            }

            return(retVal);
        }
Beispiel #8
0
        public static IBlackBox GetBlackBox(NeatGenome genome, ExperimentInitArgs_Activation activation, HyperNEAT_Args hyperneatArgs = null)
        {
            IGenomeDecoder <NeatGenome, IBlackBox> decoder = null;

            if (hyperneatArgs == null)
            {
                decoder = CreateGenomeDecoder(activation);
            }
            else
            {
                decoder = CreateGenomeDecoder(activation, hyperneatArgs);
            }

            return(decoder.Decode(genome));
        }
Beispiel #9
0
        private static IGenomeDecoder <NeatGenome, IBlackBox> CreateGenomeDecoder_Finish(HyperNEAT_Args args, NetworkActivationScheme activationSchemeCppn, NetworkActivationScheme activationSchemeSubstrate)
        {
            int numInputs  = args.NeuronCount_Input;
            int numOutputs = args.NeuronCount_Output;

            SubstrateNodeSet inputLayer  = new SubstrateNodeSet(numInputs);
            SubstrateNodeSet outputLayer = new SubstrateNodeSet(numOutputs);

            //NOTE: Can't put a neuron at the origin, because the bias node is there - see Substrate.CreateNetworkDefinition()

            // Each node in each layer needs a unique ID
            // Node IDs start at 1. (bias node is always zero)
            // The input nodes use ID range { 1, inputSize^2 } and
            // the output nodes are the next outputSize^2.
            uint inputId  = 1;
            uint outputId = Convert.ToUInt32(numInputs + 1);

            for (int cntr = 0; cntr < args.InputPositions.Length; cntr++)
            {
                inputLayer.NodeList.Add(new SubstrateNode(inputId, args.InputPositions[cntr].ToArray()));
                inputId++;
            }

            for (int cntr = 0; cntr < args.OutputPositions.Length; cntr++)
            {
                outputLayer.NodeList.Add(new SubstrateNode(outputId, args.OutputPositions[cntr].ToArray()));
                outputId++;
            }

            List <SubstrateNodeSet> nodeSetList = new List <SubstrateNodeSet>
            {
                inputLayer,
                outputLayer
            };

            //TODO: The two samples that I copied from have the same number of inputs and outputs.  This mapping may be too simplistic when the counts are different
            //TODO: Notes on using hidden layers:
            //      The above example is a simple 2-layer CPPN with no hidden layers. If you want to add hidden layers, you simply need to create an additional SubstrateNodeSet
            //      and add it to the nodeSetList. Then you will need two NodeSetMappings, one from the input (0) to the hidden (1) layer, and one from the hidden (1) to the
            //      output (2) layer.3

            // Define a connection mapping from the input layer to the output layer.
            List <NodeSetMapping> nodeSetMappingList = new List <NodeSetMapping>();

            nodeSetMappingList.Add(NodeSetMapping.Create
                                   (
                                       //NOTE: Substrate is hardcoded to 0 and 1 for input and output.  2 and up is hidden nodes.  So passing these as params unnecessary
                                       0, // this is the index into nodeSetList (the item in nodeSetList that is the input layer)
                                       1, // index of nodeSetList that is the output layer

                                       (double?)null
                                   ));

            // Construct the substrate using a steepened sigmoid as the phenome's activation function. All weights
            // under .2 will not generate connections in the final phenome
            //Substrate substrate = new Substrate(nodeSetList, DefaultActivationFunctionLibrary.CreateLibraryCppn(), 0, .2, 5, nodeSetMappingList);
            Substrate substrate = new Substrate(nodeSetList, DefaultActivationFunctionLibrary.CreateLibraryNeat(SteepenedSigmoid.__DefaultInstance), 0, .2, 5, nodeSetMappingList);

            // Create genome decoder. Decodes to a neural network packaged with
            // an activation scheme that defines a fixed number of activations per evaluation.
            //IGenomeDecoder<NeatGenome, IBlackBox> genomeDecoder = new HyperNeatDecoder(substrate, _activationSchemeCppn, _activationScheme, false);
            return(new HyperNeatDecoder(substrate, activationSchemeCppn, activationSchemeSubstrate, true));
        }
Beispiel #10
0
        private static IGenomeDecoder <NeatGenome, IBlackBox> CreateGenomeDecoder_Finish_ORIG(HyperNEAT_Args args, NetworkActivationScheme activationSchemeCppn, NetworkActivationScheme activationSchemeSubstrate)
        {
            throw new ApplicationException("obsolete");

            //if (args.InputShape != HyperNEAT_Shape.Square && args.InputShape != HyperNEAT_Shape.Square)
            //{
            //    throw new ApplicationException(string.Format("This method currently only supports square input and output sizes: Input={0}, Output={1}", args.InputShape, args.OutputShape));
            //}

            //if (args.InputCountXY != args.OutputCountXY)
            //{
            //    throw new ApplicationException(string.Format("This method currently only supports input and output counts that are the same: Input={0}, Output={1}", args.InputCountXY, args.OutputCountXY));
            //}

            //int numInputs = args.NeuronCount_Input;
            //int numOutputs = args.NeuronCount_Output;

            //SubstrateNodeSet inputLayer = new SubstrateNodeSet(numInputs);
            //SubstrateNodeSet outputLayer = new SubstrateNodeSet(numOutputs);

            ////NOTE: Can't put a neuron at the origin, because the bias node is there - see Substrate.CreateNetworkDefinition()

            //// Each node in each layer needs a unique ID
            //// Node IDs start at 1. (bias node is always zero)
            //// The input nodes use ID range { 1, inputSize^2 } and
            //// the output nodes are the next outputSize^2.
            //uint inputId = 1;
            //uint outputId = Convert.ToUInt32(numInputs + 1);

            //var inputCells = Math2D.GetCells_ORIG(args.InputSize, args.InputCountXY);
            //var outputCells = Math2D.GetCells_ORIG(args.OutputSize, args.OutputCountXY);

            //for (int y = 0; y < args.InputCountXY; y++)
            //{
            //    for (int x = 0; x < args.InputCountXY; x++)
            //    {
            //        //NOTE: This is currently hardcoded to the input and output arrays being the same size
            //        int index = (y * args.InputCountXY) + x;

            //        Point inputPoint = inputCells[index].Item2;
            //        Point outputPoint = outputCells[index].Item2;

            //        inputLayer.NodeList.Add(new SubstrateNode(inputId, new double[] { inputPoint.X, inputPoint.Y, -1d }));
            //        outputLayer.NodeList.Add(new SubstrateNode(outputId, new double[] { outputPoint.X, outputPoint.Y, 1d }));

            //        inputId++;
            //        outputId++;
            //    }
            //}

            //List<SubstrateNodeSet> nodeSetList = new List<SubstrateNodeSet>
            //{
            //    inputLayer,
            //    outputLayer
            //};

            ////TODO: The two samples that I copied from have the same number of inputs and outputs.  This mapping may be too simplistic when the counts are different
            ////TODO: Notes on using hidden layers:
            ////      The above example is a simple 2-layer CPPN with no hidden layers. If you want to add hidden layers, you simply need to create an additional SubstrateNodeSet
            ////      and add it to the nodeSetList. Then you will need two NodeSetMappings, one from the input (0) to the hidden (1) layer, and one from the hidden (1) to the
            ////      output (2) layer.3

            //// Define a connection mapping from the input layer to the output layer.
            //List<NodeSetMapping> nodeSetMappingList = new List<NodeSetMapping>();
            //nodeSetMappingList.Add(NodeSetMapping.Create
            //(
            //    //NOTE: Substrate is hardcoded to 0 and 1 for input and output.  2 and up is hidden nodes.  So passing these as params unnecessary
            //    0,      // this is the index into nodeSetList (the item in nodeSetList that is the input layer)
            //    1,      // index of nodeSetList that is the output layer

            //    (double?)null
            //));

            //// Construct the substrate using a steepened sigmoid as the phenome's activation function. All weights
            //// under .2 will not generate connections in the final phenome
            ////Substrate substrate = new Substrate(nodeSetList, DefaultActivationFunctionLibrary.CreateLibraryCppn(), 0, .2, 5, nodeSetMappingList);
            //Substrate substrate = new Substrate(nodeSetList, DefaultActivationFunctionLibrary.CreateLibraryNeat(SteepenedSigmoid.__DefaultInstance), 0, .2, 5, nodeSetMappingList);

            //// Create genome decoder. Decodes to a neural network packaged with
            //// an activation scheme that defines a fixed number of activations per evaluation.
            ////IGenomeDecoder<NeatGenome, IBlackBox> genomeDecoder = new HyperNeatDecoder(substrate, _activationSchemeCppn, _activationScheme, false);
            //return new HyperNeatDecoder(substrate, activationSchemeCppn, activationSchemeSubstrate, true);
        }
Beispiel #11
0
 public static IGenomeDecoder <NeatGenome, IBlackBox> CreateGenomeDecoder(ExperimentInitArgs_Activation activation, HyperNEAT_Args args)
 {
     return(CreateGenomeDecoder_Finish(args, GetActivationScheme_CPPN(), GetActivationScheme(activation)));
 }
Beispiel #12
0
 public NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm(IGenomeFactory <NeatGenome> genomeFactory, List <NeatGenome> genomeList, HyperNEAT_Args args)
 {
     return(CreateEvolutionAlgorithm_private(genomeFactory, genomeList, args));
 }
Beispiel #13
0
        public NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm(int populationSize, HyperNEAT_Args args)
        {
            // Create a genome2 factory with our neat genome2 parameters object and the appropriate number of input and output neuron genes.
            IGenomeFactory <NeatGenome> genomeFactory = CreateGenomeFactory(args);

            // Create an initial population of randomly generated genomes.
            List <NeatGenome> genomeList = genomeFactory.CreateGenomeList(populationSize, 0);

            // Call more specific overload
            return(CreateEvolutionAlgorithm_private(genomeFactory, genomeList, args));
        }
Beispiel #14
0
 public NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm(HyperNEAT_Args args)
 {
     return(CreateEvolutionAlgorithm(DefaultPopulationSize, args));
 }