From 8575ae16277de16f2498edea9a15b5858bbf225f Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson <cont-frb@ulund.org> Date: Mon, 12 Feb 2018 18:53:53 +0100 Subject: [PATCH] add pf --- pf.jl | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 pf.jl diff --git a/pf.jl b/pf.jl new file mode 100644 index 0000000..d7bf98a --- /dev/null +++ b/pf.jl @@ -0,0 +1,158 @@ + +using StatsBase, Plots + +function pf!(xp,w, y, N, g, f, σw ) + T = length(y) + xp[:,1] = 2σw*randn(N) + wT = @view w[:,1] + xT = @view xp[:,1] + fill!(wT,log(1/N)) + g(y[1],xT, wT) + wT .-= log(sum(exp, wT)) + + for t = 2:T + # Resample + xT1 = xT + xT = @view xp[:,t] + wT1 = wT + wT = @view w[:,t] + if t % 21 == 0 + j = resample(wT1) + f(xT,xT1[j],t-1) + fill!(wT,log(1/N)) + else # Resample not needed + f(xT,xT1,t-1) + copy!(wT,wT1) + end + + g(y[t],xT, wT) + + + # Normalize weights + offset = maximum(wT) + normConstant = 0.0 + for i = 1:N + normConstant += exp(w[i,t]-offset) + end + wT .-= log(sum(exp, wT)) + + end + xh = zeros(Float64,T) + for j = 1:T + @inbounds @simd for i = 1:N + xh[j] += xp[i,j]*exp(w[i,j]) + end + end + return xh +end + +function resample(w) + N = length(w) + j = Array(Int64,N) +# bins = cumsum(exp(w)) # devec + bins = Array(Float64,N) + bins[1] = exp(w[1]) # devec + for i = 2:N + bins[i] = bins[i-1] + exp(w[i]) + end + s = collect((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 σw0 = 2.0 +const σw = 1.0 +const σv = 1.0 + + +# f(x,t::Int64) = begin +# c = 8*cos(1.2*(t-1)) +# @inbounds for i = 1:length(x) +# x[i] = 0.5*x[i] + 25*x[i]./(1+x[i]^2) + c + σw*randn() +# end +# end + +f(xn,x,t::Int64) = begin + c = 8*cos(1.2*(t-1)) + @inbounds for i = 1:length(x) + xn[i] = 0.5*x[i] + 25*x[i]./(1+x[i]^2) + c + σw*randn() + end +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) + @inbounds for i = 1:length(w) + w[i] -= den * (y-0.05x[i]^2)^2 + end +end +function g(x) + ret = @. -0.5 * (x/σv)^2 +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 + @progress for (Ti,T) in enumerate(time_steps) + @progress 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],t) + σw*randn() + y[t+1] = 0.05x[t+1]^2 + σv*randn() + end # t + xh = pf!(xp,w, y, N, g, f, σw0 ) + 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