0 оценок0% нашли этот документ полезным (0 голосов)
54 просмотров9 страниц
The document describes code for simulating a bee colony algorithm to solve a traveling salesman problem. It defines classes like Program, Hive, Bee, and CitiesData. The Hive class represents the bee colony and contains methods like GenerateRandomMemoryMatrix() to initialize bee solutions randomly and MeasureOfQuality() to evaluate path lengths. The algorithm runs for a maximum number of cycles, where each cycle represents actions by all bees. It tracks the best found solution and allows bees to explore neighbor solutions to try improving the current best path.
The document describes code for simulating a bee colony algorithm to solve a traveling salesman problem. It defines classes like Program, Hive, Bee, and CitiesData. The Hive class represents the bee colony and contains methods like GenerateRandomMemoryMatrix() to initialize bee solutions randomly and MeasureOfQuality() to evaluate path lengths. The algorithm runs for a maximum number of cycles, where each cycle represents actions by all bees. It tracks the best found solution and allows bees to explore neighbor solutions to try improving the current best path.
The document describes code for simulating a bee colony algorithm to solve a traveling salesman problem. It defines classes like Program, Hive, Bee, and CitiesData. The Hive class represents the bee colony and contains methods like GenerateRandomMemoryMatrix() to initialize bee solutions randomly and MeasureOfQuality() to evaluate path lengths. The algorithm runs for a maximum number of cycles, where each cycle represents actions by all bees. It tracks the best found solution and allows bees to explore neighbor solutions to try improving the current best path.
// Use VS to create a C# Console Application named SimulatedBeeColony.
// Replace the contents of file Program.cs with this code.
using System; using System.Linq; using System.Threading.Tasks; namespace SimulatedBeeColony { class Program { static void Main(string[] args) { try { Console.WriteLine("\nBegin Simulated Bee Colony algorithm demo\n "); Console.WriteLine("Loading cities data for SBC Traveling Salesma n Problem analysis"); CitiesData citiesData = new CitiesData(20); Console.WriteLine(citiesData.ToString()); Console.WriteLine("Number of cities = " + citiesData.cities.Leng th); Console.WriteLine("Number of possible paths = " + citiesData.Num berOfPossiblePaths().ToString("#,###")); Console.WriteLine("Best possible solution (shortest path) length = " + citiesData.ShortestPathLength().ToString("F4")); int totalNumberBees = 500; // Ideal numbers are: Active 75% / Inactive 10% / Scout 15% int numberActive = Convert.ToInt32(totalNumberBees * .75); int numberInactive = Convert.ToInt32(totalNumberBees * .10); ; int numberScout = Convert.ToInt32(totalNumberBees * .15); ; //int maxNumberVisits = 300; //int maxNumberCycles = 32450; int maxNumberVisits = 95; int maxNumberCycles = 10570; //int maxNumberVisits = 300; // proportional to # of possible ne ighbors to given solution //int maxNumberCycles = 32450; Hive hive = new Hive(totalNumberBees, numberInactive, numberActi ve, numberScout, maxNumberVisits, maxNumberCycles, citiesData); Console.WriteLine("\nInitial random hive"); Console.WriteLine(hive); bool doProgressBar = true; hive.Solve(doProgressBar); Console.WriteLine("\nFinal hive"); Console.WriteLine(hive); Console.WriteLine("End Simulated Bee Colony demo"); Console.ReadLine(); } catch (Exception ex) { Console.WriteLine("Fatal: " + ex.Message); Console.ReadLine(); } } // Main() } // class Program class Hive { public class Bee { public int status; // 0 = inactive, 1 = active, 2 = scout public char[] memoryMatrix; // problem-specific. a path of cities. public double measureOfQuality; // smaller values are better. total distance of path. public int numberOfVisits; public Bee(int status, char[] memoryMatrix, double measureOfQuality, int numberOfVisits) { this.status = status; this.memoryMatrix = new char[memoryMatrix.Length]; Array.Copy(memoryMatrix, this.memoryMatrix, memoryMatrix.Length) ; this.measureOfQuality = measureOfQuality; this.numberOfVisits = numberOfVisits; } public override string ToString() { string s = ""; s += "Status = " + this.status + "\n"; s += " Memory = " + "\n"; for (int i = 0; i < this.memoryMatrix.Length - 1; ++i) s += this.memoryMatrix[i] + "->"; s += this.memoryMatrix[this.memoryMatrix.Length - 1] + "\n"; s += " Quality = " + this.measureOfQuality.ToString("F4"); s += " Number visits = " + this.numberOfVisits; return s; } } // Bee static Random random = null; // multipurpose public CitiesData citiesData; // this is the problem-specific data we wa nt to optimize public int totalNumberBees; // mostly for readability in the object cons tructor call public int numberInactive; public int numberActive; public int numberScout; public int maxNumberCycles; // one cycle represents an action by all bee s in the hive //public int maxCyclesWithNoImprovement; // deprecated public int maxNumberVisits; // max number of times bee will visit a give n food source without finding a better neighbor public double probPersuasion = 0.95; // probability inactive bee is pers uaded by better waggle solution public double probMistake = 0.01; // probability an active bee will reje ct a better neighbor food source OR accept worse neighbor food source public Bee[] bees; public char[] bestMemoryMatrix; // problem-specific public double bestMeasureOfQuality; public int[] indexesOfInactiveBees; // contains indexes into the bees ar ray public override string ToString() { string s = ""; s += "Best path found: "; for (int i = 0; i < this.bestMemoryMatrix.Length - 1; ++i) s += this.bestMemoryMatrix[i] + "->"; s += this.bestMemoryMatrix[this.bestMemoryMatrix.Length - 1] + "\n"; s += "Path quality: "; if (bestMeasureOfQuality < 10000.0) s += bestMeasureOfQuality.ToString("F4") + "\n"; else s += bestMeasureOfQuality.ToString("#.####e+00"); s += "\n"; return s; } public Hive(int totalNumberBees, int numberInactive, int numberActive, i nt numberScout, int maxNumberVisits, int maxNumberCycles, CitiesData citiesData) { random = new Random(0); this.totalNumberBees = totalNumberBees; this.numberInactive = numberInactive; this.numberActive = numberActive; this.numberScout = numberScout; this.maxNumberVisits = maxNumberVisits; this.maxNumberCycles = maxNumberCycles; //this.citiesData = new CitiesData(citiesData.cities.Length); // hiv e's copy of problem-specific data this.citiesData = citiesData; // reference to CityData // this.probPersuasion & this.probMistake are hard-coded in class de finition this.bees = new Bee[totalNumberBees]; // Provides the baseline best random memory matrix this.bestMemoryMatrix = GenerateRandomMemoryMatrix(); // alternative initializations are possible this.bestMeasureOfQuality = MeasureOfQuality(this.bestMemoryMatrix); this.indexesOfInactiveBees = new int[numberInactive]; // indexes of bees which are currently inactive for (int i = 0; i < totalNumberBees; ++i) // initialize each bee, an d best solution { int currStatus; // depends on i. need status before we can initi alize Bee if (i < numberInactive) { currStatus = 0; // inactive indexesOfInactiveBees[i] = i; // curr bee is inactive } else if (i < numberInactive + numberScout) { currStatus = 2; // scout } else { currStatus = 1; // active } char[] randomMemoryMatrix = GenerateRandomMemoryMatrix(); double mq = MeasureOfQuality(randomMemoryMatrix); int numberOfVisits = 0; bees[i] = new Bee(currStatus, randomMemoryMatrix, mq, numberOfVi sits); // instantiate current bee // does this bee have best solution? if (bees[i].measureOfQuality < bestMeasureOfQuality) // curr bee is better (< because smaller is better) { Array.Copy(bees[i].memoryMatrix, this.bestMemoryMatrix, bees [i].memoryMatrix.Length); this.bestMeasureOfQuality = bees[i].measureOfQuality; } } // each bee } // TravelingSalesmanHive ctor public char[] GenerateRandomMemoryMatrix() { char[] result = new char[this.citiesData.cities.Length]; // // probl em-specific Array.Copy(this.citiesData.cities, result, this.citiesData.cities.Le ngth); for (int i = 0; i < result.Length; i++) // Fisher-Yates (Knuth) shuf fle { int r = random.Next(i, result.Length); char temp = result[r]; result[r] = result[i]; result[i] = temp; } return result; } // GenerateRandomMemoryMatrix() public char[] GenerateNeighborMemoryMatrix(char[] memoryMatrix) { char[] result = new char[memoryMatrix.Length]; Array.Copy(memoryMatrix, result, memoryMatrix.Length); int ranIndex = random.Next(0, result.Length); // [0, Length-1] inclu sive int adjIndex; if (ranIndex == result.Length - 1) adjIndex = 0; else adjIndex = ranIndex + 1; char tmp = result[ranIndex]; result[ranIndex] = result[adjIndex]; result[adjIndex] = tmp; return result; } // GenerateNeighborMemoryMatrix() public double MeasureOfQuality(char[] memoryMatrix) { double answer = 0.0; for (int i = 0; i < memoryMatrix.Length - 1; ++i) { char c1 = memoryMatrix[i]; char c2 = memoryMatrix[i + 1]; double d = this.citiesData.Distance(c1, c2); answer += d; } return answer; } // MeasureOfQuality() public void Solve(bool doProgressBar) // find best Traveling Salesman Pr oblem solution { bool pb = doProgressBar; // just want a shorter variable int numberOfSymbolsToPrint = 10; // 10 units so each symbol is 10.0% progress int increment = this.maxNumberCycles / numberOfSymbolsToPrint; if (pb) Console.WriteLine("\nEntering SBC Traveling Salesman Problem algorithm main processing loop\n"); if (pb) Console.WriteLine("Progress: |==========|"); // 10 units so each symbol is 10% progress if (pb) Console.Write(" "); int cycle = 0; var sw = System.Diagnostics.Stopwatch.StartNew(); while (cycle < this.maxNumberCycles) { for (int i = 0; i < this.totalNumberBees; ++i) // each bee { switch (this.bees[i].status) { case 1: ProcessActiveBee(i); break; case 2: ProcessScoutBee(i); break; case 0: //ProcessInactiveBee(i); break; } } // for each bee
++cycle; // print a progress bar if (pb && cycle % increment == 0) Console.Write("^"); } // main while processing loop sw.Stop(); Console.WriteLine(" Total Time: " + sw.ElapsedMilliseconds); if (pb) Console.WriteLine(""); // end the progress bar } // Solve() private void ProcessInactiveBee(int i) { return; // not used in this implementation } private void ProcessActiveBee(int i) { char[] neighbor = GenerateNeighborMemoryMatrix(bees[i].memoryMatrix) ; // find a neighbor solution double neighborQuality = MeasureOfQuality(neighbor); // get its qual ity double prob = random.NextDouble(); // used to determine if bee makes a mistake; compare against probMistake which has some small value (~0.01) bool memoryWasUpdated = false; // used to determine if bee should pe rform a waggle dance when done bool numberOfVisitsOverLimit = false; // used to determine if bee wi ll convert to inactive status if (neighborQuality < bees[i].measureOfQuality) // active bee found better neighbor (< because smaller values are better) { if (prob < probMistake) // bee makes mistake: rejects a better n eighbor food source { ++bees[i].numberOfVisits; // no change to memory but update number of visits if (bees[i].numberOfVisits > maxNumberVisits) numberOfVisits OverLimit = true; } else // bee does not make a mistake: accepts a better neighbor { Array.Copy(neighbor, bees[i].memoryMatrix, neighbor.Length); // copy neighbor location into bee's memory bees[i].measureOfQuality = neighborQuality; // update the qu ality bees[i].numberOfVisits = 0; // reset counter memoryWasUpdated = true; // so that this bee will do a waggl e dance } } else // active bee did not find a better neighbor { //Console.WriteLine("c"); if (prob < probMistake) // bee makes mistake: accepts a worse ne ighbor food source { Array.Copy(neighbor, bees[i].memoryMatrix, neighbor.Length); // copy neighbor location into bee's memory bees[i].measureOfQuality = neighborQuality; // update the qu ality bees[i].numberOfVisits = 0; // reset memoryWasUpdated = true; // so that this bee will do a waggl e dance } else // no mistake: bee rejects worse food source { ++bees[i].numberOfVisits; if (bees[i].numberOfVisits > maxNumberVisits) numberOfVisits OverLimit = true; } } // at this point we need to determine a.) if the number of visits ha s been exceeded in which case bee becomes inactive // or b.) memory was updated in which case check to see if new memor y is a global best, and then bee does waggle dance // or c.) neither in which case nothing happens (bee just returns to hive). if (numberOfVisitsOverLimit == true) { bees[i].status = 0; // current active bee transitions to inactiv e bees[i].numberOfVisits = 0; // reset visits (and no change to th is bees memory) int x = random.Next(numberInactive); // pick a random inactive b ee. x is an index into a list, not a bee ID bees[indexesOfInactiveBees[x]].status = 1; // make it active indexesOfInactiveBees[x] = i; // record now-inactive bee 'i' in the inactive list } else if (memoryWasUpdated == true) // current bee returns and perfor ms waggle dance { // first, determine if the new memory is a global best. note tha t if bee has accepted a worse food source this can't be true if (bees[i].measureOfQuality < this.bestMeasureOfQuality) // the modified bee's memory is a new global best (< because smaller is better) { Array.Copy(bees[i].memoryMatrix, this.bestMemoryMatrix, bees [i].memoryMatrix.Length); // update global best memory this.bestMeasureOfQuality = bees[i].measureOfQuality; // upd ate global best quality } DoWaggleDance(i); } else // number visits is not over limit and memory was not updated s o do nothing (return to hive but do not waggle) { return; } } // ProcessActiveBee() private void ProcessScoutBee(int i) { char[] randomFoodSource = GenerateRandomMemoryMatrix(); // scout bee finds a random food source. . . double randomFoodSourceQuality = MeasureOfQuality(randomFoodSource); // and examines its quality if (randomFoodSourceQuality < bees[i].measureOfQuality) // scout bee has found a better solution than its current one (< because smaller measure is better) { Array.Copy(randomFoodSource, bees[i].memoryMatrix, randomFoodSou rce.Length); // unlike active bees, scout bees do not make mistakes bees[i].measureOfQuality = randomFoodSourceQuality; // no change to scout bee's numberOfVisits or status // did this scout bee find a better overall/global solution? if (bees[i].measureOfQuality < bestMeasureOfQuality) // yes, bet ter overall solution (< because smaller is better) { Array.Copy(bees[i].memoryMatrix, this.bestMemoryMatrix, bees [i].memoryMatrix.Length); // copy scout bee's memory to global best this.bestMeasureOfQuality = bees[i].measureOfQuality; } // better overall solution DoWaggleDance(i); // scout returns to hive and does waggle dance } // if scout bee found better solution } // ProcessScoutBee() private void DoWaggleDance(int i) { for (int ii = 0; ii < numberInactive; ++ii) // each inactive/watcher bee { int b = indexesOfInactiveBees[ii]; // index of an inactive bee if (bees[b].status != 0) throw new Exception("Catastrophic logic error when scout bee waggles dances"); if (bees[b].numberOfVisits != 0) throw new Exception("Found an i nactive bee with numberOfVisits != 0 in Scout bee waggle dance routine"); if (bees[i].measureOfQuality < bees[b].measureOfQuality) // scou t bee has a better solution than current inactive/watcher bee (< because smaller is better) { double p = random.NextDouble(); // will current inactive bee be persuaded by scout's waggle dance? if (this.probPersuasion > p) // this inactive bee is persuad ed by the scout (usually because probPersuasion is large, ~0.90) { Array.Copy(bees[i].memoryMatrix, bees[b].memoryMatrix, b ees[i].memoryMatrix.Length); bees[b].measureOfQuality = bees[i].measureOfQuality; } // inactive bee has been persuaded } // scout bee has better solution than watcher/inactive bee } // each inactive bee } // DoWaggleDance() } // class ShortestPathHive class CitiesData { public char[] cities; public CitiesData(int numberCities) { this.cities = new char[numberCities]; this.cities[0] = 'A'; for (int i = 1; i < this.cities.Length; ++i) this.cities[i] = (char)(this.cities[i - 1] + 1); } public double Distance(char firstCity, char secondCity) { return firstCity < secondCity ? 1.0*((int) secondCity - (int) firstCity) : 1.5*((int) firstCity - (int) secondCity); } public double ShortestPathLength() { return 1.0 * (this.cities.Length - 1); } public long NumberOfPossiblePaths() { long n = this.cities.Length; long answer = 1; for (int i = 1; i <= n; ++i) checked { answer *= i; } return answer; } public override string ToString() { string s = ""; s += "Cities: "; for (int i = 0; i < this.cities.Length; ++i) s += this.cities[i] + " "; return s; } } // class CitiesData } // ns