public NoveltyThread(JSPopulationEvaluator jsPop, AssessGenotypeFunction assess, int popSize) { //save our objects for executing later! popEval = jsPop; populationSize = popSize; autoEvent = new AutoResetEvent(false); waitNextTime = true; novelThread = new Thread(delegate() { autoEvent.WaitOne(); //we'll start by testing with 0 parents, and popsize of 15 yay! noveltyRun = EvolutionManager.SharedEvolutionManager.initializeEvolutionAlgorithm(popEval, populationSize, assess); //let our algoirhtm know we want to do novelty gosh darnit if(noveltyRun.multiobjective != null) noveltyRun.multiobjective.doNovelty = true; //we make sure we don't wait in this loop, since we just got started! waitNextTime = false; while (true) { //this will cause us to pause! if (waitNextTime) { waitNextTime = false; autoEvent.WaitOne(); } // Start the stopwatch we'll use to measure eval performance Stopwatch sw = Stopwatch.StartNew(); //run the generation noveltyRun.PerformOneGeneration(); // Stop the stopwatch sw.Stop(); // Report the results Console.WriteLine("Time used per gen (float): {0} ms", sw.Elapsed.TotalMilliseconds); Console.WriteLine("Time used per gen (rounded): {0} ms", sw.ElapsedMilliseconds); } }); novelThread.Start(); }
//, bool evaluate = true) /// <summary> /// Default Constructor. /// </summary> public EvolutionAlgorithm(Population pop, IPopulationEvaluator populationEvaluator, NeatParameters neatParameters, AssessGenotypeFunction assess) { assessFunction = assess; this.pop = pop; this.populationEvaluator = populationEvaluator; this.neatParameters = neatParameters; neatParameters_Normal = neatParameters; neatParameters_PrunePhase = new NeatParameters(neatParameters); neatParameters_PrunePhase.pMutateAddConnection = 0.0; neatParameters_PrunePhase.pMutateAddNode = 0.0; neatParameters_PrunePhase.pMutateAddModule = 0.0; neatParameters_PrunePhase.pMutateConnectionWeights = 0.33; neatParameters_PrunePhase.pMutateDeleteConnection = 0.33; neatParameters_PrunePhase.pMutateDeleteSimpleNeuron = 0.33; // Disable all crossover as this has a tendency to increase complexity, which is precisely what // we don't want during a pruning phase. neatParameters_PrunePhase.pOffspringAsexual = 1.0; neatParameters_PrunePhase.pOffspringSexual = 0.0; if(neatParameters.multiobjective) { this.multiobjective=new Multiobjective.Multiobjective(neatParameters); neatParameters.compatibilityThreshold=100000000.0; //disable speciation w/ multiobjective } //if (!evaluate) // return; if(neatParameters.noveltySearch) { if(neatParameters.noveltyHistogram) { this.noveltyFixed = new noveltyfixed(neatParameters.archiveThreshold); this.histogram = new noveltyhistogram(neatParameters.histogramBins); noveltyInitialized=true; InitialisePopulation(); } if(neatParameters.noveltyFixed || neatParameters.noveltyFloat) { this.noveltyFixed = new noveltyfixed(neatParameters.archiveThreshold); InitialisePopulation(); noveltyFixed.initialize(this.pop); noveltyInitialized=true; populationEvaluator.EvaluatePopulation(pop, this); noveltyFixed.updatePopulationFitness(pop.GenomeList); UpdateFitnessStats(); DetermineSpeciesTargetSize(); } } else { InitialisePopulation(); } }
public static GenomeList CreateGenomeListPreserveIDs(GenomeList seedGenomes, int length, NeatParameters neatParameters, IdGenerator idGenerator, AssessGenotypeFunction assess) { //Eventually, WIN will be brought in to maintain the genomes, for now, no need //Build the list. GenomeList genomeList = new GenomeList(); if (length < seedGenomes.Count) throw new Exception("Attempting to generate a population that is smaller than the number of seeds (i.e. some seeds will be lost). Please change pop size to accomodate for all seeds."); NeatGenome newGenome; for (int i = 0; i < seedGenomes.Count; i++) { // Use each seed directly just once. newGenome = new NeatGenome((NeatGenome)seedGenomes[i], idGenerator.NextGenomeId); genomeList.Add(newGenome); } int testCount = 0; int maxTests = 5; // For the remainder we alter the weights. //for (int i = 1; i < length; i++) //{ while (genomeList.Count < length) { newGenome = new NeatGenome((NeatGenome)seedGenomes[Utilities.Next(seedGenomes.Count)], idGenerator.NextGenomeId); // Reset the connection weights //in this particular instance, we would take a snapshot of the genome AFTER mutation for WIN purposes. But we don't track genomes yet foreach (ConnectionGene connectionGene in newGenome.ConnectionGeneList) connectionGene.Weight += (0.1 - Utilities.NextDouble() * 0.2); //!connectionGene.Weight = (Utilities.NextDouble() * neatParameters.connectionWeightRange) - neatParameters.connectionWeightRange/2.0; //Console.WriteLine((0.1 - Utilities.NextDouble() * 0.2)); //newGenome.ConnectionGeneList.Add(new ConnectionGene(idGenerator.NextInnovationId,5,newGenome.NeuronGeneList[Utilities.Next(newGenome.NeuronGeneList.Count-7)+7].InnovationId ,(Utilities.NextDouble() * neatParameters.connectionWeightRange) - neatParameters.connectionWeightRange/2.0)); //newGenome.ConnectionGeneList.Add(new ConnectionGene(idGenerator.NextInnovationId, 6, newGenome.NeuronGeneList[Utilities.Next(newGenome.NeuronGeneList.Count - 7) + 7].InnovationId, (Utilities.NextDouble() * neatParameters.connectionWeightRange) - neatParameters.connectionWeightRange / 2.0)); //if we have an assess function, it should be used for generating this individual! if (assess != null && assess(newGenome) && testCount++ < maxTests) { //after adding the genome, reset test count genomeList.Add(newGenome); testCount = 0; } else if (assess == null) genomeList.Add(newGenome); else if (testCount >= maxTests) { genomeList.Add(newGenome); testCount = 0; } } // return genomeList; }
public static GenomeList CreateGenomeListPreserveIDs(NeatParameters neatParameters, IdGenerator idGenerator, int inputNeuronCount, int outputNeuronCount, float connectionProportion, int length, AssessGenotypeFunction assess) { GenomeList genomeList = new GenomeList(); int testCount = 0; int maxTests = 5; //for (int i = 0; i < length; i++) while(genomeList.Count < length) { IGenome genome = CreateGenomePreserveID(neatParameters, idGenerator, inputNeuronCount, outputNeuronCount, connectionProportion); if (assess != null && assess(genome) && testCount++ < maxTests) { //after adding the genome, reset test count genomeList.Add(genome); testCount = 0; } else if (assess == null) genomeList.Add(genome); else if (testCount >= maxTests) { genomeList.Add(genome); testCount = 0; } } return genomeList; }
public EvolutionAlgorithm initializeEvolutionAlgorithm(IPopulationEvaluator popEval, int popSize, AssessGenotypeFunction assess, List<long> parentGenomeIDs = null) { //have to add our seed to the parents! if (officialSeedGenome != null) { //if we aren't given any parents, make a new list, and add the seed if (parentGenomeIDs == null) parentGenomeIDs = new List<long>(); parentGenomeIDs.Add(officialSeedGenome.GenomeId); } //create our initial population, using seeds or not, making sure it is at least "popsize" long GenomeList gl = createGenomeList(popSize, assess, parentGenomeIDs); //now we have a genomelist full of our parents, if they didn't die in a car crash when we were young, yay! //also, these parents, their connections, and neurons are safely catalogued by WIN (eventually...) Population pop = new Population(idgen, gl); //create our algorithm evoAlgorithm = new EvolutionAlgorithm(pop, popEval, neatParams, assess); createExperimentDirectory(); //send it away! return evoAlgorithm; }
/// <summary> /// Creates a genomeList from a random start, or using a list of seed genome IDs /// </summary> /// <param name="popSize"></param> /// <param name="parentGenomeIDs"></param> /// <returns></returns> public GenomeList createGenomeList(int popSize, AssessGenotypeFunction genoAssess, List<long> parentGenomeIDs = null) { //must return a genome list! GenomeList gl; //if we have parents, add their genomes to our starting genomelist if (parentGenomeIDs != null) { GenomeList seeds = new GenomeList(); seeds.AddRange(getGenomesFromIDs(parentGenomeIDs).Values); gl = new GenomeList(); gl.AddRange(GenomeFactory.CreateGenomeListPreserveIDs(seeds, popSize, neatParams, idgen, genoAssess)); } else { //we don't have any seeds, we need to form our own initial population gl = GenomeFactory.CreateGenomeListPreserveIDs(neatParams, idgen, cppnInputs, cppnOutputs, neatParams.pInitialPopulationInterconnections, popSize, genoAssess); } //add each genome to our list of generated genomes, yo. //gl.ForEach(genome => allGeneratedGenomes.Add(genome)); //now we are free to return the genomes return gl; }