To define a diffusion model suitable for inference with BridgeSDEInference.jl
one must define two processes:
- the
target
diffusion - and the
auxiliary
diffusion
The diffusion definitions will extend some of the functionality of the existing
functions from Bridge.jl
, so the following imports are necessary:
using Bridge
import Bridge: b, σ, B, β, a, constdiff
The target process needs to be a struct inheriting from
ContinuousTimeProcess{ℝ{d,T}}
(where d
is a dimension of the diffusion) with
the first type parameter {T}
defining the data-type of the parameters. The
members of the struct must define the diffusion process and are usually limited
to a list of parameters. An example of a valid definition of a 10
dimensional
diffusion with two parameters \alpha
and \beta
would be
struct TargetDiffusion{T} <: ContinuousTimeProcess{ℝ{10,T}}
α::T
β::T
TargetDiffusion(α::T, β::T) where T = new{T}(α, β)
end
Then, one must specify the dynamics of the diffusion by specifying the behaviour
of the drift and volatility functions b
and σ
(defined in Bridge.jl
) for
TargetDiffusion
:
b(t, x, P::TargetDiffusion) = foo(t, x, P.α, P.β)
σ(t, x, P::TargetDiffusion) = bar(t, x, P.α, P.β)
where foo
and bar
are some user-defined functions. Finally, three auxiliary
functions must be defined:
constdiff(::TargetDiffusion) = false
indicating whether σ(t, x, P::TargetDiffusion)
is independent from the values
of x
and t
,
clone(P::TargetDiffusion, θ) = TargetDiffusion(θ...)
which returns a new copy of the process with new set of parameters, and finally
params(P::TargetDiffusion) = [P.α, P.β]
which returns an array with all parameter values. Optionally, functions nonhypo
, hypo_a_inv
, num_non_hypo
and phi
can be defined to make it possible to perform conjugate updates of the parameters (see ... for more details on conjugate updates [TODO add])
The auxiliary diffusion, similarly, needs to be a struct inheriting from
ContinuousTimeProcess{ℝ{d,T}}
with the first type parameter {T}
defining
the data-type of the parameters. It is often necessary for the auxiliary
diffusion to have to have access to the information regarding the starting
and ending time of the interval on which it is defined. Additionally, the
starting and end-point of the target process are also sometimes used (if
available). An example of a definition of the auxiliary diffusion is:
struct AuxiliaryDiffusion{R,S1,S2}
α::R
β::R
t::Float64 # starting time of the interval
u::S1 # starting position of the target process
T::Float64 # end-time of the interval
v::S2 # final position of the target process
AuxiliaryDiffusion(α::R, β::R, t, u::S1, T, v::S2) = new{R,S1,S2}(α, β, t, u, T, v)
end
It is now necessary to specify the dynamics of the process. Unlike in the case
of the Target
, specifying the volatility coefficient is not necessary and it
is sufficient to only provide a diffusion coefficient (a:=σσ'
). The package
supports only linear diffusions as auxiliary processes and thus function b
should be defined as:
b(t, x, P::AuxiliaryDiffusion) = B(t, P) * x + β(t, P)
where B
and β
need to be overwritten as follows:
B(t, P::AuxiliaryDiffusion) = foo2(t, P)
β(t, P::AuxiliaryDiffusion) = foo3(t, P)
where the user-defined functions foo2
and foo3
should return a d
by d
matrix and a length-d
vector respectively. One needs to define the diffusion
coefficient
a(t, P::AuxiliaryDiffusion) = bar2(t, P)
As previously, the clone
constructor, params
and also a convenience
function returning the names of the paramters:
clone(P::AuxiliaryDiffusion, θ) = AuxiliaryDiffusion(θ..., P.t, P.u, P.T, P.v)
params(P::AuxiliaryDiffusion) = (P.α, P.β)
param_names(P::AuxiliaryDiffusion) = (:α, :β)