public void Generate() { IRouletteWheel rouletteWheel = breedingFactory.CreateRouletteWheel(generation); breeder.SetRouletteWheel(rouletteWheel); breeder.CalcFitness(generation); Solution[] newGeneration = new Solution[population]; for (int i = 0; i < population; i++) { newGeneration[i] = breeder.Breed(); } logger.logBestFitSolution(writer, FindBestFit()); generation = newGeneration; }
private void createNextGeneration(ITrainingSession bestPerformer) { Stopwatch watch = new Stopwatch(); watch.Start(); int numberOfTopPerformersToChoose = (int)(_generationConfig.GenerationPopulation * 0.50); int numToBreed = (int)(_generationConfig.GenerationPopulation * 0.35); int numToGen = (int)(_generationConfig.GenerationPopulation * 0.15); if (numberOfTopPerformersToChoose + numToBreed + numToGen < _generationConfig.GenerationPopulation) { numToGen += _generationConfig.GenerationPopulation - (numberOfTopPerformersToChoose + numToBreed + numToGen); } var sessions = _generation.GetBestPerformers(numberOfTopPerformersToChoose); if (bestPerformer != null) { LoggerFactory.GetLogger().Log(LogLevel.Info, "Best performer found for creating generation"); if (sessions.All(s => s.NeuralNet.GetGenes() != bestPerformer.NeuralNet.GetGenes())) { LoggerFactory.GetLogger() .Log(LogLevel.Info, $"Best performer adding to sessions with eval {bestPerformer.GetSessionEvaluation()}"); sessions[sessions.Count - 1] = bestPerformer; sessions = sessions.OrderByDescending(s => s.GetSessionEvaluation()).ToList(); LoggerFactory.GetLogger() .Log(LogLevel.Info, $"session 0 eval: {sessions[0].GetSessionEvaluation()}"); } else { LoggerFactory.GetLogger() .Log(LogLevel.Info, $"Best performer already in generation: not adding."); } } _history.AddEval(sessions[0].GetSessionEvaluation()); var mutateChance = DetermineMutateChance(); IList <INeuralNetwork> children = _breeder.Breed(sessions, numToBreed); var newSessions = new List <ITrainingSession>(); //Allow the very top numToLiveOn sessions to be added to next generation untouched int numToLiveOn = sessions.Count / 10; var sessionsToLiveOn = sessions.Take(numToLiveOn).ToList(); newSessions.AddRange(sessionsToLiveOn); //try to mutate session that will live on 1 by 1 var mutatedTop = GetMutatedNetworks(sessionsToLiveOn.Select(s => s.NeuralNet), mutateChance); //or each session that lived on that was mutated, remove last top performer, then mutate remaining top performers in batch and add sessions = sessions.Skip(numToLiveOn).ToList(); var sessionSubset = sessions.Take(sessions.Count - mutatedTop.Count); IList <INeuralNetwork> toKeepButPossiblyMutate = sessionSubset.Select(session => session.NeuralNet).ToList(); IList <INeuralNetwork> newNetworks = getNewNetworks(numToGen, mutateChance); List <INeuralNetwork> toTryMutate = new List <INeuralNetwork>(); //try to mutate both new networks as well as all the top performers we wanted to keep toTryMutate.AddRange(toKeepButPossiblyMutate); toTryMutate.AddRange(newNetworks); bool didMutate; IList <INeuralNetwork> maybeMutated = _mutator.Mutate(toTryMutate, mutateChance, out didMutate); List <INeuralNetwork> allToAdd = new List <INeuralNetwork>(); allToAdd.AddRange(mutatedTop); allToAdd.AddRange(children); allToAdd.AddRange(maybeMutated); newSessions.AddRange(allToAdd.Select((net, sessionNumber) => new TrainingSession(net, _evaluatableFactory.Create(net), sessionNumber))); _generation = new Generation(newSessions, _generationConfig); watch.Stop(); LoggerFactory.GetLogger().Log(LogLevel.Debug, $"create generation runtime (sec): {watch.Elapsed.TotalSeconds}"); watch.Reset(); }
public void Solve(BionicModel model, BionicSolverSettings settings) { if (model == null) { throw new ArgumentNullException("model"); } if (settings == null) { throw new ArgumentNullException("settings"); } OnSolverStarting(new EventArgs()); IInitialPopulationGenerator initializer = InitialPopulationGeneratorFactory.CreateInitialPopulationGenerator(); ISelector selector = SelectorFactory.CreateSelector(); IBreeder breeder = BreederFactory.CreateBreeder(); // 1. Zeroing generation number model.CurrentGeneration = 0; OnSolverStarted(new EventArgs()); // 2. Creating initial population CopyIndividuals(initializer.GenerateInitialPopulation(settings.InitialPopulationSize, model.Attributes), model.CurrentPopulation); CalculateFitness(model, model.CurrentPopulation, settings); model.ApplyFunctionalConstraints(); OnPopulationUpdated(new EventArgs()); while (model.CurrentGeneration < settings.MaxGenerations) { // 3. Selecting most fit individuals IEnumerable <Individual> fitIndividuals = selector.Select(model.CurrentPopulation, model.FitnessCriterion, settings.SelectionCap); if (fitIndividuals.Count() == 0) { OnSolverFinished(new SolverFinishedEventArgs("All individuals are inactive")); return; } // Selected subpopulation will contain only selected active individuals Population selectedSubPopulation = new Population(fitIndividuals.Count()); foreach (Individual fitIndividual in fitIndividuals) { selectedSubPopulation.Add(fitIndividual); } // 4. Breeding the selected ones IEnumerable <Individual> descendants = breeder.Breed(selectedSubPopulation, model.Attributes, settings.DescendantsRangePercent, settings.DescendantsNum, model.CurrentGeneration + 1); if (descendants.Count() == 0) { OnSolverFinished(new SolverFinishedEventArgs("No descendants was created")); return; } // Descendants subpopulation will contain only new individuals Population descendantsSubPopulation = new Population(descendants.Count()); foreach (Individual descendant in descendants) { descendantsSubPopulation.Add(descendant); } // 5. Calculating fitness of the descendants CalculateFitness(model, descendantsSubPopulation, settings); // At this point, all descendants are still active, although // there may be individuals that don't fit f. c. // 6. Forming new population if (settings.ApplyElitism) { // First unite descendants with their parents (elitism) // We can do this without fear of ID collision because this // was taken into account on the breeding step CopyIndividuals(descendantsSubPopulation, selectedSubPopulation); // Now this united population becomes current, we just // throw away old individuals model.CurrentPopulation.Clear(); CopyIndividuals(selectedSubPopulation, model.CurrentPopulation); } else { // We throw away parents and old individuals, // descendants are taking over the place model.CurrentPopulation.Clear(); CopyIndividuals(descendantsSubPopulation, model.CurrentPopulation); } model.ApplyFunctionalConstraints(); // 7. Updating current generation number model.CurrentGeneration = model.CurrentPopulation.Max(ind => ind.Value.GenerationNumber); OnPopulationUpdated(new EventArgs()); } OnSolverFinished(new SolverFinishedEventArgs()); }