From e0ffc5902acbec8bbe502532d6ef174ca2614a64 Mon Sep 17 00:00:00 2001
From: baggepinnen <cont-frb@ulund.org>
Date: Wed, 14 Feb 2018 06:17:05 +0100
Subject: [PATCH] work on pf

---
 pf.jl     |  60 +++++++++++-----------
 pf_vec.jl | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+), 29 deletions(-)
 create mode 100644 pf_vec.jl

diff --git a/pf.jl b/pf.jl
index d7bf98a..bc89631 100644
--- a/pf.jl
+++ b/pf.jl
@@ -1,5 +1,4 @@
-
-using StatsBase, Plots
+using StatsBase, Plots, Distributions
 
 function pf!(xp,w, y, N, g, f, σw )
     T = length(y)
@@ -7,8 +6,8 @@ function pf!(xp,w, y, N, g, f, σw )
     wT = @view w[:,1]
     xT = @view xp[:,1]
     fill!(wT,log(1/N))
-    g(y[1],xT, wT)
-    wT .-= log(sum(exp, wT))
+    g(wT, y[1],xT)
+    wT .-= log(sum(exp,wT))
 
     for t = 2:T
         # Resample
@@ -25,16 +24,10 @@ function pf!(xp,w, y, N, g, f, σw )
             copy!(wT,wT1)
         end
 
-        g(y[t],xT, wT)
+        g(wT, y[t],xT)
 
 
-        # Normalize weights
-        offset = maximum(wT)
-        normConstant = 0.0
-        for i = 1:N
-            normConstant += exp(w[i,t]-offset)
-        end
-        wT .-= log(sum(exp, wT))
+        logsumexp!(wT)
 
     end
     xh = zeros(Float64,T)
@@ -46,16 +39,26 @@ function pf!(xp,w, y, N, g, f, σw )
     return xh
 end
 
+@inline logsumexp!(w) = w .-= log(sum(exp, w))
+# function logsumexp!(w)
+#     offset = maximum(wT)
+#     normConstant = 0.0
+#     for i = 1:N
+#         normConstant += exp(w[i,t]-offset)
+#     end
+#     wT .-= log(normConstant) + offset
+# end
+
 function resample(w)
     N = length(w)
-    j = Array(Int64,N)
+    j = Array{Int64}(N)
 #     bins = cumsum(exp(w)) # devec
-    bins = Array(Float64,N)
-    bins[1] = exp(w[1]) # devec
+    bins = Array{Float64}(N)
+    bins[1] = exp(w[1])
     for i = 2:N
         bins[i] = bins[i-1] + exp(w[i])
     end
-    s = collect((rand()/N+0):1/N:bins[end])
+    s = (rand()/N+0):1/N:bins[end]
 
     bo = 1
     for i = 1:N
@@ -90,16 +93,15 @@ f(xn,x,t::Int64) = begin
 end
 f(x::Float64,t::Int64) = 0.5*x + 25*x./(1+x^2) + 8*cos(1.2*(t-1))
 
-# g(y[t]-0.05xp[:,t].^2, wT)
-const den = 0.5/σv^2
-function g(y::Float64,x,w)
+const pg = Distributions.Normal(0,σv)
+function g(w,y::Float64,x)
     @inbounds for i = 1:length(w)
-        w[i] -= den * (y-0.05x[i]^2)^2
+        w[i] -= logpdf(pg, y-0.05x[i]^2)
     end
 end
-function g(x)
-    ret = @. -0.5 * (x/σv)^2
-end
+
+
+
 rms(x) = sqrt(mean(abs2, x))
 
 function run_test()
@@ -107,14 +109,14 @@ function run_test()
     time_steps = [20, 50, 100, 200]
     RMSE = zeros(length(particle_count),length(time_steps)) # Store the RMS errors
     propagated_particles = 0
-    @progress for (Ti,T) in enumerate(time_steps)
-        @progress for (Ni, N) in enumerate(particle_count)
+    for (Ti,T) in enumerate(time_steps)
+        for (Ni, N) in enumerate(particle_count)
             montecarlo_runs = maximum(particle_count)*maximum(time_steps) / T / N
             #             montecarlo_runs = 1
-            xp = Array(Float64,(N,T))
-            w = Array(Float64,(N,T))
-            x = Array(Float64,T)
-            y = Array(Float64,T)
+            xp = Array{Float64}(N,T)
+            w = Array{Float64}(N,T)
+            x = Array{Float64}(T)
+            y = Array{Float64}(T)
 
             E = @parallel (+) for mc_iter = 1:montecarlo_runs
                 x[1] = σw*randn()
