Пример #1
0
        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;
        }
Пример #2
0
        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);
                    }
                }
            }
        }