In [1]:
from IPython.core.display import HTML
css_file = 'https://raw.githubusercontent.com/ngcm/training-public/master/ipython_notebook_styles/ngcmstyle.css'
HTML(url=css_file)
Out[1]:
This background for these exercises is article of D Higham, An Algorithmic Introduction to Numerical Simulation of Stochastic Differential Equations, SIAM Review 43:525-546 (2001). Higham provides Matlab codes illustrating the basic ideas at http://personal.strath.ac.uk/d.j.higham/algfiles.html, which are also given in the paper.
For random processes in python
you should look at the numpy.random
module. To set the initial seed (which you should not do in a real simulation, but allows for reproducible testing), see numpy.random.seed
.
A random walk or Brownian process or Wiener process is a way of modelling error introduced by uncertainty into a differential equation. The random variable representing the walk is denoted $W$. A single realization of the walk is written $W(t)$. We will assume that
These requirements lead to a definition of a discrete random walk: given the points $\{ t_i \}$ with $i = 0, \dots, N$ separated by a uniform timestep $\delta t$, we have - for a single realization of the walk - the definition
$$
\begin{align}
\text{d}W_i &= \sqrt{\delta t} {\cal N}(0, 1), \\
W_i &= \left( \sum_{j=0}^{i-1} \text{d}W_j \right), \\
W_0 &= 0
\end{align}
$$
Here ${\cal N}(0, 1)$ means a realization of a normally distributed random variable with mean $0$ and standard deviation $1$: programmatically, the output of numpy.random.randn
.
When working with discrete Brownian processes, there are two things we can do.
Both viewpoints are important.
100
. Compare the results.
In [2]:
%matplotlib inline
import numpy
from matplotlib import pyplot
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
rcParams['figure.figsize'] = (12,6)
from scipy.integrate import quad
Evaluate the function $u(W(t)) = \sin^2(t + W(t))$, where $W(t)$ is a Brownian process, on $M$ Brownian paths for $M = 500, 1000, 2000$. Compare the average path for each $M$.
The average path at time $t$ should be given by $$ \begin{equation} \int_{-\infty}^{\infty} \frac{\sin(t+s)^2 \exp(-s^2 / 2t)}{\sqrt{2 \pi t}} \,\text{d}s. \end{equation} $$
In [3]:
# This computes the exact solution!
t_int = numpy.linspace(0.005, numpy.pi, 1000)
def integrand(x,t):
return numpy.sin(t+x)**2*numpy.exp(-x**2/(2.0*t))/numpy.sqrt(2.0*numpy.pi*t)
int_exact = numpy.zeros_like(t_int)
for i, t in enumerate(t_int):
int_exact[i], err = quad(integrand, -numpy.inf, numpy.inf, args=(t,))
We have, in eg finite elements or multistep methods for IVPs, written the solution of differential equations in terms of integrals. We're going to do the same again, so we need to integrate random variables. The integral of a random variable with respect to a Brownian process is written $$ \int_0^t G(s) \, \text{d}W_s, $$ where the notation $\text{d}W_s$ indicates that the step in the Brownian process depends on the (dummy) independent variable $s$.
We'll concentrate on the case $G(s) = W(s)$, so we're trying to integrate the Brownian process itself. If this were a standard, non-random variable, the answer would be $$ \int_0^t W(s) \, \text{d}W_s = \frac{1}{2} \left( W(t)^2 - W(0)^2 \right). $$
When we approximate the quadrature numerically than we would split the interval $[0, T]$ into strips (subintervals), approximate the integral on each subinterval by picking a point inside the interval, evaluating the integrand at that point, and weighting it by the width of the subinterval. In normal integration it doesn't matter which point within the subinterval we choose.
In the stochastic case that is not true. We pick a specific point $\tau_i = a t_i + (1-a) t_{i-1}$ in the interval $[t_{i-1}, t_i]$. The value $a \in [0, 1]$ is a constant that says where within each interval we are evaluating the integrand. We can then approximate the integral by
\begin{equation} \int_0^T W(s) \, dW_s = \sum_{i=1}^N W(\tau_i) \left[ W(t_i) - W(t_{i-1}) \right] = S_N. \end{equation}Now we can compute (using that the expectation of the products of $W$ terms is the covariance, which is the minimum of the arguments)
\begin{align} \mathbb{E}(S_N) &= \mathbb{E} \left( \sum_{i=1}^N W(\tau_i) \left[ W(t_i) - W(t_{i-1}) \right] \right) \\ &= \sum_{i=1}^N \mathbb{E} \left( W(\tau_i) W(t_i) \right) - \mathbb{E} \left( W(\tau_i) W(t_{i-1}) \right) \\ &= \sum_{i=1}^N (\min\{\tau_i, t_i\} - \min\{\tau_i, t_{i-1}\}) \\ &= \sum_{i=1}^N (\tau_i - t_{i-1}) \\ &= (t - t_0) a. \end{align}The choice of evaluation point matters.
So there are multiple different stochastic integrals, each (effectively) corresponding to a different choice of $a$. The two standard choices are There are two standard choices of stochastic integral.
These lead to $$ \int_0^t G(s) \, \text{d}W_s \simeq_{\text{Ito}} \sum_{j=0}^{N-1} G(s_j, W(s_j)) \left( W(s_{j+1}) - W(s_j) \right) = \sum_{j=0}^{N-1} G(s_j) \text{d}W(s_{j}) $$ for the Ito integral, and $$ \int_0^t G(s) \, \text{d}W_s \simeq_{\text{Stratonovich}} \sum_{j=0}^{N-1} \frac{1}{2} \left( G(s_j, W(s_j)) + G(s_{j+1}, W(s_{j+1})) \right) \left( W(s_{j+1}) - W(s_j) \right) = \sum_{j=0}^{N-1} \frac{1}{2} \left( G(s_j, W(s_j)) + G(s_{j+1}, W(s_{j+1})) \right) \text{d}W(s_{j}). $$ for the Stratonovich integral.
Write functions to compute the Itô and Stratonovich integrals of a function $h(t, W(t))$ of a given Brownian process $W(t)$ over the interval $[0, 1]$.
In [4]:
def ito(h, trange, dW):
"""Compute the Ito stochastic integral given the range of t.
Parameters
----------
h : function
integrand
trange : list of float
the range of integration
dW : array of float
Brownian increments
seed : integer
optional seed for the Brownian path
Returns
-------
ito : float
the integral
"""
return ito
In [5]:
def stratonovich(h, trange, dW):
"""Compute the Stratonovich stochastic integral given the range of t.
Parameters
----------
h : function
integrand
trange : list of float
the range of integration
dW : array of float
the Brownian increments
Returns
-------
stratonovich : float
the integral
"""
return stratonovich
Test the functions on $h = W(t)$ for various $N$. Compare the limiting values of the integrals.
Now we can write down a stochastic differential equation.
The differential form of a stochastic differential equation is $$ \frac{\text{d}X}{\text{d}t} = f(X) + g(X) \frac{\text{d}W}{\text{d}t} $$ and the comparable (and more useful) integral form is $$ \text{d}X = f(X) \, \text{d}t + g(X) \text{d}W. $$ This has formal solution $$ X(t) = X_0 + \int_0^t f(X(s)) \, \text{d}s + \int_0^t g(X(s)) \, \text{d}W_s. $$
We can use our Ito integral above to write down the Euler-Maruyama method
$$ X(t+h) \simeq X(t) + h f(X(t)) + g(X(t)) \left( W(t+h) - W(t) \right) + {\cal{O}}(h^p). $$Written in discrete, subscript form we have
$$ X_{n+1} = X_n + h f_n + g_n \, \text{d}W_{n} $$The order of convergence $p$ is an interesting and complex question.
Apply the Euler-Maruyama method to the stochastic differential equation
$$ \begin{equation} dX(t) = \lambda X(t) + \mu X(t) dW(t), \qquad X(0) = X_0. \end{equation} $$Choose any reasonable values of the free parameters $\lambda, \mu, X_0$.
The exact solution to this equation is $X(t) = X(0) \exp \left[ \left( \lambda - \tfrac{1}{2} \mu^2 \right) t + \mu W(t) \right]$. Fix the timetstep and compare your solution to the exact solution.
Vary the timestep of the Brownian path and check how the numerical solution compares to the exact solution.
We have two ways of thinking about Brownian paths or processes.
We can fix the path (ie fix $\text{d}W$) and vary the timescale on which we're looking at it: this gives us a single random path, and we can ask how the numerical method converges for this single realization. This is strong convergence.
Alternatively, we can view each path as a single realization of a random process that should average to zero. We can then look at how the method converges as we average over a large number of realizations, also looking at how it converges as we vary the timescale. This is weak convergence.
Formally, denote the true solution as $X(T)$ and the numerical solution for a given step length $h$ as $X^h(T)$. The order of convergence is denoted $p$.
For Euler-Maruyama, expect $p=1/2$!.
For Euler-Maruyama, expect $p=1$.
Investigate the weak and strong convergence of your method, applied to the problem above.
In [ ]: