Definition of a diffusion process

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

Definition of the target process

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}}
    TargetDiffusion(α::T, β::T) where T = new{T}(α, β)

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])

Definition of the auxiliary process

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}
    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)

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) = (:α, :β)