/// <summary> /// Sorts genomes using the <see cref="_generationEvaluationActor"/>. /// </summary> /// <param name="genomesToSort">The <see cref="ImmutableGenome"/>s to sort.</param> /// <returns>The sorting result.</returns> protected SortResult SortGenomes(ImmutableList <ImmutableGenome> genomesToSort) { var generationEvaluationMessage = new GenerationEvaluation <TInstance, TResult>( genomesToSort, this._instances, (runEvaluator, participantsOfGeneration, instancesOfGeneration) => new SortingGenerationEvaluationStrategy <TInstance, TResult>( runEvaluator, participantsOfGeneration, instancesOfGeneration, this._currentGeneration, this._useGrayBoxInGeneration)); var generationEvaluationTask = this._generationEvaluationActor.Ask <SortResult>(generationEvaluationMessage).ContinueWith( task => { if (task.IsFaulted) { throw new InvalidOperationException( $"The generation evaluation in generation {this._currentGeneration} resulted in an exception!{Environment.NewLine}Message: {task.Exception?.Message}"); } return(task.Result); }); generationEvaluationTask.Wait(); return(generationEvaluationTask.Result); }
/// <summary> /// The <see cref="Ready"/> state is responsible for handling generation evaluation messages. /// </summary> private void Ready() { this.Receive <GenerationEvaluation <TInstance, TResult> >( generationEvaluation => { this.SetGenerationEvaluationIssuer(this.Sender); this._currentGenerationEvaluation = generationEvaluation; this._evaluationStrategy = generationEvaluation.EvaluationStrategyFactory( this._runEvaluator, generationEvaluation.Participants, generationEvaluation.Instances); this._genomesWaitingForResultsFromStorage = new HashSet <ImmutableGenome>( generationEvaluation.Participants, ImmutableGenome.GenomeComparer); this.Become(this.FetchingResultsFromStorage); foreach (var genome in this._genomesWaitingForResultsFromStorage.ToList()) { this._resultStorageActor.Tell(new GenomeResultsRequest(genome)); } }); // Unreachable member events should always be handled to keep the Akka.NET cluster clean. this.Receive <ClusterEvent.UnreachableMember>( this.HandleUnreachableMessage); }
/// <summary> /// Evaluates all incumbent genomes on the provided instances. /// </summary> /// <param name="allIncumbentGenomes">All incumbent genomes.</param> /// <param name="instances">The instances.</param> /// <returns>The <see cref="GgaResult{TResult}"/>.</returns> public GgaResult <TResult> EvaluateAllIncumbentGenomes( IEnumerable <ImmutableGenome> allIncumbentGenomes, IEnumerable <TInstance> instances) { if (allIncumbentGenomes == null) { throw new ArgumentNullException(nameof(allIncumbentGenomes)); } if (!allIncumbentGenomes.Any()) { throw new ArgumentOutOfRangeException(nameof(allIncumbentGenomes)); } if (instances == null) { throw new ArgumentNullException(nameof(instances)); } if (!instances.Any()) { throw new ArgumentOutOfRangeException(nameof(instances)); } // Set generation to -1 and disable gray box, since this is a "post tuning generation". var generationEvaluationMessage = new GenerationEvaluation <TInstance, TResult>( allIncumbentGenomes, instances, (runEvaluator, participantsOfGeneration, instancesOfGeneration) => new MiniTournamentGenerationEvaluationStrategy <TInstance, TResult>( runEvaluator, participantsOfGeneration, instancesOfGeneration, -1, this._configuration, false, true)); var generationEvaluationTask = this._generationEvaluationActor.Ask <GgaResult <TResult> >(generationEvaluationMessage).ContinueWith( task => { if (task.IsFaulted) { throw new InvalidOperationException( $"The evaluation of all incumbent genomes resulted in an exception!{Environment.NewLine}Message: {task.Exception?.Message}"); } return(task.Result); }); generationEvaluationTask.Wait(); return(generationEvaluationTask.Result); }
/// <summary> /// Selects those genomes from the competitive part of the population that are allowed to reproduce. /// </summary> /// <param name="instancesForEvaluation"> /// The <typeparamref name="TInstance"/>s to use for evaluation. /// </param> /// <returns> /// Competitive genomes allowed to reproduce. /// </returns> private TournamentWinnersWithRank <TResult> PerformSelection( IEnumerable <TInstance> instancesForEvaluation) { var generationEvaluationMessage = new GenerationEvaluation <TInstance, TResult>( this._population.GetCompetitiveIndividuals().Select(genome => new ImmutableGenome(genome)), instancesForEvaluation, (runEvaluator, participantsOfGeneration, instancesOfGeneration) => new MiniTournamentGenerationEvaluationStrategy <TInstance, TResult>( runEvaluator, participantsOfGeneration, instancesOfGeneration, this._currentGeneration, this._configuration, this._useGrayBoxInGeneration, false)); var generationEvaluationTask = this._tournamentSelector.Ask <GgaResult <TResult> >(generationEvaluationMessage).ContinueWith( task => { if (task.IsFaulted) { // It was impossible to determine the best genomes, i.e. something really bad happened. // In this case, we throw an exception for the caller to handle. throw new InvalidOperationException( $"The generation evaluation with GGA in generation {this._currentGeneration} resulted in an exception!{Environment.NewLine}Message: {task.Exception?.Message}"); } var result = new TournamentWinnersWithRank <TResult>( task.Result.CompetitiveParents, task.Result.GenerationBest, task.Result.GenerationBestResult, task.Result.GenomeToTournamentRank); return(result); }); generationEvaluationTask.Wait(); return(generationEvaluationTask.Result); }
public static void Crossover(this CrossoverFunction crossoverFunction, NeuralNetwork child, GenerationEvaluation evaluation, SelectionFunction selectionFunction, float fitnessPower) { var(b, w) = evaluation.pool.Select(selectionFunction, fitnessPower); var(better, worse) = (b.Genes, w.Genes); var genes = child.genes; var count = genes.Length; var halfCount = genes.Length / 2; switch (crossoverFunction) { case CrossoverFunction.HalfWorstBest: for (var i = 0; i < halfCount; i++) { child.genes[i] = better[i]; } for (var i = halfCount; i < count; i++) { child.genes[i] = worse[i]; } break; case CrossoverFunction.HalfBestWorse: for (var i = 0; i < halfCount; i++) { child.genes[i] = worse[i]; } for (var i = halfCount; i < count; i++) { child.genes[i] = better[i]; } break; case CrossoverFunction.HalfRandomShift: var shift = Random.Range(0, count - 1); var overlaps = shift + halfCount > count - 1; for (var i = 0; i < count; i++) { child.genes[i] = (!overlaps && i > shift && i < shift + halfCount || overlaps && !(i > shift && i < shift + halfCount) ? better : worse)[i]; } break; case CrossoverFunction.Step: for (var i = 0; i < count; i++) { genes[i] = (i % 2 == 0 ? better : worse)[i]; } break; case CrossoverFunction.StepRandom: for (var i = 0; i < count; i++) { genes[i] = (Random.value > .5f ? better : worse)[i]; } break; case CrossoverFunction.FractionRandom: { for (var i = 0; i < count; i++) { var fraction = Random.value; genes[i] = better[i] * fraction + worse[i] * (1f - fraction); } break; } case CrossoverFunction.FractionByFitness: { var fraction = b.Fitness / (b.Fitness + w.Fitness); for (var i = 0; i < count; i++) { genes[i] = better[i] * fraction + worse[i] * (1f - fraction); } break; } case CrossoverFunction.Average: default: for (var i = 0; i < count; i++) { genes[i] = (better[i] + worse[i]) * .5f; } break; } }