using System;
using System.Linq;
using System.Collections.Generic;
class TSP_DE
{
static Random rand = new Random();
static (double, double)[] cities = {
(88, 16), (42, 76), (5, 76), (69, 13), (73, 56), (100, 100), (22, 92), (48, 74), (73, 46),
(39, 1), (51, 75), (92, 2), (101, 44), (55, 26), (71, 27), (42, 81), (51, 91), (89, 54),
(33, 18), (40, 78)
};
static int numCities = cities.Length;
static double TotalDistance(int[] order)
{
double dist = 0;
for (int i = 0; i < order.Length - 1; i++)
dist += Distance(cities[order[i]], cities[order[i + 1]]);
dist += Distance(cities[order[order.Length - 1]], cities[order[0]]);
return dist;
}
static double Distance((double, double) a, (double, double) b) =>
Math.Sqrt(Math.Pow(a.Item1 - b.Item1, 2) + Math.Pow(a.Item2 - b.Item2, 2));
static int[] Mutate(int[] order)
{
int[] newOrder = (int[])order.Clone();
int idx1 = rand.Next(numCities);
int idx2 = rand.Next(numCities);
(newOrder[idx1], newOrder[idx2]) = (newOrder[idx2], newOrder[idx1]);
return newOrder;
}
static int[] Crossover(int[] parent1, int[] parent2)
{
int size = parent1.Length;
int[] child = new int[size];
Array.Fill(child, -1);
int start = rand.Next(size);
int end = rand.Next(start, size);
for (int i = start; i <= end; i++)
child[i] = parent1[i];
for (int i = 0; i < size; i++)
{
if (child.Contains(parent2[i])) continue;
for (int j = 0; j < size; j++)
{
if (child[j] == -1)
{
child[j] = parent2[i];
break;
}
}
}
return child;
}
static int[] DifferentialEvolution(int populationSize, int generations, double mutationRate, double crossoverRate)
{
List<int[]> population = new List<int[]>();
for (int i = 0; i < populationSize; i++)
population.Add(Enumerable.Range(0, numCities).OrderBy(_ => rand.Next()).ToArray());
int[] bestSolution = population[0];
double bestDistance = TotalDistance(bestSolution);
for (int gen = 0; gen < generations; gen++)
{
List<int[]> newPopulation = new List<int[]>();
foreach (var individual in population)
{
var candidates = population.OrderBy(_ => rand.Next()).Take(3).ToArray();
int[] mutant = Mutate(candidates[0]);
int[] trial;
if (rand.NextDouble() < crossoverRate)
trial = Crossover(mutant, individual);
else
trial = (int[])mutant.Clone();
double trialDistance = TotalDistance(trial);
double individualDistance = TotalDistance(individual);
if (trialDistance < individualDistance)
{
newPopulation.Add(trial);
if (trialDistance < bestDistance)
{
bestDistance = trialDistance;
bestSolution = trial;
}
}
else
{
newPopulation.Add(individual);
}
}
population = newPopulation;
Console.WriteLine($"Generation {gen + 1}: Best Distance = {bestDistance}");
}
return bestSolution;
}
static void Main()
{
int populationSize = 50;
int generations = 2000;
double mutationRate = 0.5;
double crossoverRate = 0.5;
Console.WriteLine("Starting Differential Evolution for TSP...");
int[] bestOrder = DifferentialEvolution(populationSize, generations, mutationRate, crossoverRate);
Console.WriteLine("\nOptimal Route:");
foreach (var city in bestOrder)
Console.Write(city + " -> ");
Console.WriteLine(bestOrder[0]);
Console.WriteLine("Optimal Distance: " + TotalDistance(bestOrder));
}
}