public PopulationNovelty(int size, NoveltyChromosome ancestor, IFitnessFunction fitnessFunction, IDistanceFunction distanceFunction, ISelectionMethod selectionMethod, int kNearestNeighbours) : base(size, ancestor, fitnessFunction, selectionMethod) { if (kNearestNeighbours < 2) { throw new ArgumentException("Too small nearest neighbours was specified."); } _distanceFunction = distanceFunction; _kNearestNeighbours = kNearestNeighbours; }
private void CalculateSparseness() { population = population.OrderByDescending(x => x.Fitness).ToList(); // CALCULATE ALL SPARSENESS HERE Parallel.For(0, population.Count, i => { double[] distances = new double[population.Count + _archive.Count]; NoveltyChromosome auxChromosome = (NoveltyChromosome)this[i]; for (int j = 0; j < population.Count; j++) { distances[j] = findDistance(auxChromosome, this[j]); } for (int j = 0; j < _archive.Count; j++) { distances[population.Count + j] = findDistance(auxChromosome, _archive[j]); } double distSum = 0; double[] closestDistances = new double[_kNearestNeighbours]; double[] closestFitness = new double[_kNearestNeighbours]; for (int k = 0; k < _kNearestNeighbours; k++) { closestDistances[k] = int.MaxValue; } for (int j = 0; j < population.Count + _archive.Count; j++) { double currentDistance = distances[j]; // // If it's better than the worst saved distances // if (currentDistance < closestDistances[_kNearestNeighbours - 1] && (i != j)) { bool shift = false; double auxDistance1 = 0; double auxDistance2 = 0; double auxFitness1 = 0; double auxFitness2 = 0; for (int k = 0; k < _kNearestNeighbours; k++) { // // Save the new distance at its proper place in the closestDistances array // if (shift == false) { if (currentDistance < closestDistances[k]) { shift = true; auxDistance1 = closestDistances[k]; auxFitness1 = closestFitness[k]; closestDistances[k] = currentDistance; if (j < population.Count) { closestFitness[k] = this[j].Fitness; } else if (auxChromosome != _archive[j - population.Count]) { closestFitness[k] = _archive[j - population.Count].Fitness; } } } // // And shift the rest keeping the array closestDistances always ordered // else { auxDistance2 = closestDistances[k]; closestDistances[k] = auxDistance1; auxDistance1 = auxDistance2; if (j < population.Count || auxChromosome != _archive[j - population.Count]) { auxFitness2 = closestFitness[k]; closestFitness[k] = auxFitness1; auxFitness1 = auxFitness2; } } } } } auxChromosome.LocalCompetition = 0; // // Make a sum of all those _nearestNeighbours distances. // for (int k = 0; k < _kNearestNeighbours; k++) { distSum += closestDistances[k]; if (auxChromosome.Fitness > closestFitness[k]) { auxChromosome.LocalCompetition++; } } // // Claculate the average // auxChromosome.Sparseness = distSum / KNearestNeighbours; if (auxChromosome.Fitness < _minimalCriteria) { auxChromosome.LocalCompetition = 0; } }); for (int i = 0; i < population.Count; i++) { NoveltyChromosome currentChromosome = (NoveltyChromosome)this[i]; if (currentChromosome.Sparseness > _sparsenessThreshold) { _archive.Add(currentChromosome); // // Count as added to archive. // _addedToArchiveCount++; if (_archive.Count > _archiveSizeLimit) { _archive.RemoveAt(0); } } } }