Function Repository Resource:

ItoProcessChangeVariables

Source Notebook

Perform a state variable change for an Ito stochastic process

Contributed by: Bruno Tenorio

ResourceFunction["ItoProcessChangeVariables"][itoProc, u, trans]

changes the state variable in the Ito process itoProc to u using the transformation trans.

ResourceFunction["ItoProcessChangeVariables"][itoProc, {u1, u2,}, trans]

changes the state variables in the Ito process to {u1,u2,}.

Details and Options

ResourceFunction["ItoProcessChangeVariables"] can be used to perform a change of state variables of an ItoProcess including the transformation of the initial conditions. The function returns a new ItoProcess.
The drift a and diffusion(noise) b of the input process can follow any of the specifications allowed by ItoProcess.
The new diffusion (noise) term b' is calculated via the Jacobian matrix J of the corresponding mapping as b'==J.b. This applies whether the diffusion b is a vector or a matrix.
The new drift term a' is calculated accounting for the second-order "Ito Lemma correction". For each component fi of the transformation: (a')i=fi/t+fi.a+1/2Tr(bbT.H(fi)). H is the Hessian matrix of the coordinate transformation and the partial derivative with respect to time includes transformations that have explicit time dependence.
The transformation trans can have the forms:
Following the conventions of DSolveChangeVariables, the transformation can be entered in any form accepted by CoordinateTransformData.
Assumptions can be supplied to specify restrictions on the state variables and parameters. They are used for inverse mapping, solving and expression simplification.
Please see the documentation page for ItoProcess for additional details on variables and their meaning.

Examples

Basic Examples (5) 

Define a geometric Brownian motion stochastic process:

In[1]:=
gbm = ItoProcess@GeometricBrownianMotionProcess[\[Mu], \[Sigma], x0]
Out[1]=

Get the arithmetic Brownian motion via a logarithmic transformation:

In[2]:=
logGBM = ResourceFunction["ItoProcessChangeVariables"][
  gbm, {y}, {y == Log[\[FormalX]]}]
Out[2]=

Mean and variance of the transformed process:

In[3]:=
Comap[{Mean, Variance}, logGBM[t]]
Out[3]=

Start with a Wiener process:

In[4]:=
wiener = ItoProcess[WienerProcess[]]
Out[4]=

In a square transformation of this process, a particular branch is picked in the inverse mapping:

In[5]:=
ResourceFunction[
 "ItoProcessChangeVariables"][wiener, {y}, {y == \[FormalX]^2}]
Out[5]=

Define a 2D process with the noise as a matrix:

In[6]:=
proc = ItoProcess[{{0, 0}, PauliMatrix[1]}, {{x, y}, {x0, y0}}, t]
Out[6]=

Two variable linear transformation of the process:

In[7]:=
transProc = ResourceFunction["ItoProcessChangeVariables"][
  proc, {u, v}, {u == x + y, v == x - y}]
Out[7]=

Start with a Wiener process:

In[8]:=
wiener = ItoProcess[{0, 1}, {x, x0}, t]
Out[8]=

Perform an exponential transformation:

In[9]:=
expProc = ResourceFunction["ItoProcessChangeVariables"][
  wiener, {y}, {y == Exp[x]}]
Out[9]=

Create a geometric Brownian motion process:

In[10]:=
gbm = ItoProcess[{\[Mu] x[t], \[Sigma] x[t]}, {x, x0}, t]
Out[10]=

Reciprocal transformation of the process:

In[11]:=
reciprocal = ResourceFunction["ItoProcessChangeVariables"][gbm, {y}, {y == 1/x}]
Out[11]=

Scope (4) 

Create a particular Ito process:

In[12]:=
proc = ItoProcess[{\[Alpha] x, \[Beta]}, {x, x0}, {t, 0}]
Out[12]=

Explicit time-dependent transformation:

In[13]:=
ResourceFunction[
 "ItoProcessChangeVariables"][proc, {y}, {y == x Exp[-t]}]
Out[13]=

Start with a driftless process:

In[14]:=
proc = ItoProcess[{0, \[Beta] E^-x}, {x, x0}, {t, 0}]
Out[14]=

Calculate the drift of the transformation under the variable change z = tanh(x):

In[15]:=
ResourceFunction["ItoProcessChangeVariables"][proc, {z}, {z == Tanh[x]}][
  "Drift"] // FullSimplify
Out[15]=

Start with a 2D Wiener process:

In[16]:=
wiener2D = ItoProcess[{{0, 0}, IdentityMatrix[2]}, {{x, y}, {x0, y0}}, t]
Out[16]=

Transform the process to polar coordinates such that the initial zero drift becomes non zero and radial dependent in polar coordinates:

In[17]:=
ResourceFunction["ItoProcessChangeVariables"][wiener2D, {r, \[Theta]},
  "Cartesian" -> "Polar"]
Out[17]=

Start with a 3D Wiener process:

In[18]:=
wiener3D = ItoProcess[{{0, 0, 0}, IdentityMatrix[3]}, {{x, y, z}, {x0, y0, z0}},
   t]
Out[18]=

Transform the process from Cartesian to ParabolicCylindrical coordinates using a long name convention:

In[19]:=
ResourceFunction[
 "ItoProcessChangeVariables"][wiener3D, {\[Sigma], \[Tau], \[FormalZ]}, {"Cartesian", "Euclidean", 3} -> {"ParabolicCylindrical",
    "Euclidean", 3}]
Out[19]=

Options (4) 

Define a 1D Wiener process:

In[20]:=
wiener = ItoProcess[{0, {1}}, {x, x0}, t]
Out[20]=

Perform a trigonometric change of variables, because of the periodic nature of the transformation is not possible to get a unique solution:

In[21]:=
ResourceFunction[
 "ItoProcessChangeVariables"][wiener, {y}, {y == Cos[x]}]
Out[21]=

Using the assumption 0<x<π, we select one branch:

In[22]:=
ResourceFunction[
 "ItoProcessChangeVariables"][wiener, {y}, {y == Cos[x]}, Assumptions -> {0 < x < \[Pi]}]
Out[22]=

Using the assumption -π<x<0, we get a different branch that has a sign flip in the diffusion:

In[23]:=
ResourceFunction[
 "ItoProcessChangeVariables"][wiener, {y}, {y == Cos[x]}, Assumptions -> {-\[Pi] < x < 0}]
Out[23]=

Applications (17) 

Mean shifting Ornstein-Uhlenbeck (4) 

Define the OrnsteinUhlenbeck process:

In[24]:=
proc = OrnsteinUhlenbeckProcess[\[Mu], \[Sigma], \[Theta], x0];

Compute mean and variance of the process:

In[25]:=
Comap[{Mean, Variance}, proc[t]] // Simplify
Out[25]=

Perform the variable change y=x-μ:

In[26]:=
transformed = ResourceFunction["ItoProcessChangeVariables"][ ItoProcess@proc, {y}, {y == \[FormalX] - \[Mu]}]
Out[26]=

Check the mean and variance, the mean got shifted but the process remains OrnsteinUhlenbeck:

In[27]:=
Comap[{Mean, Variance}, transformed[t]] // FullSimplify
Out[27]=

Risk-neutral measure (GBM model) (3) 

Define a geometric Brownian motion process modeling a stock price:

In[28]:=
proc = ItoProcess[{r x, \[Sigma] x}, {x, x0}, {t, 0}]
Out[28]=

Find the discounted stock price via the transformation S = -r tx, S is a martingale:

In[29]:=
transformedProc = ResourceFunction["ItoProcessChangeVariables"][
  proc, {S}, {S == x Exp[-r t]}]
Out[29]=

Show a path simulation, setting σ = 0.05 and x0 = 100:

In[30]:=
paths = RandomFunction[
   transformedProc /. {\[Sigma] -> 0.05, x0 -> 100}, {0, 1, 0.01}, 100];
