Skip to content

Instantly share code, notes, and snippets.

@eulerfx
Last active May 10, 2018 14:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eulerfx/e6c9d76f65026d3279432fc89c06c7cb to your computer and use it in GitHub Desktop.
Save eulerfx/e6c9d76f65026d3279432fc89c06c7cb to your computer and use it in GitHub Desktop.
F# Poisson process
open System
open System.Threading
let private disposable (dispose:unit -> unit) =
{ new IDisposable with member __.Dispose () = dispose () }
/// Creates an observable which triggers based on intervals specified by the input sequence.
let ofDelays (delays:TimeSpan seq) : IObservable<DateTimeOffset> =
{ new IObservable<_> with
member __.Subscribe obs =
let en = delays.GetEnumerator ()
let mutable timer : Timer = Unchecked.defaultof<_>
let dispose () =
if not (isNull timer) then timer.Dispose ()
en.Dispose ()
let setNext () =
try
if en.MoveNext () then
timer.Change (int en.Current.TotalMilliseconds, Timeout.Infinite) |> ignore
else
obs.OnCompleted ()
dispose ()
with ex ->
obs.OnError ex
dispose ()
let tick (_:obj) =
obs.OnNext DateTimeOffset.UtcNow
setNext ()
timer <- new Timer(TimerCallback(tick))
setNext ()
disposable dispose }
/// Returns a sequence of time spans which fillow an exponential distribution based on the
/// specified rate parameter.
let expInterArrivalSequence (ratePerSec:float) : TimeSpan seq = seq {
let rng = Random()
let delay () = -log (1.0 - rng.NextDouble ()) / ratePerSec
while true do
yield delay () |> TimeSpan.FromSeconds }
/// Creates an event which triggers based on exponentially distributed intervals
/// thereby simulating a poisson process.
let poissonEvent (ratePerSec:float) : IObservable<DateTimeOffset> =
ratePerSec
|> expInterArrivalSequence
|> ofDelays
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment