Anda di halaman 1dari 9

// 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

Anda mungkin juga menyukai