The other day at the local Erlang users group, the presenter asked for other people to come up with topics and presentations. I decided it would be fun and interesting to work on some algorithm related projects. The original credit for this specific project idea has to go to James McCaffery for his original article in MSDN. I highly recommend looking up his articles.

Important Notice: Please understand, I am a complete novice in Erlang. My terminology and methods are probably aberrant, but this was done as a learning exercise for me. I thought it would be fun to share.

The Algorithm

In summary, a Simulated Bee Colony algorithm very roughly simulates bees foraging for food. The idea being that instead of looking for the best “food source”, the algorithm is looking for the best solution in some problem space. My understanding is that it is best applied to a problem space that has both many possible local minima. There is an added requirement that you are able get a candidate solution that is “near” some given solution.

How it does this is by creating 3 populations of bees: Scouts, Active Foragers, and Inactive Foragers.

Scouts – This kind of bee will randomly select candidate solutions, if it finds a new personal best, it will return to the hive and tell any Inactive Foragers that it found a new good solution.

– This kind of bee will randomly select candidate solutions, if it finds a new personal best, it will return to the hive and tell any Inactive Foragers that it found a new good solution. Active Foragers – This kind of bee will return to it’s last know best solution when it searches and look at possible neighbor solutions. If it finds a new best it use that. Similar to the scouts, it will also notify any Inactive Foragers that it has found a new good solution.

– This kind of bee will return to it’s last know best solution when it searches and look at possible neighbor solutions. If it finds a new best it use that. Similar to the scouts, it will also notify any Inactive Foragers that it has found a new good solution. Inactive Foragers – This kind of bee will wait at the hive and when a scout or active forager comes back it will evaluate new good solutions and see if it is better than what it had before.

Active foragers transition to inactive after some period of foraging. The original project used a certain number of failed attempts to find a new personal best. When a bee goes from Active to Inactive, another Inactive bee will become active. You can think of it like as the bee lands in the hive one of the waiting bees takes off. To help prevent the algorithm from getting stuck in local minima, there is some additional randomness in two areas. The first is that scouts and active foragers don’t always select the a new personal best solution correctly. The second area is that the rate that scouts and active foragers convince the inactive foragers is not 100%. I don’t understand currently the best practices for determining optimal rates of error/persuasion.

The original solution

In the original version all the bees were objects with a few properties and had their state updated by one thread in a loop. See the original article for a detailed look at how the C# version of the code worked. You can get a basic idea of the flow for the application though with the snippets below. It was not a complicated process.

Reworked in Erlang

As soon as I finished implementing the original articles C# code, it occurred to me that this would be a much more interesting program if each bee were autonomous and not strapped into an inline loop. After a little thought I decided it would be a great fit to start up a state machine for each bee and one for the hive itself. I would use the hive as a mediator of intra-bee communication.

When I was done, I ended up with it broken out into the following modules: (Code available here)

Problem Definitions simpleprob.erl – A simple problem definition that I used to test that everything was communicating. wordprob.erl – A more complicated problem with a large problem space. tspprob.erl – A cone of the original traveling salesman problem from the original article.

Hive/Bee Files hive.erl – This file has the hive class and most is used as the entry point to the solver. bee.erl – The bee state machine.



To start up the the solver for a given problem, you would do something like the following in the erl.

Hive.erl

At the top of the hive module I created the record type “hiveState” to capture the current context of the hive. In addition, I also declared several constants to control the number of bees and how long they should live.

Next we have the initialization call. This is the only function exposed from the hive module. It creates a callback for the main process, starts up the hive by calling “run_hive” on a new process, then begins to create processes for each bee. Finally it waits for the solution to be returned via it’s callback.

The hive_run function is a receiver whose only job is to wait for messages coming from the bees. It can receive when a bee finds a new personal best solution and notify the inactive bees. The hive also keeps track of when bees return to the hive and has the responsibility of notifying an inactive bee to take off. Finally it also keeps track of how many bees are left alive. When every bee is dead, it will return the best solution it has found so far.

bee.erl

The bee module is setup similarly. At the top I defined the constants that are used by the bee and a record to maintain it’s state.

Next we have the function that is used to start up the new bee processes. Notice that I am using the cryptographic random function to see the standard random number generator. I learn through experimentation that I was generating the processes so fast that all the random number generators were creating the same sequences. By using the crytpo random seeds this eliminates that problem. Most of this method is just setting up the initial state of the bee.

The majority of the rest of the bee module are the functions that make up the main state machine. I primarily used pattern matching for handing each state.

Finally I have a few helper functions to help with modifying state and adding probability to the system.

All in all this was a fun experience to play around with a language that I have very little experience with. I plan on working on converting some other organically inspired algorithms over to it for fun. I look forward to questions, comments and suggestions.