/// <summary> /// Evaluates a list of genomes. Here we select the genomes to be evaluated before invoking /// _innerEvaluator to evaluate them. /// </summary> public void Evaluate(IList <TGenome> genomeList, string userName) { // Select the genomes to be evaluated. Place them in a temporary list of genomes to be // evaluated after the genome selection loop. The selection is not performed in series // so that we can wrap parallel execution versions of IGenomeListEvaluator. List <TGenome> filteredList = new List <TGenome>(genomeList.Count); foreach (TGenome genome in genomeList) { if (_selectionPredicate.Invoke(genome)) { // Add the genome to the temp list for evaluation later. filteredList.Add(genome); } else { // Register that the genome skipped an evaluation. genome.EvaluationInfo.EvaluationPassCount++; } } // Evaluate selected genomes. _innerEvaluator.Evaluate(filteredList, userName); }
/// <summary> /// Main genome evaluation loop with no phenome caching (decode on each evaluation). /// Individuals are competed pairwise against every champion in the hall of fame. /// The final fitness score is the weighted sum of the fitness versus the champions /// and the fitness score by the inner evaluator. /// </summary> public void Evaluate(IList <TGenome> genomeList) { _innerEvaluator.Evaluate(genomeList); //Create a temporary list of fitness values with the scores of the inner evaluator. FitnessInfo[] results = new FitnessInfo[genomeList.Count]; for (int i = 0; i < results.Length; i++) { results[i] = new FitnessInfo(genomeList[i].EvaluationInfo.Fitness * (1.0 - _hallOfFameWeight), genomeList[i].EvaluationInfo.AlternativeFitness * (1.0 - _hallOfFameWeight)); } // Calculate how much each champion game is worth double championGameWeight = _hallOfFameWeight / (double)_hallOfFame.Count; // Exhaustively compete individuals against each other. Parallel.For(0, genomeList.Count, delegate(int i) { // Decode the first genome. TPhenome phenome1 = _genomeDecoder.Decode(genomeList[i]); // Check that the first genome is valid. if (phenome1 == null) { return; } for (int j = 0; j < _hallOfFame.Count; j++) { // Decode the second genome. TPhenome phenome2 = _genomeDecoder.Decode(_hallOfFame[j]); // Check that the second genome is valid. if (phenome2 == null) { continue; } // Compete the two individuals against each other and get the results. FitnessInfo fitness1, fitness2; _phenomeEvaluator.Evaluate(phenome1, phenome2, out fitness1, out fitness2); // Add the results to each genome's overall fitness. // Note that we need to use a lock here because // the += operation is not atomic. // ENHANCEMENT: I don't think this lock is necessary here since the hall of fame // is our inner loop. lock (results) { results[i]._fitness += fitness1._fitness * championGameWeight; results[i]._alternativeFitness += fitness1._alternativeFitness * championGameWeight; } } }); // Update every genome in the population with its new fitness score. for (int i = 0; i < results.Length; i++) { genomeList[i].EvaluationInfo.SetFitness(results[i]._fitness); genomeList[i].EvaluationInfo.AlternativeFitness = results[i]._alternativeFitness; } }