cleanedPaths = paths["Paths"] /. {t_, {v_}} :> {t, v};
ListLinePlot[cleanedPaths, PlotStyle -> Directive[Opacity[0.4`], Blue],
  PlotLabel -> "Risk-Neutral (Driftless) Paths", AxesLabel -> {"Time (T)", "Value (Y)"}, Frame -> True, Epilog -> {Red, Thick, Line[{{0, 100}, {1, 100}}]} ]
Out[31]=

Noisy oscillator (4) 

Define a process representing a noisy oscillator, with drift in velocity related to position (as in Hooke's law), with added diffusion only in velocity:

In[32]:=
oscillator = ItoProcess[{{v, -x}, {{0}, {\[Sigma]}}, {x[t], v[t]}}, {{x, v}, {x0, v0}}, {t, 0}]
Out[32]=

Transforming to E and ϕ variables (energy and phase):

In[33]:=
transformed = ResourceFunction["ItoProcessChangeVariables"][
   oscillator, {\[FormalCapitalE], \[Phi]}, {\[FormalCapitalE] == 1/2 (x^2 + v^2), \[Phi] == ArcTan[x, v]}] // Quiet
Out[33]=

Show a path simulation with σ=0.03,x0=0.5,v0=-0.5. Plotting the phase portrait we get deformed circular paths:

In[34]:=
paths = RandomFunction[(oscillator /. {\[Sigma] -> 0.03, x0 -> 0.5, v0 -> -0.5}), {0, 2 \[Pi], 0.001}, 3];
data = paths["Paths"][[All, All, 2]];
ListLinePlot[data, AspectRatio -> 1, PlotRange -> All, PlotLabel -> "Phase Portrait (x vs v)"]
Out[35]=

In energy-phase space the same parameters create noisy paths:

In[36]:=
paths = RandomFunction[(transformed /. {\[Sigma] -> 0.03, x0 -> 0.5, v0 -> -0.5}), {0, 2 \[Pi], 0.001}, 3];
data = paths["Paths"][[All, All, 2]];
ListLinePlot[data, AspectRatio -> 1, PlotRange -> All, PlotLabel -> "Portrait(E vs \[Phi])"]
Out[37]=

Quantum State Diffusion (6) 

Define a stochastic differential equation in Cartesian coordinates, this process was obtained from Quantum State Diffusion for some density matrix ρ and Lindblad jump operator L=σz:

In[38]:=
procCartesian = ItoProcess[{{-2 x \[Gamma], -2 y \[Gamma] - z \[Omega]x, y \[Omega]x}, {-2 x z Sqrt[\[Gamma]], -2 y z Sqrt[\[Gamma]], 2 (1 - z^2) Sqrt[\[Gamma]]}}, {{x, y, z}, {x0, y0, z0}}, t];

Perform change of variables to spherical coordinates which are more appropriate to the geometry of the state space:

In[39]:=
procSpherical = ResourceFunction["ItoProcessChangeVariables"][
  procCartesian, {r, \[Theta], \[Phi]}, "Cartesian" -> "Spherical"]
Out[39]=

Assign parameters. The initial state is on the surface of the Bloch sphere (r =1, θ=π/3, ϕ = π/3):

In[40]:=
procSpherical = procSpherical /. Join[Thread[{x0, y0, z0} -> FromSphericalCoordinates[{1, \[Pi]/3, \[Pi]/3}]], {\[Gamma] -> 1, \[Omega]x -> 0.3}];

Generate 100 realizations of the transformed process using simulation time γ/ωx:

In[41]:=
trajectoriesSpherical = RandomFunction[procSpherical, {0, 10/3, 1/300}, 100];

Calculate Bloch vector trajectories:

In[42]:=
blochVectorTrajectoriesCollapse = MapAt[Apply[#1 {Cos[#3] Sin[#2], Sin[#3] Sin[#2], Cos[#2]} &], trajectoriesSpherical["ValueList"], {All, All}];

Population of |0〉 can be calculated as , show some trajectories and how they converge towards the poles:

In[43]:=
ListLinePlot[(
 1 + blochVectorTrajectoriesCollapse[[;; 50, All, 3]])/2, Sequence[
 PlotRange -> {0, 1}, AspectRatio -> 1/2, Frame -> True, GridLines -> Automatic, PlotStyle -> Thin, DataRange -> {0, 10/3}, FrameLabel -> {"Time", "Population of |0\[RightAngleBracket]"}, PlotLabel -> "Population of |0\[RightAngleBracket] vs time for different trajectories"]]
Out[43]=

Possible Issues (2) 

If no initial state is supplied when creating a process the default is 0 for each state variable:

In[44]:=
wiener2D = ItoProcess[{{0, 0}, IdentityMatrix[2]}, {x, y}, t]
Out[44]=

Some initial conditions may be undefined under the variable transformation, in this case the origin:

In[45]:=
ResourceFunction["ItoProcessChangeVariables"][wiener2D, {r, \[Theta]},
  "Cartesian" -> "Polar"]
Out[45]=

Publisher

Mads Bahrami

Requirements

Wolfram Language 13.3 (June 2023) or above

Version History

  • 1.0.0 – 09 January 2026

License Information