//Mutasyon Fonksiyonu public void Mutation(TspFile chromosome, double probability) { Random r = new Random(); double rndProbability = r.NextDouble(); if (rndProbability <= probability) //Mutasyon olasiligi, random sayimizdan buyukse mutasyon islemi gerceklesir { // random pozisyondaki sehri 1 arttiriyoruz ama bunu gecici bir degiskende tutuyoruz. int mPosition = r.Next(0, chromosome.cityList.Count); int temp = chromosome.cityList[mPosition].index; int temp2 = temp + 1; //degisecek sehri bulma for (int i = 0; i < chromosome.cityList.Count; i++) { //degeri artirilan sehri buldugmuzda ve o sehir, sehir sayimizdan kucuk oldugunda if (chromosome.cityList[i].index == temp2 && temp2 <= chromosome.cityList.Count) { chromosome.cityList[i].index = temp; //degeri 1 artan sehiri 1 eksiltiyoruz chromosome.cityList[mPosition].index++; //mutasyon gecirecek gercek geni 1 arttiriyoruz break; } } } }
// //Ilk populasyonu olusturma public List <TspFile> CreateFirstPopulation(TspFile firstTspFile, int populationSize) { List <TspFile> populationList = new List <TspFile>(); for (int i = 0; i < populationSize; i++) { List <City> cityPopulation = new List <City>(firstTspFile.cityList); Shuffle <City>(cityPopulation); TspFile tspFile = new TspFile(); tspFile.cityList = cityPopulation; populationList.Add(tspFile); } return(populationList); }
void SaveFile(TspFile result, double bestFitness) { StreamWriter sw = new StreamWriter(tspFile.name + ".tour"); sw.WriteLine("Name : " + tspFile.name + ".tour"); sw.WriteLine("Comment : " + bestFitness); sw.WriteLine("TYPE : TOUR"); sw.WriteLine("DIMENSION : " + tspFile.dimension); sw.WriteLine("TOUR_SECTION"); for (int i = 0; i < result.cityList.Count; i++) { sw.WriteLine(result.cityList[i].index); } sw.WriteLine("-1"); sw.WriteLine("EOF"); sw.Close(); }
//------Parent seciminde kullandigimiz Rank Selection yontemi------------- //Algoritma en kotuden en iyiye fitness degerlerini siralayip, //sirasina gore i.sira / (n(n+1))/2 formulu ile hesapliyor. //Boylelikle en iyi fitness en buyuk olasiliga sahip oluyor. public TspFile[] RankSelection(List <TspFile> populationList) { Dictionary <double, double[]> rank = new Dictionary <double, double[]>(); double n = (populationList.Count * (populationList.Count + 1)) / 2; double cumulativeRankSum = 0; // kumulatif toplam urettigimiz random sayinin nereye dustugunu bulmak icin tanimlandi. for (int i = 1; i <= populationList.Count; i++) { rank.Add(i, new double[] { i / n, cumulativeRankSum + i / n }); cumulativeRankSum += i / n; } Random r = new Random(); double p1 = r.Next(0, int.MaxValue) / (double)int.MaxValue; //0 ile 1 arasinda sayi uretmek icin kullandik. double p2 = r.Next(0, int.MaxValue) / (double)int.MaxValue; TspFile parent1 = new TspFile(); TspFile parent2 = new TspFile(); parent1 = populationList[0]; parent2 = populationList[0]; for (int i = rank.Count; i >= 1; i--) { rank.TryGetValue(i, out double[] value); if (p1 >= value[1]) { parent1 = populationList[i]; break; } } for (int i = rank.Count; i >= 1; i--) { rank.TryGetValue(i, out double[] value); if (p2 >= value[1]) { parent2 = populationList[i]; break; } } return(new TspFile[] { parent1, parent2 }); }
//Fitness degerlerini dosya tipine gore hesaplayan fonksiyon //fitness fonksiyonumuz uzaklik hesabi oldugundan problemin tipi fitness fonksiyonumuzu da belirliyor. public void CalculateFitnessFunction(TspFile tspFile, EdgeWeightType edgeWeightType) { switch (edgeWeightType) { case EdgeWeightType.EUC_2D: tspFile.EuclidDistance(); break; case EdgeWeightType.MAX_2D: tspFile.MaximumDistance(); break; case EdgeWeightType.MAN_2D: tspFile.ManhattanDistance(); break; case EdgeWeightType.CEIL_2D: tspFile.CeilDistance(); break; default: break; } }
// Dosya okuma Fonksiyonu //Butun satirlari okuyup lines`a atiyor. // daha sonra string islemleri ile tspfile classina tanimliyoruz. void ReadFile() { listBox1.Items.Clear(); OpenFileDialog openFileDialog = new OpenFileDialog(); if (openFileDialog.ShowDialog() == DialogResult.OK) { string[] lines = File.ReadAllLines(openFileDialog.FileName); tspFile = new TspFile(); bool startCoordinat = false; bool rightFile = true; char[] seperators = new char[] { ' ' }; for (int i = 0; i < lines.Length; i++) { string line = lines[i].Trim(); if (line != "NODE_COORD_SECTION" && startCoordinat == false) { string before = line.Split(':')[0].Trim(); string after = line.Split(':')[1].Trim(); if (before == "NAME") { tspFile.name = after; } else if (before == "TYPE") { if (after == "TSP") { tspFile.type = after; } else { rightFile = false; /////// Dosya TSP degil ise yanlis dosya tipi break; } } else if (before == "COMMENT") { tspFile.comment = after; } else if (before == "DIMENSION") { tspFile.dimension = int.Parse(after); } else if (before == "EDGE_WEIGHT_TYPE") //tipi 2d olmayanlari okumuyor. { try { tspFile.edgeWeightType = (EdgeWeightType)Enum.Parse(typeof(EdgeWeightType), after); } catch (Exception) { rightFile = false; MessageBox.Show("Yanlış Dosya Formatı. Geçerli formatlar EUC_2D - MAX_2D - MAN_2D - CEIL_2D"); break; } } } else if (line == "NODE_COORD_SECTION") { startCoordinat = true; } else if (line != "EOF") { line = lines[i].Trim(); string[] splitLine = line.Split(seperators, StringSplitOptions.RemoveEmptyEntries); int index = int.Parse(splitLine[0]); double x = double.Parse(splitLine[1].Replace('.', ',')); double y = double.Parse(splitLine[2].Replace('.', ',')); tspFile.AddCity(index, x, y); } } if (rightFile) // Dosya tsp ve tipi 2d ise { listBox1.Items.Add(tspFile.name); listBox1.Items.Add(tspFile.comment); listBox1.Items.Add(tspFile.type); listBox1.Items.Add(tspFile.dimension); listBox1.Items.Add(tspFile.edgeWeightType); listBox1.Items.Add(tspFile.MaximumDistance()); for (int i = 0; i < tspFile.cityList.Count; i++) { listBox1.Items.Add(tspFile.cityList[i].index + ".city " + tspFile.cityList[i].x + " , " + tspFile.cityList[i].y); } } } }
private void btn_run_Click(object sender, EventArgs e) { chart1.Series.Clear(); Series series = chart1.Series.Add("Distance"); int iterationNumber = int.Parse(txt_iterationNumber.Text); int populationSize = int.Parse(txt_populationSize.Text); double mutationProbability = double.Parse(txt_mutationProbability.Text); double elitismRatio = double.Parse(txt_elitismRatio.Text); string crossoverType = combo_crossoverOperator.Text; GeneticOperations geneticOperations = new GeneticOperations(); List <TspFile> populationList = geneticOperations.CreateFirstPopulation(tspFile, populationSize); List <TspFile> newPopulationList = new List <TspFile>(); TspFile parent1; TspFile parent2; for (int j = 0; j < populationList.Count; j++) { //populasyonun fitness degerlerinin hesaplanmasi geneticOperations.CalculateFitnessFunction(populationList[j], tspFile.edgeWeightType); } // burada popülasyon sıralanacak fitness değerine göre populationList.Sort(); double maxFitness = 0, minFitness = double.MaxValue, meanFitness = 0; for (int i = 0; i < iterationNumber; i++) { newPopulationList.Clear(); // elitizm int elitismCount = (int)(elitismRatio * populationSize); for (int j = 1; j <= elitismCount; j++) { newPopulationList.Add(populationList[populationList.Count - j]); } // popülasyonlar oluşturuluyor while (newPopulationList.Count <= populationSize) { // Popülasyona genetik algoritmalar uygulanıyor TspFile[] parents = geneticOperations.RankSelection(populationList); //Rank Selection yapilmasi, geriye 2 parent donuyor. parent1 = parents[0]; parent2 = parents[1]; switch (crossoverType) { case "One Point": parents = geneticOperations.OnePointCrossover(parents); break; case "Two Point": parents = geneticOperations.TwoPointCrossover(parents); break; case "Position Based Crossover": // Bu caprazlama da tek cocuk elde ettigimiz icin 2 kere yapiyoruz parent1 = geneticOperations.PositionBasedCrossover(parents)[0]; parent2 = geneticOperations.PositionBasedCrossover(parents)[0]; parents[0] = parent1; parents[1] = parent2; break; } geneticOperations.Mutation(parent1, mutationProbability); geneticOperations.Mutation(parent2, mutationProbability); newPopulationList.AddRange(parents); } for (int j = 0; j < newPopulationList.Count; j++) { geneticOperations.CalculateFitnessFunction(newPopulationList[j], tspFile.edgeWeightType); maxFitness = Math.Max(maxFitness, newPopulationList[j].distance); minFitness = Math.Min(minFitness, newPopulationList[j].distance); meanFitness += newPopulationList[j].distance; meanFitness /= newPopulationList.Count; } populationList = new List <TspFile>(newPopulationList); populationList.Sort(); series.Points.Add(minFitness); } TspFile result = new TspFile(); minFitness = double.MaxValue; for (int k = 0; k < populationList.Count; k++) { listBox1.Items.Add(populationList[k].distance); if (minFitness > populationList[k].distance) { minFitness = populationList[k].distance; result = populationList[k]; } } /* * double max = 0, min = double.MaxValue, mean = 0; * for (int k = 0; k < populationList.Count; k++) * { * max = Math.Max(max, populationList[k].distance); * min = Math.Min(min, populationList[k].distance); * mean += populationList[k].distance; * } * mean /= populationList.Count; * listBox1.Items.Add("maximum fitness " + max); * listBox1.Items.Add("minimum fitness " + min); * listBox1.Items.Add("mean fitness " + mean); * */ /* * for (int j = 0; j < populationList.Count; j++) * { * geneticOperations.CalculateFitnessFunction(populationList[j], tspFile.edgeWeightType); * } */ this.Text = "Bitti"; SaveFile(result, minFitness); }
//Pozisyon bazli Crossover Fonksiyonu //Parent1`den Rastgele secilen pozisyonlardaki genler(sehirler) cocuk kromozoma aktarilir. //parent2`den sirasiyla cocukta olmayan genler aktarilirken olanlar goz ardi edilir. public TspFile[] PositionBasedCrossover(TspFile[] parents) { TspFile parent1 = parents[0]; TspFile parent2 = parents[1]; Random r = new Random(); List <int> positionArray = new List <int>(); int randomNumber = r.Next(0, parent1.cityList.Count); // random kac tane sayi gelecegini yine random seciyoruz. for (int i = 0; i < randomNumber; i++) { positionArray.Add(r.Next(0, parent1.cityList.Count)); // Bu listeye random sayilari atiyoruz. } //Rank Selection`dan gelen cocuklar TspFile child1 = new TspFile(); TspFile child2 = new TspFile(); for (int i = 0; i < parent1.cityList.Count; i++) { City city = new City { index = 0 }; child1.cityList.Add(city); } //Burda sehrin tekrar edip etmedigini kontrol ediyoruz. for (int i = 0; i < parent1.cityList.Count; i++) { if (positionArray.Exists(find => { if (find == i) { return(true); } else { return(false); } })) { child1.cityList[i] = parent1.cityList[i]; } } for (int j = 0; j < parent1.cityList.Count; j++) { if (!child1.cityList.Exists(city => { if (city.index == parent2.cityList[j].index) { return(true); } else { return(false); } })) { for (int k = 0; k < child1.cityList.Count; k++) { if (child1.cityList[k].index == 0) { child1.cityList[k] = parent2.cityList[j]; break; } } } } // child2 yapılacak? return(new TspFile[] { child1, child2 }); }
//Iki Noktali Caprazlama Fonksiyonu //Rank`tangelen 2 adet parent, random iki noktadan bolunuyor. public TspFile[] TwoPointCrossover(TspFile[] parents) { TspFile parent1 = parents[0]; TspFile parent2 = parents[1]; Random r = new Random(); int positionMin; int positionMax; do { positionMin = r.Next(1, parent1.cityList.Count); // İlk kesme noktası positionMax = r.Next(1, parent1.cityList.Count); // İkinci kesme noktası } while (positionMax == positionMin); //eger iki noktada esit gelirse diye if (positionMin > positionMax) //eger min deger max degerden buyuk olursa isimler dogru olmasi adina yer degistirme yapiyoruz. { int temp = positionMin; positionMin = positionMax; positionMax = temp; } TspFile child1 = new TspFile(); TspFile child2 = new TspFile(); // Crossover Child 1 //child1 = [----parent1----/----parent2----/----parent1---] yapisinin olusmasi icin gerekli ayristirma // [0--------------min-------------max---------sehirSayisi] child1.cityList.AddRange(parent1.cityList.GetRange(0, positionMin)); // child1.cityList.AddRange(parent2.cityList.GetRange(positionMin + 1, positionMax - positionMin)); child1.cityList.AddRange(parent1.cityList.GetRange(positionMax, parent2.cityList.Count - positionMax)); int location = positionMin; for (int i = 0; i < parent2.cityList.Count; i++) { if (!child1.cityList.Exists(city => { if (city.index == parent2.cityList[i].index) { return(true); } else { return(false); } })) { child1.cityList.Insert(location++, parent2.cityList[i]); } } // Crossover Child 2 //child2 = [----parent2----/----parent1----/----parent2---] child2.cityList.AddRange(parent2.cityList.GetRange(0, positionMin)); // child2.cityList.AddRange(parent1.cityList.GetRange(positionMin + 1, positionMax - positionMin)); child2.cityList.AddRange(parent2.cityList.GetRange(positionMax, parent2.cityList.Count - positionMax)); location = positionMin; for (int i = 0; i < parent1.cityList.Count; i++) { if (!child2.cityList.Exists(city => { if (city.index == parent1.cityList[i].index) { return(true); } else { return(false); } })) { child2.cityList.Insert(location++, parent1.cityList[i]); } } return(new TspFile[] { child1, child2 }); }
//Tek Noktali Caprazlama Fonksiyonu //Rank`tangelen 2 adet parent, random bir noktadan bolunuyor. public TspFile[] OnePointCrossover(TspFile[] parents) { TspFile parent1 = parents[0]; TspFile parent2 = parents[1]; Random r = new Random(); int position = r.Next(1, parent1.cityList.Count); TspFile child1 = new TspFile(); TspFile child2 = new TspFile(); // Crossover Child 1 //ilk cocuga 1. parent`in ilk parcasi + 2.parent`in ikinci parcasi ekleniyor + 2. parent'in seçilmeyen parçaları da ekleniyor child1.cityList.AddRange(parent1.cityList.GetRange(0, position)); for (int i = position; i < parent2.cityList.Count; i++) { //Bu surecte tekrar eden sehirlerin kontrolu saglaniyor. if (!child1.cityList.Exists(city => { if (city.index == parent2.cityList[i].index) { return(true); } else { return(false); } })) { child1.cityList.Add(parent2.cityList[i]); } } for (int i = 0; i < position; i++) { if (!child1.cityList.Exists(city => { if (city.index == parent2.cityList[i].index) { return(true); } else { return(false); } })) { child1.cityList.Add(parent2.cityList[i]); } } // Crossover Child 2 child2.cityList.AddRange(parent2.cityList.GetRange(0, position)); for (int i = position; i < parent2.cityList.Count; i++) { if (!child2.cityList.Exists(city => { if (city.index == parent1.cityList[i].index) { return(true); } else { return(false); } })) { child2.cityList.Add(parent1.cityList[i]); } } for (int i = 0; i < position; i++) { if (!child2.cityList.Exists(city => { if (city.index == parent1.cityList[i].index) { return(true); } else { return(false); } })) { child2.cityList.Add(parent1.cityList[i]); } } return(new TspFile[] { child1, child2 }); }