Source code for mutwo.common_generators.brown

"""Algorithms which are related to Scottish botanist Robert Brown."""

import math
import typing

import numpy as np  # type: ignore
from scipy.stats import norm  # type: ignore

__all__ = ("random_walk_noise",)


[docs]def random_walk_noise( x0: float, n: int, dt: float, delta: float, out: typing.Union[np.array, None] = None, random_state: int = None, ) -> np.array: """Generate an instance of Brownian motion (i.e. the Wiener process). :param x0: the initial condition(s) (i.e. position(s)) of the Brownian motion. :param n: the number of steps to take :param dt: the time step :param delta: delta determines the "speed" of the Brownian motion. The random variable of the position at time t, X(t), has a normal distribution whose mean is the position at time t=0 and whose variance is delta**2*t. :param out: If `out` is not None, it specifies the array in which to put the result. If `out` is None, a new numpy array is created and returned. :param random_state: set the random seed of the pseudo-random generator. :return: A numpy array of floats with shape `x0.shape + (n,)`. X(t) = X(0) + N(0, delta**2 * t; 0, t) where N(a,b; t0, t1) is a normally distributed random variable with mean a and variance b. The parameters t0 and t1 make explicit the statistical independence of N on different time intervals; that is, if [t0, t1) and [t2, t3) are disjoint intervals, then N(a, b; t0, t1) and N(a, b; t2, t3) are independent. Written as an iteration scheme, X(t + dt) = X(t) + N(0, delta**2 * dt; t, t+dt) If `x0` is an array (or array-like), each value in `x0` is treated as an initial condition, and the value returned is a numpy array with one more dimension than `x0`. Note that the initial value `x0` is not included in the returned array. This code has been copied from the scipy cookbook: https://scipy-cookbook.readthedocs.io/items/BrownianMotion.html """ x0_as_array = np.asarray(x0) # For each element of x0, generate a sample of n numbers from a # normal distribution. r = norm.rvs( size=x0_as_array.shape + (n,), scale=delta * math.sqrt(dt), random_state=random_state ) # If `out` was not given, create an output array. if out is None: out = np.empty(r.shape) # This computes the Brownian motion by forming the cumulative sum of # the random samples. np.cumsum(r, axis=-1, out=out) # Add the initial condition. out += np.expand_dims(x0_as_array, axis=-1) return out