/// <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)); }
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))); }
/// <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)); }
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)); }
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); }
public List <NeatGenome> LoadPopulation(XmlReader xr, HyperNEAT_Args hyperneatArgs) { return(LoadPopulation_static(xr, _activationDefinition, hyperneatArgs)); }
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); }
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)); }
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)); }
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); }
public static IGenomeDecoder <NeatGenome, IBlackBox> CreateGenomeDecoder(ExperimentInitArgs_Activation activation, HyperNEAT_Args args) { return(CreateGenomeDecoder_Finish(args, GetActivationScheme_CPPN(), GetActivationScheme(activation))); }
public NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm(IGenomeFactory <NeatGenome> genomeFactory, List <NeatGenome> genomeList, HyperNEAT_Args args) { return(CreateEvolutionAlgorithm_private(genomeFactory, genomeList, args)); }
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)); }
public NeatEvolutionAlgorithm <NeatGenome> CreateEvolutionAlgorithm(HyperNEAT_Args args) { return(CreateEvolutionAlgorithm(DefaultPopulationSize, args)); }