-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathintegrate.jl
55 lines (43 loc) · 1.55 KB
/
integrate.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
module Integrate
using Distributions
import Sobol: skip, SobolSeq
import Base.Iterators: take, Repeated
import HCubature: hcubature
import LinearAlgebra: cholesky
abstract type AbstractIntegrator end
(∫::AbstractIntegrator)(f::Function) = sum(w*f(x) for (w,x) in zip(∫.w, ∫.x))
struct FixedNodeIntegrator{Tx,Tw} <: AbstractIntegrator
x::Tx
w::Tw
end
MonteCarloIntegrator(distribution::Distribution, ndraw=100)=FixedNodeIntegrator([rand(distribution) for i=1:ndraw], Repeated(1/ndraw))
function QuasiMonteCarloIntegrator(distribution::UnivariateDistribution, ndraws=100)
ss = skip(SobolSeq(1), ndraw)
x = [quantile(distribution, x) for x in take(ss,ndraw)]
w = Repeated(1/ndraw)
FixedNodeIntegrator(x,w)
end
function QuasiMonteCarloIntegrator(distribution::AbstractMvNormal, ndraw=100)
ss = skip(SobolSeq(length(distribution)), ndraw)
L = cholesky(distribution.Σ).L
x = [L*quantile.(Normal(), x) for x in take(ss,ndraw)]
w = Repeated(1/ndraw)
FixedNodeIntegrator(x,w)
end
struct AdaptiveIntegrator{FE,FT,FJ,A,L} <: AbstractIntegrator
eval::FE
transform::FT
detJ::FJ
args::A
limits::L
end
(∫::AdaptiveIntegrator)(f::Function) = ∫.eval(t->f(∫.transform(t))*∫.detJ(t), ∫.limits...; ∫.args...)[1]
function AdaptiveIntegrator(dist::AbstractMvNormal; eval=hcubature, options=())
D = length(dist)
x(t) = t./(1 .- t.^2)
Dx(t) = prod((1 .+ t.^2)./(1 .- t.^2).^2)*pdf(dist,x(t))
args = options
limits = (-ones(D), ones(D))
AdaptiveIntegrator(hcubature,x,Dx,args, limits)
end
end