public static PathChosen NearestNeighbor(CityCollection cities)
        {
            PathChosen  result       = new PathChosen(cities);
            int         numAvailable = cities.Count - 1;
            List <City> usedCities   = new List <City>(); // initialize empty

            City currentCity = cities[0];

            usedCities.Add(currentCity);
            while (numAvailable > 0)
            {
                // find the next closest
                City closest = cities.NearestTo(currentCity.X, currentCity.Y, usedCities);

                // add to our path
                result.AddNextCity(closest);
                currentCity = closest;

                // remember that we've seen this
                usedCities.Add(closest);
                numAvailable--;
            }

            return(result);
        }
Пример #2
0
        public PathChosen(CityCollection setOfCities)
        {
            // keep a reference to the cities
            Cities = setOfCities;

            // and a corresponding list of indexes that specifies the path to take
            CityIndexes = new List <int>();
        }
Пример #3
0
 public CandidateSolution(PathChosen existingPath)
 {
     path   = new PathChosen(existingPath);
     cities = path.Cities;
 }
Пример #4
0
 public CandidateSolution(CityCollection availableCities)
 {
     cities = availableCities;
     path   = new PathChosen(cities);
     path.CreateRandomOrdering();
 }
        public PathChosen FindOptimalPath(CityCollection cities)
        {
            // create generation 0 with all randomly created possible solutions
            currentGeneration = new List <CandidateSolution>(populationSize);
            for (int i = 0; i < populationSize; i++)
            {
                currentGeneration.Add(new CandidateSolution(cities));
            }

            int generationNumber = 1;

            while (true)
            {
                totalFitnessThisGeneration = 0;
                int bestFitnessScoreThisGeneration           = System.Int32.MinValue;
                CandidateSolution bestSolutionThisGeneration = null;

                foreach (var candidate in currentGeneration)
                {
                    candidate.CalculatePathLength();
                }

                // find the longest path, which is the worst solution
                int longestDistance = currentGeneration.Max(c => c.PathLength);

                // then subtract each candidate's distance from that maximum distance
                foreach (var candidate in currentGeneration)
                {
                    // set fitness so the shortest path is the highest value, and the worst is 0
                    candidate.Fitness = longestDistance - candidate.PathLength;

                    // sum up the fitness scores for our roulette wheel selection
                    totalFitnessThisGeneration += candidate.Fitness;
                    if (candidate.Fitness > bestFitnessScoreThisGeneration)
                    {
                        bestFitnessScoreThisGeneration = candidate.Fitness;
                        bestSolutionThisGeneration     = candidate;
                    }
                }

                // Ranked fitnesses for smoothing out selection when fitness scores vary widely

                //currentGeneration = currentGeneration.OrderBy(g => g.Fitness).ToList();
                //int ranking = 1;
                //foreach (var candidate in currentGeneration)
                //{
                //    candidate.Fitness = ranking;
                //    ranking++;
                //}

                int shortestPathThisGeneration = bestSolutionThisGeneration.PathLength;

                // compare this generation's best to the best that have come before it
                if (shortestPathThisGeneration < shortestPathAllTime)
                {
                    // save the best score
                    shortestPathAllTime = shortestPathThisGeneration;

                    // and save the possible solution
                    bestSolution = bestSolutionThisGeneration.DeepClone();
                    bestSolutionGenerationNumber = generationNumber;
                }
                else
                if ((generationNumber - bestSolutionGenerationNumber) >
                    NoChangeGenerationCountForTermination)
                {
                    break;
                }

                // create the next generation
                List <CandidateSolution> nextGeneration = new List <CandidateSolution>();

                // Elitism
                int numElitesToAdd = (int)(elitismRate * populationSize);
                var theBest        = currentGeneration.OrderBy(c => c.PathLength).Take(numElitesToAdd);
                foreach (var peakPerformer in theBest)
                {
                    nextGeneration.Add(peakPerformer);
                }

                while (nextGeneration.Count < populationSize)
                {
                    CandidateSolution parent1, parent2;

                    // pick two parents based on good fitness
                    parent1 = SelectCandidate();
                    parent2 = SelectCandidate();
                    //parent1 = SelectCandidateViaTournament();
                    //parent2 = SelectCandidateViaTournament();

                    // cross them over to generate two new children
                    CandidateSolution child1, child2;
                    CrossOverParents(parent1, parent2, out child1, out child2);

                    // apply mutation to the children if needed
                    //child1.DoSwapMutation(mutationRate);
                    //child2.DoSwapMutation(mutationRate);
                    child1.DoDisplacementMutation(mutationRate);
                    child2.DoDisplacementMutation(mutationRate);

                    // and then add them to the next generation
                    nextGeneration.Add(child1);
                    nextGeneration.Add(child2);
                }

                // move to the next generation
                currentGeneration = nextGeneration;
                generationNumber++;
            }

            //Debug.WriteLine(shortestPathAllTime + " found at generation " + bestSolutionGenerationNumber);
            return(bestSolution.Path);
        }