bumblebee Wiki Rss Feedhttp://bumblebee.codeplex.com/bumblebee Wiki Rss DescriptionUpdated Wiki: Homehttp://bumblebee.codeplex.com/wikipage?version=9<div class="wikidoc"><b>Project Description</b><br />Bumblebee is an Artificial Bee Colony (ABC) algorithm developed in F#. The algorithm is a randomized search method that mimics the behavior of bee hives: it dispatches "bees" to search for new solutions or explore the neighborhood of known solutions, and allocates new searches based on the quality of the results returned so far.<br /><br />The Solver will search for a solution to a problem, defined by 3 functions: <br />
<ul><li>a generator which returns new solutions, </li>
<li>a mutator which returns solutions close to an existing solution, </li>
<li>an evaluator, which evaluates the quality of a solution as a float. </li></ul>
<br />The solver dispatches bees to search in parallel (Scout Bees for new solutions, Active Bees for improvements around a known solution), and fires events every time an improved solution is found, until the search is stopped.<br />
<h3>The algorithm in action: Traveling Salesman Problem</h3>
The project includes a C# WPF application, which shows the algorithm working in real-time trying to find the shortest route between a list of randomly generated cities. The video below shows the bee busy on a 200-cities route:<br /><div class="video" style="text-align:Center"><span class="player"><object height="285px" width="320px"><param name="movie" value="http://www.youtube.com/v/PWbRBYKz4tw"></param><param name="wmode" value="transparent"></param><embed height="285px" width="320px" type="application/x-shockwave-flash" wmode="transparent" src="http://www.youtube.com/v/PWbRBYKz4tw" /></object></span><br /><span class="external"><a href="http://www.youtube.com/watch?v=PWbRBYKz4tw" target="_blank">Launch in another window</a></span></div><br />
<h3>Illustration: Traveling Salesman Problem</h3>
The objective is to find the shortest closed path connecting a list of cities. Starting with an array of Cities, we will generate new solutions by shuffling the initial list, and mutate solutions by either swapping a random pair of cities, or trying to remove crossings in the current solution. The Quality of a solution will be the negative of the distance, so that shorter distances have a higher quality than longer ones.<br /><br /><pre>
open System
open System.Diagnostics
open ClearLines.Bumblebee
[<DebuggerDisplay("{Name}")>]
type City = { Name: string; X: float; Y: float }
let Main =
// Euclidean distance between cities
let distance (C1, C2) =
( (C1.X - C2.X) ** 2.0 +
(C1.Y - C2.Y) ** 2.0) ** 0.5
// Permutation function:
// swaps items at first and second index
let swap (first: int, second) index =
if index = first then second
elif index = second then first
else index
// Swap 2 random elements in an Array
let randomSwap (rng: Random) items =
let last = Array.length items
let first = rng.Next(last)
let second = rng.Next(last)
Array.permute (fun i -> swap (first, second) i) items
// Fisher-Yates shuffle
let shuffle (rng: Random) items =
let rec shuffleTo (indexes: int[]) upTo =
match upTo with
| 0 -> indexes
| _ ->
let fst = rng.Next(upTo)
let temp = indexes.[fst]
indexes.[fst] <- indexes.[upTo]
indexes.[upTo] <- temp
shuffleTo indexes (upTo - 1)
let length = Array.length items
let indexes = [| 0 .. length - 1 |]
let shuffled = shuffleTo indexes (length - 1)
Array.permute (fun i -> shuffled.[i]) items
// Compute the total distance,
// summing distances between consecutive cities
let quality (circuit: City []) =
let length = Array.length circuit
[|
for i in 0 .. (length - 1) ->
distance(circuit.[i], circuit.[(i + 1) % length])
|]
|> Array.sum
// determines if 2 pairs of cities intersect
// see http://stackoverflow.com/a/3842157/114519
let intersects (city1, city2) (city3, city4) =
let det1 = (city1.X - city3.X) * (city2.Y - city3.Y) - (city2.X - city3.X) * (city1.Y - city3.Y)
let det2 = (city1.X - city4.X) * (city2.Y - city4.Y) - (city2.X - city4.X) * (city1.Y - city4.Y)
let det3 = (city3.X - city1.X) * (city4.Y - city1.Y) - (city4.X - city1.X) * (city3.Y - city1.Y)
let det4 = (city3.X - city2.X) * (city4.Y - city2.Y) - (city4.X - city2.X) * (city3.Y - city2.Y)
(det1 * det2 <= 0.0) && (det3 * det4 <= 0.0)
// Pick a random city in the circuit
// and look for an intersection afterwards.
// If an intersection is found, remove the crossing
let decross (rng: Random) (circuit: City []) =
let length = Array.length circuit
if length < 4
then circuit
else
let i = rng.Next(length - 3)
let c1, c2 = circuit.[i], circuit.[i + 1]
let intersection =
seq { i + 2 .. length - 2 }
|> Seq.tryFind (fun i -> intersects (c1, c2) (circuit.[i], circuit.[i+1]))
match intersection with
| None -> circuit
| Some(j) ->
let permutation x =
if x > i && x <= j then i + j + 1 - x
else x
Array.permute permutation circuit
// create an Array of cities on a circle:
// that way, we know the best length is about 2*Pi*R
let testRoute radius points =
let angle = Math.PI * 2.0 / (double)points
[|
for i in 1 .. points ->
{ Name = i.ToString();
X = Math.Cos(angle * (double) i) * radius;
Y = Math.Sin(angle * (double) i) * radius }
|]
let rng = RNG.create()
let root = testRoute 10.0 100 |> shuffle rng
let generator = fun (rng: Random) -> shuffle rng root
let mutator = fun (rng: Random) (circuit: City []) ->
let p = rng.NextDouble()
if ( p < 0.1 )
then decross rng circuit
else randomSwap rng circuit
let evaluator = fun (circuit: City []) -> - quality circuit
let problem = new Problem<City []>(generator, mutator, evaluator)
let displaySolution (circuit: City []) =
Array.iter (fun (c) -> Console.Write(c.Name + " ")) circuit
let foundSomething = fun (msg: SolutionMessage<City []>) ->
Console.WriteLine("{0}, {1}", msg.DateTime.TimeOfDay, msg.Quality)
// Console.WriteLine(displaySolution(msg.Solution))
Console.WriteLine()
let solver = new Solver<City []>()
solver.FoundSolution.Add foundSomething
Console.WriteLine("Press [Enter] to start")
let wait = Console.ReadLine()
Console.WriteLine("Starting: press [Enter] to stop search")
solver.Search problem |> ignore
let wait = Console.ReadLine()
solver.Stop()
Console.WriteLine("Search stopped: press [Enter] to close")
let wait = Console.ReadLine()
Console.WriteLine("Done")
</pre></div><div class="ClearBoth"></div>mathiasbThu, 07 Jun 2012 03:14:56 GMTUpdated Wiki: Home 20120607031456AUpdated Wiki: Homehttp://bumblebee.codeplex.com/wikipage?version=8<div class="wikidoc"><b>Project Description</b><br />Bumblebee is an Artificial Bee Colony (ABC) algorithm developed in F#. The algorithm is a randomized search method that mimics the behavior of bee hives: it dispatches "bees" to search for new solutions or explore the neighborhood of known solutions, and allocates new searches based on the quality of the results returned so far.<br /><br />The Solver will search for a solution to a problem, defined by 3 functions: <br />
<ul><li>a generator which returns new solutions, </li>
<li>a mutator which returns solutions close to an existing solution, </li>
<li>an evaluator, which evaluates the quality of a solution as a float. </li></ul>
<br />The solver dispatches bees to search in parallel (Scout Bees for new solutions, Active Bees for improvements around a known solution), and fires events every time an improved solution is found, until the search is stopped.<br />
<h3>The algorithm in action: Traveling Salesman Problem</h3>
The project includes a C# WPF application, which shows the algorithm working in real-time trying to find the shortest route between a list of randomly generated cities. The video below shows the bee busy on a 200-cities route:<br /><div class="video" style="text-align:Center"><span class="player"><object height="285px" width="320px"><param name="movie" value="http://www.youtube.com/v/PWbRBYKz4tw"></param><param name="wmode" value="transparent"></param><embed height="285px" width="320px" type="application/x-shockwave-flash" wmode="transparent" src="http://www.youtube.com/v/PWbRBYKz4tw" /></object></span><br /><span class="external"><a href="http://www.youtube.com/watch?v=PWbRBYKz4tw" target="_blank">Launch in another window</a></span></div><br />
<h3>Illustration: Traveling Salesman Problem</h3>
The objective is to find the shortest closed path connecting a list of cities. Starting with an array of Cities, we will generate new solutions by shuffling the initial list, and mutate solutions by either swapping a random pair of cities, or trying to remove crossings in the current solution. The Quality of a solution will be the negative of the distance, so that shorter distances have a higher quality than longer ones.<br /><br /><pre>
open System
open System.Diagnostics
open ClearLines.Bumblebee
[<DebuggerDisplay("{Name}")>]
type City = { Name: string; X: float; Y: float }
let Main =
// Euclidean distance between cities
let distance (C1, C2) =
( (C1.X - C2.X) ** 2.0 +
(C1.Y - C2.Y) ** 2.0) ** 0.5
// Permutation function:
// swaps items at first and second index
let swap (first: int, second) index =
if index = first then second
elif index = second then first
else index
// Swap 2 random elements in an Array
let randomSwap (rng: Random) items =
let last = Array.length items
let first = rng.Next(last)
let second = rng.Next(last)
Array.permute (fun i -> swap (first, second) i) items
// Fisher-Yates shuffle
let shuffle (rng: Random) items =
let rec shuffleTo (indexes: int[]) upTo =
match upTo with
| 0 -> indexes
| _ ->
let fst = rng.Next(upTo)
let temp = indexes.[fst]
indexes.[fst] <- indexes.[upTo]
indexes.[upTo] <- temp
shuffleTo indexes (upTo - 1)
let length = Array.length items
let indexes = [| 0 .. length - 1 |]
let shuffled = shuffleTo indexes (length - 1)
Array.permute (fun i -> shuffled.[i]) items
// Compute the total distance,
// summing distances between consecutive cities
let quality (circuit: City []) =
let length = Array.length circuit
[|
for i in 0 .. (length - 1) ->
distance(circuit.[i], circuit.[(i + 1) % length])
|]
|> Array.sum
// determines if 2 pairs of cities intersect
let intersects (city1, city2) (city3, city4) =
let det1 = (city1.X - city3.X) * (city2.Y - city3.Y) - (city2.X - city3.X) * (city1.Y - city3.Y)
let det2 = (city1.X - city4.X) * (city2.Y - city4.Y) - (city2.X - city4.X) * (city1.Y - city4.Y)
let det3 = (city3.X - city1.X) * (city4.Y - city1.Y) - (city4.X - city1.X) * (city3.Y - city1.Y)
let det4 = (city3.X - city2.X) * (city4.Y - city2.Y) - (city4.X - city2.X) * (city3.Y - city2.Y)
(det1 * det2 <= 0.0) && (det3 * det4 <= 0.0)
// Pick a random city in the circuit
// and look for an intersection afterwards.
// If an intersection is found, remove the crossing
let decross (rng: Random) (circuit: City []) =
let length = Array.length circuit
if length < 4
then circuit
else
let i = rng.Next(length - 3)
let c1, c2 = circuit.[i], circuit.[i + 1]
let intersection =
seq { i + 2 .. length - 2 }
|> Seq.tryFind (fun i -> intersects (c1, c2) (circuit.[i], circuit.[i+1]))
match intersection with
| None -> circuit
| Some(j) ->
let permutation x =
if x > i && x <= j then i + j + 1 - x
else x
Array.permute permutation circuit
// create an Array of cities on a circle:
// that way, we know the best length is about 2*Pi*R
let testRoute radius points =
let angle = Math.PI * 2.0 / (double)points
[|
for i in 1 .. points ->
{ Name = i.ToString();
X = Math.Cos(angle * (double) i) * radius;
Y = Math.Sin(angle * (double) i) * radius }
|]
let rng = RNG.create()
let root = testRoute 10.0 200 |> shuffle rng
let generator = fun (data: City []) (rng: Random) -> shuffle rng data
let mutator = fun (data: City []) (rng: Random) (circuit: City []) ->
let p = rng.NextDouble()
if ( p < 0.1 )
then decross rng circuit
else randomSwap rng circuit
let evaluator = fun (circuit: City []) -> - quality circuit
let problem = new Problem<City [], City []>(root, generator, mutator, evaluator)
let displaySolution (circuit: City []) =
Array.iter (fun (c) -> Console.Write(c.Name + " ")) circuit
let foundSomething = fun (msg: SolutionMessage<City []>) ->
Console.WriteLine("{0}, {1}", msg.DateTime.TimeOfDay, msg.Quality)
// Console.WriteLine(displaySolution(msg.Solution))
Console.WriteLine()
let solver = new Solver<City []>()
solver.FoundSolution.Add foundSomething
Console.WriteLine("Press [Enter] to start")
let wait = Console.ReadLine()
Console.WriteLine("Starting: press [Enter] to stop search")
solver.Solve problem |> ignore
let wait = Console.ReadLine()
solver.Stop()
Console.WriteLine("Search stopped: press [Enter] to close")
let wait = Console.ReadLine()
Console.WriteLine("Done")
</pre></div><div class="ClearBoth"></div>mathiasbTue, 29 May 2012 03:43:09 GMTUpdated Wiki: Home 20120529034309AUpdated Wiki: Resourceshttp://bumblebee.codeplex.com/wikipage?title=Resources&version=3<div class="wikidoc"><h1>Code samples</h1>
The source code contains an implementation of a Traveling Salesman Problem solver using Bumblebee, both in C# and F#. The C# implementation includes a WPF user interface, which displays the solver in action, reorganizing in real time the travel circuit as improvements are discovered.<br />
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Resources">Bumblebee Sort in F sharp</a> : sorting a list of integers using Bumblebee, from F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Resources">Bumblebee Sort in C sharp</a> : sorting a list of integers using Bumblebee, from C#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Resources">Fair partition in n groups</a> : partitioning a list of integers into lists of close total, F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bipartite-matching-FSharp&referringTitle=Resources">Bipartite-matching-FSharp</a> : matching 2 lists of points to minimize distance, F#</li></ul></div><div class="ClearBoth"></div>mathiasbSun, 01 Apr 2012 22:56:18 GMTUpdated Wiki: Resources 20120401105618PUpdated Wiki: Bipartite-matching-FSharphttp://bumblebee.codeplex.com/wikipage?title=Bipartite-matching-FSharp&version=1<div class="wikidoc">The code sample below was inspired by the following <a href="http://stackoverflow.com/questions/9863108/non-intersecting-line-segment">StackOverflow question on bipartite matching</a>.<br /><i>There are N starting points (purple) and N target points (green) in 2D. I want an algorithm that connects starting points to target points by a line segment (brown) without any of these segments intersecting (red) and while minimizing the cumulative length of all segments.</i><br />Check out this <a href="http://clear-lines.com/blog/post/Bipartite-matching-with-Bumblebee.aspx">blog post</a> for comments on the implementation!<br /><br /><pre>
open ClearLines.Bumblebee
open System
type Point = { X: float; Y: float }
let Main =
let rng = new Random()
let points = 100
let firstList = [ for i in 0 .. points -> { X = (float)i ; Y = float(i) } ]
let secondList = [ for i in 0 .. points -> { X = (float)i ; Y = float(i) } ]
let root = firstList, secondList
let swapper (first, second) index =
if index = first then second
elif index = second then first
else index
let swap list (rng: Random) =
let last = List.length list
let first = rng.Next(last)
let second = rng.Next(last)
List.permute (fun i -> swapper (first, second) i) list
let shuffle (rng: Random) list =
let rec shuffleUpTo index (array: int[]) =
match index with
| 0 -> array
| _ ->
let swapIndex = rng.Next(index + 1)
let temp = array.[index]
array.[index] <- array.[swapIndex]
array.[swapIndex] <- temp
shuffleUpTo (index - 1) array
let lastIndex = (List.length list - 1)
let shuffled = shuffleUpTo lastIndex [| 0 .. lastIndex |]
List.permute (fun i -> shuffled.[i]) list
let generate = fun (rng: Random) ->
(fst root |> shuffle rng, snd root)
let mutate = fun (rng: Random, solution) ->
(swap (fst solution) rng, snd solution)
let distance pair =
((fst pair).X - (snd pair).X) ** 2.0 + ((fst pair).Y - (snd pair).Y) ** 2.0
let evaluate = fun (solution: Point list * Point list) ->
List.zip (fst solution) (snd solution)
|> List.sumBy (fun p -> - distance p)
let problem = new Problem<Point list * Point list>(generate, mutate, evaluate)
let solver = new Solver<Point list * Point list>()
let foundSomething = fun (msg: SolutionMessage<Point list * Point list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre></div><div class="ClearBoth"></div>mathiasbSun, 01 Apr 2012 22:55:31 GMTUpdated Wiki: Bipartite-matching-FSharp 20120401105531PUpdated Wiki: API documentationhttp://bumblebee.codeplex.com/wikipage?title=API documentation&version=2<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.</div><div class="ClearBoth"></div>mathiasbSat, 07 Jan 2012 04:21:16 GMTUpdated Wiki: API documentation 20120107042116AUpdated Wiki: Resourceshttp://bumblebee.codeplex.com/wikipage?title=Resources&version=2<div class="wikidoc"><h1>Code samples</h1>
The source code contains an implementation of a Traveling Salesman Problem solver using Bumblebee, both in C# and F#. The C# implementation includes a WPF user interface, which displays the solver in action, reorganizing in real time the travel circuit as improvements are discovered.<br />
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Resources">Bumblebee Sort in F sharp</a> : sorting a list of integers using Bumblebee, from F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Resources">Bumblebee Sort in C sharp</a> : sorting a list of integers using Bumblebee, from C#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Resources">Fair partition in n groups</a> : partitioning a list of integers into lists of close total, F#</li></ul></div><div class="ClearBoth"></div>mathiasbSat, 07 Jan 2012 03:12:34 GMTUpdated Wiki: Resources 20120107031234AUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=6<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible.<br />
<h2><a href="http://bumblebee.codeplex.com/wikipage?title=API%20documentation&referringTitle=Documentation">API documentation</a></h2>
The <b><a href="http://bumblebee.codeplex.com/wikipage?title=API%20documentation&referringTitle=Documentation">API documentation</a></b> page provides an overview of the Solver API.<br />
<h2><a href="http://bumblebee.codeplex.com/wikipage?title=Resources&referringTitle=Documentation">Code Samples & Resources</a></h2>
The <b><a href="http://bumblebee.codeplex.com/wikipage?title=Resources&referringTitle=Documentation">Resources</a></b> page provides code samples illustrating how to use the Bumblebee Solver on a few problems, both in C# and F#.</div><div class="ClearBoth"></div>mathiasbSat, 07 Jan 2012 03:09:44 GMTUpdated Wiki: Documentation 20120107030944AUpdated Wiki: Resourceshttp://bumblebee.codeplex.com/wikipage?title=Resources&version=1<div class="wikidoc"><h1>Code samples</h1>
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Resources">Bumblebee Sort in F sharp</a> : sorting a list of integers using Bumblebee, from F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Resources">Bumblebee Sort in C sharp</a> : sorting a list of integers using Bumblebee, from C#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Resources">Fair partition in n groups</a> : partitioning a list of integers into lists of close total, F#</li></ul></div><div class="ClearBoth"></div>mathiasbSat, 07 Jan 2012 02:16:02 GMTUpdated Wiki: Resources 20120107021602AUpdated Wiki: API documentationhttp://bumblebee.codeplex.com/wikipage?title=API documentation&version=1<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h1>API overview</h1>
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.</div><div class="ClearBoth"></div>mathiasbSat, 07 Jan 2012 02:14:30 GMTUpdated Wiki: API documentation 20120107021430AUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=5<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Illustration/code samples on using Bumblebee</h2>
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Documentation">Bumblebee Sort in F sharp</a> : sorting a list of integers using Bumblebee, from F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Documentation">Bumblebee Sort in C sharp</a> : sorting a list of integers using Bumblebee, from C#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Documentation">Fair partition in n groups</a> : partitioning a list of integers into lists of close total, F#</li></ul>
<h1>API overview</h1>
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.<br />
<h2>Illustration/code samples on using Bumblebee</h2>
<b>BumblebeeSort: sorting a list of integers using Bumblebee</b>
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Documentation">Bumblebee Sort in F sharp</a> : how to use Bumblebee, from F#</li>
<li><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Documentation">Bumblebee Sort in C sharp</a> : how to use Bumblebee from C#</li></ul>
<ul><li><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Documentation">Fair partition in n groups</a> : partitioning a list of integers into lists of close total.</li></ul></div><div class="ClearBoth"></div>mathiasbFri, 06 Jan 2012 21:37:00 GMTUpdated Wiki: Documentation 20120106093700PUpdated Wiki: Fair partition in n groupshttp://bumblebee.codeplex.com/wikipage?title=Fair partition in n groups&version=2<div class="wikidoc">The code sample below is a F# solution that uses Bumblebee to solve the following problem, which came from <a href="http://stackoverflow.com/questions/8762230/what-is-an-algorithm-to-split-a-group-of-items-into-3-separate-groups-fairly" class="externalLink">this StackOverflow question<span class="externalLinkIcon"></span></a>:<br /><br /><i> Given a group of n items, each with a distinct value V(i), what is the best way to divide the items into 3 groups so the group with the highest value is minimIzed? Give the value of this largest group. </i><br /><br />The following is a F# implementation; to make the sample work, just create a F# Console app, add a reference to the Bumblebee dll (version 0.2), and paste in the following.<br /><br />Check out this <a href="http://www.clear-lines.com/blog/post/Fair-split-into-3-groups-using-Bumblebee.aspx" class="externalLink">blog post<span class="externalLinkIcon"></span></a> for comments on the implementation!<br /><br /><pre>
open ClearLines.Bumblebee
open System
type Allocation = { Element: int; Group: int }
let Main =
let groups = 3
let rng = new Random()
let root = [ for i in 0 .. 1000 -> rng.Next(0, 100000) ]
let generate = fun (rng: Random) ->
List.map (fun e -> { Element = e; Group = rng.Next(0, groups) }) root
let mutate = fun (rng: Random, solution: Allocation list) ->
let count = List.length solution
let changed = rng.Next(0, count)
solution |> List.mapi (fun i e ->
if i = changed then
{ Element = e.Element; Group = rng.Next(0, groups) }
else e)
let evaluate = fun (solution: Allocation list) ->
let groupValues =
[
for g in 0 .. (groups - 1) ->
List.filter (fun e -> e.Group = g) solution
|> List.sumBy (fun e -> e.Element);
]
List.min (groupValues) - List.max (groupValues) |> (float)
let problem = new Problem<Allocation list>(generate, mutate, evaluate)
let solver = new Solver<Allocation list>()
let displaySolution (solution: Allocation list) =
[
for g in 0 .. (groups - 1) ->
let group = List.filter (fun e -> e.Group = g) solution
Console.Write("Total group {0}: {1} // ", g, List.sumBy (fun e -> e.Element) group)
//List.map (fun i -> Console.Write("<{0},{1}> ", i.Element, i.Group)) group |> ignore
Console.WriteLine ()
]
let foundSomething = fun (msg: SolutionMessage<Allocation list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
displaySolution(msg.Solution) |> ignore
Console.WriteLine()
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre></div><div class="ClearBoth"></div>mathiasbFri, 06 Jan 2012 21:28:26 GMTUpdated Wiki: Fair partition in n groups 20120106092826PUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=4<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.<br />
<h2>Illustration: sorting a list of integers using Bumblebee</h2>
<a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Documentation">Bumblebee Sort in F sharp</a> : how to use Bumblebee from F#<br /><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Documentation">Bumblebee Sort in C sharp</a> : how to use Bumblebee from C#<br /><br /><a href="http://bumblebee.codeplex.com/wikipage?title=Fair%20partition%20in%20n%20groups&referringTitle=Documentation">Fair partition in n groups</a> : partitioning a list of integers into lists of close total.</div><div class="ClearBoth"></div>mathiasbFri, 06 Jan 2012 21:18:32 GMTUpdated Wiki: Documentation 20120106091832PUpdated Wiki: Fair partition in n groupshttp://bumblebee.codeplex.com/wikipage?title=Fair partition in n groups&version=1<div class="wikidoc">The code sample below is a F# solution that uses Bumblebee to solve the following problem, which came from <a href="http://stackoverflow.com/questions/8762230/what-is-an-algorithm-to-split-a-group-of-items-into-3-separate-groups-fairly" class="externalLink">this StackOverflow question<span class="externalLinkIcon"></span></a>.<br /><i> Given a group of n items, each with a distinct value V(i), what is the best way to divide the items into 3 groups so the group with the highest value is minimIzed? Give the value of this largest group. </i><br /><br /><pre>
open ClearLines.Bumblebee
open System
type Allocation = { Element: int; Group: int }
let Main =
let groups = 3
let rng = new Random()
let root = [ for i in 0 .. 1000 -> rng.Next(0, 100000) ]
let generate = fun (rng: Random) ->
List.map (fun e -> { Element = e; Group = rng.Next(0, groups) }) root
let mutate = fun (rng: Random, solution: Allocation list) ->
let count = List.length solution
let changed = rng.Next(0, count)
solution |> List.mapi (fun i e ->
if i = changed then
{ Element = e.Element; Group = rng.Next(0, groups) }
else e)
let evaluate = fun (solution: Allocation list) ->
let groupValues =
[
for g in 0 .. (groups - 1) ->
List.filter (fun e -> e.Group = g) solution
|> List.sumBy (fun e -> e.Element);
]
List.min (groupValues) - List.max (groupValues) |> (float)
let problem = new Problem<Allocation list>(generate, mutate, evaluate)
let solver = new Solver<Allocation list>()
let displaySolution (solution: Allocation list) =
[
for g in 0 .. (groups - 1) ->
let group = List.filter (fun e -> e.Group = g) solution
Console.Write("Total group {0}: {1} // ", g, List.sumBy (fun e -> e.Element) group)
//List.map (fun i -> Console.Write("<{0},{1}> ", i.Element, i.Group)) group |> ignore
Console.WriteLine ()
]
let foundSomething = fun (msg: SolutionMessage<Allocation list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
displaySolution(msg.Solution) |> ignore
Console.WriteLine()
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre></div><div class="ClearBoth"></div>mathiasbFri, 06 Jan 2012 21:16:55 GMTUpdated Wiki: Fair partition in n groups 20120106091655PUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=3<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.<br />
<h2>Illustration: sorting a list of integers using Bumblebee</h2>
<a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Documentation">Bumblebee Sort in F sharp</a> : how to use Bumblebee from F#<br /><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20C%20sharp&referringTitle=Documentation">Bumblebee Sort in C sharp</a> : how to use Bumblebee from C#</div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:11:53 GMTUpdated Wiki: Documentation 20111229051153AUpdated Wiki: Bumblebee Sort in C sharphttp://bumblebee.codeplex.com/wikipage?title=Bumblebee Sort in C sharp&version=1<div class="wikidoc"><h2>BumblebeeSort in C#</h2>
Our goal is to sort a list of integers in increasing order, using Bumblebee. First, let's create a Console application in C#, add a reference to the Bumblebee dll and FSharp.Core 4.0, and create our Main method.<br /><br /><pre>
using System;
using System.Collections.Generic;
using System.Linq;
namespace BumbleBeeSort.CSharp
{
using ClearLines.Bumblebee;
using Microsoft.FSharp.Control;
using Random = System.Random;
class Program
{
static void Main(string[] args)
{
</pre><br />We’ll start with a random list of integers:<br /><br /><pre>
var rng = new Random();
var root = new List<int>();
for (var i = 0; i < 100; i++)
{
root.Add(rng.Next(0, 100));
}
</pre><br />The type of solution we expect is a list of integers, therefore the problem will be a Problem<int list>.<br /><br />We need to define the Problem in a way that can be handled by Bumblebee. Bumblebee requires 3 functions to operate: a function to generate new solutions, a function to mutate an existing list, and a function to evaluate the quality of a solution.<br />Our approach will be to simply permute random elements in the list, without worrying about generating new solutions. In other words, we will just use Active bees to explore starting from the initial root solution, without Scouting for new solutions.<br /><br /><pre>
var generate = new Func<Random, List<int>>(
(random) => root);
var mutate = new Func<Tuple<Random, List<int>>, List<int>>
(tuple =>
{
var random = tuple.Item1;
var list = tuple.Item2;
var count = list.Count();
var first = random.Next(0, count);
var second = random.Next(0, count);
if (first == second)
{
return list;
}
var copy = new List<int>(list);
var firstElement = copy[first];
var secondElement = copy[second];
copy[second] = firstElement;
copy[first] = secondElement;
return copy;
});
</pre><br />The third element we need is an evaluation function, which will measure the quality of a list. In order to do this, for each element in the list, we will count how many items after that element are smaller (i.e. incorrectly sorted), and add a penalty of -1 for each.<br /><br /><pre>
var evaluate = new Func<List<int>, double>
(list =>
{
var count = list.Count();
var value = 0;
for (var i = 0; i < count; i++)
{
var head = list[i];
var subList = list.GetRange(i + 1, count - 1 - i);
value -= subList.Count(it => it < head);
}
return (double)value;
});
</pre><br />We can now create a Problem and instantiate the Solver:<br /><br /><pre>
var problem = new Problem<List<int>>(generate, mutate, evaluate);
var solver = new Solver<List<int>>();
</pre><br />Finally, we need to subscribe to the FoundSolution event that is fired by the Solver every time an improvement is found. We will write to the Console the current list of integers, as well as the time the solution was found and its quality:<br /><br /><pre>
var displaySolution = new Action<SolutionMessage<List<int>>>(
(message) =>
{
foreach (var i in message.Solution)
{
Console.Write(i.ToString() + " ");
}
Console.WriteLine();
});
var foundSomething = new FSharpHandler<SolutionMessage<List<int>>>(
(sender, message) =>
{
Console.WriteLine("New solution of quality {0} found at {1}",
message.Quality,
message.DateTime.TimeOfDay);
displaySolution(message);
});
</pre><br />We can now subscribe to the event, and launch the search.<br /><br /><pre>
solver.FoundSolution += foundSomething;
solver.Search(problem);
Console.ReadLine();
</pre><br />BumbleBeeSort is now ready to run: the Console will show the initial list of random numbers, being sorted as improved solutions are found by the bees. The solver will keep on running, until <b>Enter</b> is pressed.</div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:10:10 GMTUpdated Wiki: Bumblebee Sort in C sharp 20111229051010AUpdated Wiki: Bumblebee Sort in F sharphttp://bumblebee.codeplex.com/wikipage?title=Bumblebee Sort in F sharp&version=3<div class="wikidoc"><h2>BumblebeeSort in F#</h2>
Our goal is to sort a list of integers in increasing order, using Bumblebee. First, let's create a Console application in F#, add a reference to the Bumblebee dll, and create our Main method.<br /><br /><pre>
open ClearLines.Bumblebee
open System
let Main =
</pre><br />We’ll start with a random list of integers:<br /><br /><pre>
let rng = new Random()
let root =
[ for i in 0 .. 100 do yield rng.Next(0, 100)]
</pre><br />The type of solution we expect is a list of integers, therefore the problem will be a Problem<int list>.<br /><br />We need to define the Problem in a way that can be handled by Bumblebee. Bumblebee requires 3 functions to operate: a function to generate new solutions, a function to mutate an existing list, and a function to evaluate the quality of a solution.<br />Our approach will be to simply permute random elements in the list, without worrying about generating new solutions. In other words, we will just use Active bees to explore starting from the initial root solution, without Scouting for new solutions.<br /><br /><pre>
let generate = fun (rng: Random) -> root
let mutate = fun (rng: Random, solution: int list) ->
let count = List.length solution
let first = rng.Next(0, count)
let second = rng.Next(0, count)
if first = second then solution else
List.permute (fun (i) ->
if i = first then second
elif i = second then first
else i) solution
</pre><br />The third element we need is an evaluation function, which will measure the quality of a list. In order to do this, for each element in the list, we will count how many items after that element are smaller (i.e. incorrectly sorted), and add a penalty of -1 for each.<br /><br /><pre>
let evaluate = fun (solution: int list) ->
let value (list: int list) =
match list with
| [] -> 0
| _ -> List.sumBy (fun elem -> (if elem >= List.head list then 0 else -1)) (List.tail list)
let rec listValue (list: int list) acc =
match list with
| [] -> acc
| _ -> listValue (List.tail list) acc + value list
listValue solution 0 |> (float)
</pre><br />We can now create a Problem and instantiate the Solver:<br /><br /><pre>
let problem = new Problem<int list>(generate, mutate, evaluate)
let solver = new Solver<int list>()
</pre><br />Finally, we need to subscribe to the FoundSolution event that is fired by the Solver every time an improvement is found. We will write to the Console the current list of integers, as well as the time the solution was found and its quality:<br /><br /><pre>
let displaySolution (solution: int list) =
List.iter (fun (i) -> Console.Write(i.ToString() + " ")) solution
let foundSomething = fun (msg: SolutionMessage<int list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
displaySolution(msg.Solution)
Console.WriteLine()
</pre><br />We can now subscribe to the event, and launch the search.<br /><br /><pre>
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre><br />BumbleBeeSort is now ready to run: the Console will show the initial list of random numbers, being sorted as improved solutions are found by the bees. The solver will keep on running, until <b>Enter</b> is pressed.</div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:05:42 GMTUpdated Wiki: Bumblebee Sort in F sharp 20111229050542AUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=2<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.<br /><br /><a href="http://bumblebee.codeplex.com/wikipage?title=Bumblebee%20Sort%20in%20F%20sharp&referringTitle=Documentation">Bumblebee Sort in F sharp</a></div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:04:49 GMTUpdated Wiki: Documentation 20111229050449AUpdated Wiki: Bumblebee Sort in F sharphttp://bumblebee.codeplex.com/wikipage?title=Bumblebee Sort in F sharp&version=2<div class="wikidoc"><h2>BumblebeeSort in F#</h2>
Our goal is to sort a list of integers in increasing order, using Bumblebee. First, let's create a Console application in F#, add a reference to the Bumblebee dll, and create our Main method.<br /><br /><pre>
open ClearLines.Bumblebee
open System
let Main =
</pre><br />We’ll start with a random list of integers:<br /><br /><pre>
let rng = new Random()
let root =
[ for i in 0 .. 100 do yield rng.Next(0, 100)]
</pre><br />The type of solution we expect is a list of integers, therefore the problem will be a Problem<int list>.<br /><br />We need to define the Problem in a way that can be handled by Bumblebee. Bumblebee requires 3 functions to operate: a function to generate new solutions, a function to mutate an existing list, and a function to evaluate the quality of a solution.<br />Our approach will be to simply permute random elements in the list, without worrying about generating new solutions. In other words, we will just use Active bees to explore starting from the initial root solution, without Scouting for new solutions.<br /><br /><pre>
let generate = fun (rng: Random) -> root
let mutate = fun (rng: Random, solution: int list) ->
let count = List.length solution
let first = rng.Next(0, count - 1)
let second = rng.Next(0, count)
if first = second then solution else
List.permute (fun (i) ->
if i = first then second
elif i = second then first
else i) solution
</pre><br />The third element we need is an evaluation function, which will measure the quality of a list. In order to do this, for each element in the list, we will count how many items after that element are smaller (i.e. incorrectly sorted), and add a penalty of -1 for each.<br /><br /><pre>
let evaluate = fun (solution: int list) ->
let value (list: int list) =
match list with
| [] -> 0
| _ -> List.sumBy (fun elem -> (if elem >= List.head list then 0 else -1)) (List.tail list)
let rec listValue (list: int list) acc =
match list with
| [] -> acc
| _ -> listValue (List.tail list) acc + value list
listValue solution 0 |> (float)
</pre><br />We can now create a Problem and instantiate the Solver:<br /><br /><pre>
let problem = new Problem<int list>(generate, mutate, evaluate)
let solver = new Solver<int list>()
</pre><br />Finally, we need to subscribe to the FoundSolution event that is fired by the Solver every time an improvement is found. We will write to the Console the current list of integers, as well as the time the solution was found and its quality:<br /><br /><pre>
let displaySolution (solution: int list) =
List.iter (fun (i) -> Console.Write(i.ToString() + " ")) solution
let foundSomething = fun (msg: SolutionMessage<int list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
displaySolution(msg.Solution)
Console.WriteLine()
</pre><br />We can now subscribe to the event, and launch the search.<br /><br /><pre>
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre><br />BumbleBeeSort is now ready to run: the Console will show the initial list of random numbers, being sorted as improved solutions are found by the bees. The solver will keep on running, until <b>Enter</b> is pressed.</div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:02:51 GMTUpdated Wiki: Bumblebee Sort in F sharp 20111229050251AUpdated Wiki: Bumblebee Sort in F sharphttp://bumblebee.codeplex.com/wikipage?title=Bumblebee Sort in F sharp&version=1<div class="wikidoc"><h2>BumblebeeSort in F#</h2>
Our goal is to sort a list of integers in increasing order, using Bumblebee. First, let's create a Console application in F#, add a reference to the Bumblebee dll, and create our Main method.<br /><br /><pre>
open ClearLines.Bumblebee
open System
let Main =
</pre><br />We’ll start with a random list of integers:<br /><br /><pre>
let rng = new Random()
let root =
[ for i in 0 .. 100 do yield rng.Next(0, 100)]
</pre><br />The type of solution we expect is a list of integers, therefore the problem will be a Problem<int list>.<br /><br />We need to define the Problem in a way that can be handled by Bumblebee. Bumblebee requires 3 functions to operate: a function to generate new solutions, a function to mutate an existing list, and a function to evaluate the quality of a solution.<br />Our approach will be to simply permute random elements in the list, without worrying about generating new solutions. In other words, we will just use Active bees to explore starting from the initial root solution, without Scouting for new solutions.<br /><br /><pre>
let generate = fun (rng: Random) -> root
let mutate = fun (rng: Random, solution: int list) ->
let count = List.length solution
let first = rng.Next(0, count - 1)
let second = rng.Next(0, count)
if first = second then solution else
List.permute (fun (i) ->
if i = first then second
elif i = second then first
else i) solution
</pre><br />The third element we need is an evaluation function, which will measure the quality of a list. In order to do this, for each element in the list, we will count how many items after that element are smaller (i.e. incorrectly sorted), and add a penalty of -1 for each.<br /><br /><pre>
let evaluate = fun (solution: int list) ->
let value (list: int list) =
match list with
| [] -> 0
| _ -> List.sumBy (fun elem -> (if elem >= List.head list then 0 else -1)) (List.tail list)
let rec listValue (list: int list) acc =
match list with
| [] -> acc
| _ -> listValue (List.tail list) acc + value list
listValue solution 0 |> (float)
</pre><br />We can now create a Problem and instantiate the Solver:<br /><br /><pre>
let problem = new Problem<int list>(generate, mutate, evaluate)
let solver = new Solver<int list>()
</pre><br />Finally, we need to subscribe to the FoundSolution event that is fired by the Solver every time an improvement is found. We will write to the Console the current list of integers, as well as the time the solution was found and its quality:<br /><br /><pre>
let displaySolution (solution: int list) =
List.iter (fun (i) -> Console.Write(i.ToString() + " ")) solution
let foundSomething = fun (msg: SolutionMessage<int list>) ->
Console.WriteLine("New solution of quality {0} found at {1}", msg.Quality, msg.DateTime.TimeOfDay)
displaySolution(msg.Solution)
Console.WriteLine()
</pre><br />We can now subscribe to the event, and launch the search.<br /><br /><pre>
solver.FoundSolution.Add foundSomething
solver.Search(problem) |> ignore
Console.ReadLine() |> ignore
</pre><br /><br />BumbleBeeSort is now ready to run: the Console will show the initial list of random numbers, being sorted as improved solutions are found by the bees. The solver will keep on running, until <a href="http://bumblebee.codeplex.com/wikipage?title=Enter&referringTitle=Bumblebee%20Sort%20in%20F%20sharp">Enter</a> is pressed.</div><div class="ClearBoth"></div>mathiasbThu, 29 Dec 2011 05:02:08 GMTUpdated Wiki: Bumblebee Sort in F sharp 20111229050208AUpdated Wiki: Documentationhttp://bumblebee.codeplex.com/documentation?version=1<div class="wikidoc"><b>Bumblebee</b> is an Artificial Bee Colony solver, written in F#. The main class of Bumblebee is the <b>Solver</b>, and its purpose is to search for solutions to a generic <b>Problem</b> with the highest Quality possible. The Solver exposes two main methods, and an event: Search, Stop and FoundSolution.<br />
<h2>Search, Stop, and FoundSolution</h2>
Given a generic problem of type T (T being a Solution to the problem), Search will begin searching for improved solutions, and continue searching until Stop is called, which will interrupt the Search. Whenever a solution that is better than the current best is encountered, the Solver will raise the <b>FoundSolution</b> event, which returns a <b>SolutionMessage</b> containing the Solution, its Quality measurement, and the time the solution was found.<br /><br />It is impossible for the Solver to determine whether a Solution is optimal; therefore, the caller is responsible to decide when to terminate the Search by calling Stop. That call could be based on observing no improvement for a certain length of time, or on the rate of improvement between solutions, for instance.<br />
<h2>Defining the Problem</h2>
Defining the Problem is the complex part of the exercise. The <b>Search</b> method requires a <b>Problem</b> for the Solver to operate on:<br /><br />F#: <span class="codeInline">Search(problem: Problem<’a>)</span><br />C#: <span class="codeInline">Search(Problem<T> problem)</span><br /><br />A Problem is a generic class, and requires three functions: Generate, Mutate and Evaluate.<br /><br /><b>Evaluate</b> takes a solution and returns a float, which measures the Quality of the solution:<br /><br />F#: <span class="codeInline">'a -> float</span><br />C#: <span class="codeInline">Func<T, float></span><br /><br />Evaluate should be increasing with the Quality of the Solution, that is, if a solution is better than another, the value returned by Evaluate should be greater. The Solver will use that function to decide whether a new Solution is an improvement.<br /><br /><b>Generate</b> takes in a Random, and returns a Solution:<br /><br />F#: <span class="codeInline">Random -> ‘a</span><br />C#: <span class="codeInline">Func<Random, T></span><br /><br />The purpose of Generate is to produce new Solutions, regardless of what solutions have been identified by the Solver thus far. In terms of Bees activity, this represents a Bee exploring for new territory.<br /><br /><b>Mutate</b> takes in a Tuple consisting of a Random and a known Solution, and returns a Solution:<br /><br />F#: <span class="codeInline">(Random * ‘a) -> ‘a</span><br />C#: <span class="codeInline">Func<<Tuple<Random, T>, T></span><br /><br />The purpose of Mutate is to produce a Solution in the neighborhood of a known Solution. In terms of Bees activity, this represents a Bee exploring around a known territory, looking for potential improvements.</div><div class="ClearBoth"></div>mathiasbWed, 28 Dec 2011 04:25:17 GMTUpdated Wiki: Documentation 20111228042517A