diff --git a/pf_vec.jl b/pf_vec.jl
new file mode 100644
index 0000000..91b47f9
--- /dev/null
+++ b/pf_vec.jl
@@ -0,0 +1,149 @@
+using StatsBase, Plots, Distributions, StaticArrays
+
+function init_pf(N, p0)
+    xprev = rand(p0,N)
+    x = similar(x)
+    w = fill(log(1/N), N)
+    x,xprev,w
+end
+
+function pf!(x, xprev, w, u, y, g, f)
+    N = length(x)
+    if shouldresample(w)
+        j = resample(w)
+        f(x,xprev,u,j)
+        fill!(w,log(1/N))
+    else # Resample not needed
+        f(x,xprev,u,1:N)
+    end
+    g(w,y,x)
+    logsumexp!(w)
+    x
+end
+
+function weigthed_mean(x,w)
+    xh = zeros(size(x[1]))
+    @inbounds @simd  for i = eachindex(x)
+        xh .+= x[i].*exp(w[i])
+    end
+    return xh
+end
+
+@inline logsumexp!(w) = w .-= log(sum(exp, w))
+# function logsumexp!(w)
+#     offset = maximum(wT)
+#     normConstant = 0.0
+#     for i = 1:N
+#         normConstant += exp(w[i,t]-offset)
+#     end
+#     wT .-= log(normConstant) + offset
+# end
+
+function resample(w)
+    N = length(w)
+    j = Array{Int64}(N)
+    bins = Array{Float64}(N)
+    bins[1] = exp(w[1])
+    for i = 2:N
+        bins[i] = bins[i-1] + exp(w[i])
+    end
+    s = (rand()/N+0):1/N:bins[end]
+
+    bo = 1
+    for i = 1:N
+        @inbounds for b = bo:N
+            if s[i] < bins[b]
+                j[i] = b
+                bo = b
+                break
+            end
+        end
+    end
+    return j
+end
+
+const pg = Distributions.Normal(0,1.0)
+const pf = Distributions.Normal(0,1.0)
+const p0 = Distributions.Normal(0,2.0)
+
+n = 7
+m = 2
+p = 2
+T = randn(n,n)
+const A = SMatrix{n,n}(T*diagm(linspace(0.5,0.99,n))/T)
+const B = @SMatrix randn(n,m)
+const C = @SMatrix randn(p,n)
+
+function f(x,xp,u,j)
+    @inbounds for i = eachindex(x)
+        x[i] =  A*xp[j[i]] + B*u + rand(pf)
+    end
+end
+function f(x,u)
+    x[i] =  A*xp[j[i]] + B*u + rand(pf)
+end
+
+function g(w,y::Float64,x)
+    @inbounds for i = 1:length(w)
+        w[i] -= logpdf(pg, y-C*x[i])
+    end
+end
+
+
+
+rms(x) = sqrt(mean(abs2, x))
+
+function run_test()
+    particle_count = [5 10 20 50 100 200 500 1000 10_000]
+    time_steps = [20, 50, 100, 200]
+    RMSE = zeros(length(particle_count),length(time_steps)) # Store the RMS errors
+    propagated_particles = 0
+    for (Ti,T) in enumerate(time_steps)
+        for (Ni, N) in enumerate(particle_count)
+            montecarlo_runs = maximum(particle_count)*maximum(time_steps) / T / N
+            #             montecarlo_runs = 1
+            xp = Array{Float64}(N,T)
+            w = Array{Float64}(N,T)
+            x = Array{Float64}(T)
+            y = Array{Float64}(T)
+
+            E = @parallel (+) for mc_iter = 1:montecarlo_runs
+            x[1] = σw*randn()
+            y[1] = σv*randn()
+            @inbounds for t = 1:T-1
+                x[t+1] = f(x[t],u) + σw*randn()
+                y[t+1] = 0.05x[t+1]^2  + σv*randn()
+            end # t
+            xh = pf!(x, xprev, w, u, y, g, f)
+            rms(x-xh)
+        end # MC
+        RMSE[Ni,Ti] = E/montecarlo_runs
+        propagated_particles += montecarlo_runs*N*T
+        #     figure();plot([x xh])
+
+        @show N
+    end # N
+    @show T
+end # T
+println("Propagated $propagated_particles particles")
+#
+return RMSE
+end
+
+@time pf!(eye(4),eye(4), ones(4), 4, g, f, σw )
+gc()
+Profile.clear()
+
+@time RMSE = run_test()
+
+# Profile.print()
+function plotting(RMSE)
+    time_steps = [20, 50, 100, 200]
+    particle_count = [5, 10, 20, 50, 100, 200, 500, 1000, 10_000]
+    nT = length(time_steps)
+    leg = reshape(["$(time_steps[i]) time steps" for i = 1:nT], 1,:)
+
+    plot(particle_count,RMSE,xscale=:log10, ylabel="RMS errors", xlabel=" Number of particles", lab=leg)
+end
+
+plotting(RMSE)
-- 
GitLab