In [1]:
using StochasticEuler
using PyPlot
PyPlot.plt[:style][:use]("ggplot")
In [2]:
?ieuler_sde
Out[2]:
In [3]:
σ = 1.
θ = 2.
μ = 3.
function ornstein_uhlenbeck!(t, x, xdot, gdW, dW, compute_xdot, compute_gdW)
if compute_xdot
xdot[:]=θ*(μ-x[1])
end
if compute_gdW
gdW[1] = σ*dW[1]
end
xdot, gdW
end
t0=0
t1=1.
ts = linspace(t0,t1,501)
h = .001
x0 = [1.]
# Since the diffusion coefficient is constant, the Ito and Stratonovich SDEs are identical
ts, xs1, dWs = ieuler_heun(ornstein_uhlenbeck!, x0, ts, h, 1)
ts, xs2, dWs = ieuler_mayurama(ornstein_uhlenbeck!, x0, ts, h, 1)
expmtht = exp(-θ*ts)
sol = x0[1] *expmtht - μ*(expmtht-1) + σ*expmtht .* cumsum([0;dWs']./expmtht);
subplot(211)
plot(ts, xs1')
plot(ts, xs2')
plot(ts, sol)
ylabel(L"Solution $x(t)$")
title("Ornstein Uhlenbeck Process")
subplot(212)
plot(ts, xs1'-sol)
plot(ts, xs2'-sol)
xlabel(L"Time $t$")
ylabel("Errors")
Out[3]:
In [4]:
a, b, c, d = [1,2,3,4,7]
function linear_sde_ito!(t, x, xdot, gdW, dW, compute_xdot, compute_gdW)
if compute_xdot
xdot[1]=(a*x[1] + c)
end
if compute_gdW
gdW[1] = (b*x[1] + d) * dW[1]
end
xdot, gdW
end
function linear_sde_strat!(t, x, xdot, gdW, dW, compute_xdot, compute_gdW)
if compute_xdot
xdot[1]=((a-.5*b^2)*x[1] + c - .5*b*d)
end
if compute_gdW
gdW[1] = (b*x[1]+d)*dW[1]
end
xdot, gdW
end
t0=0
t1=1.
ts = linspace(t0, t1, 1001)
h = 1./(2<<16)
x0 = [1.]
ts, xs1, dWs, iters1 = ieuler_heun(linear_sde_strat!, x0, ts, h, 1; return_metrics=true, ϵ_rel=1e-10, max_iter=20)
ts, xs2, dWs, iters2 = ieuler_mayurama(linear_sde_ito!, x0, ts, h, 1; return_metrics=true, ϵ_rel=1e-10, max_iter=20)
dts = diff(ts)
dWs = dWs'
Φtt0 = exp(cumsum((a-.5*b^2) * dts + b*dWs))
xtsol = [x0[1]; Φtt0 .* (x0[1] + cumsum((c) *dts ./ Φtt0) + cumsum(d * dWs ./ Φtt0))]
subplot(211)
title("General linear SDE")
plot(ts, xs1')
plot(ts, xs2')
plot(ts, xtsol)
ylabel(L"Solution $x(t)$")
subplot(212)
plot(ts, xs1'-xtsol, label="Stratonovich")
plot(ts, xs2'-xtsol, label="Ito")
legend()
xlabel(L"Time $t$")
ylabel("Errors")
Out[4]:
In [5]:
function exp_sde_ito!(t, x, xdot, gdW, dW, compute_xdot, compute_gdW)
if compute_xdot
xdot[1]= -x[1]*(2*log(x[1]) + 1)
end
if compute_gdW
gdW[1] = -2x[1]*sqrt(-log(x[1]))*dW[1]
end
xdot, gdW
end
function exp_sde_strat!(t, x, xdot, gdW, dW, compute_xdot, compute_gdW)
if compute_xdot
xdot[1]= 0.
end
if compute_gdW
gdW[1] = -2x[1]*sqrt(-log(x[1]))*dW[1]
end
xdot, gdW
end
t0=0
t1=1.
ts = linspace(t0, t1, 1001)
h = .00001
x0 = [.5]
ts, xs1, dWs = ieuler_heun(exp_sde_strat!, x0, ts, h, 1; ν=.5)
ts, xs2, dWs = ieuler_mayurama(exp_sde_ito!, x0, ts, h, 1; ν=.5)
dts = diff(ts)
dWs = dWs'
Wts = cumsum(dWs)
xtsol = [x0[1]; exp(-(Wts + sqrt(-log(x0[1]))).^2)]
subplot(211)
title("Exponential SDE")
plot(ts, xs1')
plot(ts, xs2')
plot(ts, xtsol)
ylabel(L"Solution $x(t)$")
subplot(212)
plot(ts, xs1'-xtsol, label="Stratonovich")
plot(ts, xs2'-xtsol, label="Ito")
legend(loc="lower left")
xlabel(L"Time $t$")
ylabel("Errors")
Out[5]:
In [6]:
?CumulativeNormal
Out[6]:
In [7]:
d = 5
rng = MersenneTwister()
# averages over 2 samples
cnrng2 = CumulativeNormal(rng, 2,d)
# averages over 4 samples
cnrng4 = CumulativeNormal(rng, 4,d)
vec = zeros(d)
srand(rng, 0)
full_grid = hcat([randn(rng, d) for j=1:4]...)
srand(rng, 0)
half_grid = hcat([randn(cnrng2, d) for j=1:2]...)
srand(rng, 0)
quarter_grid = hcat([randn!(cnrng4, vec) for j=1:1]...)
# Verify that block summing works correctly
@assert norm(full_grid * kron(eye(2), ones(2))/sqrt(2) - half_grid) < 10*eps(Float64)
@assert norm(full_grid * ones(4)/sqrt(4) - quarter_grid) < 10*eps(Float64)
@assert norm(half_grid * ones(2)/sqrt(2) - quarter_grid) < 10*eps(Float64)
In [8]:
t0=0
t1=1.
ts = linspace(t0, t1, 2049)
h = 1./(2<<17)
x0 = [1.]
grid_sizes = [1,2,4,8,16,32,64, 128]
d = 1
rngs = AbstractRNG[MersenneTwister()]
for gs = grid_sizes[2:end]
push!(rngs, CumulativeNormal(rngs[1], gs, d))
end
seed = 2
allxs = zeros(length(ts), length(grid_sizes))
alldWs = zeros(length(ts)-1, length(grid_sizes))
alliters = zeros(Int64, length(ts)-1, length(grid_sizes))
for k=1:length(grid_sizes)
println("Grid size: $(grid_sizes[k]*h)")
@time ts, xs, dWs, iters = ieuler_heun(
linear_sde_strat!, x0, ts, h*grid_sizes[k], 1;
rng=rngs[k], ν=.5, κ=.5, seed=seed, ϵ_rel=1e-10, max_iter=20, return_metrics=true)
allxs[:,k] = xs[:]
alldWs[:,k] = dWs[:]
alliters[:,k] = iters[:]
end
dWs = alldWs[:,1]
dts = diff(ts)
Φtt0 = exp(cumsum((a-.5*b^2) * dts + b*dWs))
xtsol = [x0[1]; Φtt0 .* (x0[1] + cumsum((c) *dts ./ Φtt0) + cumsum(d * dWs ./ Φtt0))];
In [9]:
subplot(311)
# plot(ts, xs1', label="h=$h")
# plot(ts, xs2', label="h=$(2h)")
# # plot(ts, xs3', label="h=$(3h)")
# plot(ts, xs4', label="h=$(4h)")
# plot(ts, xs8', label="h=$(8h)")
plot(ts, allxs)
plot(ts, xtsol, label="exact")
xtsol_wide = sub(xtsol,1:length(xtsol), 1)
# legend(loc="upper right")
title("Convergence test for Linear SDE")
ylabel(L"Solution $x(t)$")
rel_errs = abs(broadcast((/), allxs, xtsol+eps(Float64)) - 1)
subplot(312)
semilogy(ts, abs(broadcast((-), allxs, xtsol)))
ylabel("Absolute error")
subplot(313)
semilogy(ts, rel_errs)
ylim(1e-5,1)
xlabel(L"Time $t$")
ylabel("Relative error")
Out[9]:
In [10]:
loglog(grid_sizes, 2*sum(alliters, 1)')
ylabel("Number of SDE calls")
xlabel(L"Step size $h/h_0$")
Out[10]: