Last active
October 10, 2017 12:38
-
-
Save sqeezy/b606c3042543f997fbd24d64a5030bcd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
type Agent<'T> = MailboxProcessor<'T> | |
let maxFloat = Double.MaxValue | |
let ran = Random 42 | |
let randomFloat ()= | |
float(ran.Next(-10000000,10000000)) | |
type MsgType = | |
| Finish | |
| UpdateGlobal of float | |
| Start | |
type GlobalStateApi = | |
|Register of Agent<MsgType> | |
|NewGlobalBest of float | |
|Start | |
type WorkerState = | |
{GlobalStateAgent : Agent<GlobalStateApi>; | |
LocalBest : float; | |
GlobalBest : float; | |
Running : bool | |
} | |
with | |
static member Create agent globalBest = | |
{LocalBest=globalBest;GlobalBest=globalBest;GlobalStateAgent=agent; Running = false} | |
member this.UpdateLocalBest value = {LocalBest=value;GlobalBest=this.GlobalBest;GlobalStateAgent=this.GlobalStateAgent;Running = this.Running} | |
member this.UpdateGlobalBest value = {LocalBest=this.LocalBest;GlobalBest=value;GlobalStateAgent=this.GlobalStateAgent;Running = this.Running} | |
member this.Start = {LocalBest=this.LocalBest;GlobalBest=this.GlobalBest;GlobalStateAgent=this.GlobalStateAgent;Running = true} | |
let Worker globalStateAgent = Agent.Start(fun inbox -> | |
let rec loop (state:WorkerState) = async{ | |
let! msg = inbox.TryReceive(1) | |
match msg with | |
|Some (value : MsgType) -> | |
match value with | |
|MsgType.Start -> return! loop state.Start | |
|Finish -> return () | |
|UpdateGlobal newGlobal -> | |
let newState = state.UpdateGlobalBest newGlobal | |
return! loop newState | |
|None -> | |
if state.Running then | |
let newTest = randomFloat() | |
if newTest < state.LocalBest then | |
let newState = state.UpdateLocalBest newTest | |
if newTest < state.GlobalBest then | |
state.GlobalStateAgent.Post(NewGlobalBest newTest) | |
return! loop newState | |
return! loop state | |
} | |
let initialState = (WorkerState.Create globalStateAgent maxFloat) | |
loop initialState | |
) | |
type GlobalState = {Agents : Agent<MsgType> list;GlobalBest : float} with | |
member this.UpdateBest newBest = {Agents=this.Agents;GlobalBest =newBest} | |
member this.AddAgent agent = {Agents=agent::this.Agents;GlobalBest=this.GlobalBest} | |
let GlobalStateAgent () = | |
Agent.Start(fun inbox -> | |
let sendNewBestToAllAgents (agents:list<Agent<MsgType>>) best = | |
let sendNewBestToAgent agent = (agent:Agent<MsgType>).Post(UpdateGlobal best) | |
agents |> List.map sendNewBestToAgent | |
let rec loop state = | |
async{ | |
let! msg = inbox.TryReceive(1) | |
match msg with | |
|Some call -> | |
match call with | |
|Register agent -> return! loop (state.AddAgent(agent):GlobalState) | |
|Start -> | |
let startAgent (agent : Agent<MsgType>) = agent.Post(MsgType.Start) | |
List.map startAgent state.Agents |> ignore | |
return! loop state | |
|NewGlobalBest value -> | |
match value < state.GlobalBest with | |
|true -> | |
sendNewBestToAllAgents state.Agents value |> ignore | |
printfn "New global best %A" value | |
return! loop (state.UpdateBest value) | |
|false -> | |
return! loop state | |
|None -> return! loop state | |
} | |
loop {Agents=[];GlobalBest=0.0} | |
) | |
[<EntryPoint>] | |
let main argv = | |
let hub = GlobalStateAgent() | |
let createWorker () = Worker hub | |
let register w = hub.Post(Register w) | |
let createAndRegister = createWorker >> register | |
[1..10] | |
|> fun _ -> createAndRegister() | |
hub.Post(Start) | |
while true do | |
Console.WriteLine "wait" | |
Threading.Thread.Sleep 1000 | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment