Skip to content

Commit b3757a0

Browse files
committed
polishing and cubature
1 parent 38dea3c commit b3757a0

File tree

2 files changed

+54
-42
lines changed

2 files changed

+54
-42
lines changed

docs/src/lecture_12/cubature.png

685 KB
Loading

docs/src/lecture_12/lecture.md

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Ordinary Differencial equations
1+
# Uncertainty Propagation in Ordinary Differential Equations
22

3-
Differential equations are commonly used in science to describe many aspects of the physical world, ranging from dynamical systems, curves in space, to complex multi-physics phenomena.
3+
Differential equations are commonly used in science to describe many aspects of the physical world, ranging from dynamical systems and curves in space to complex multi-physics phenomena.
44

55
As an example, consider a simple non-linear ordinary differential equation:
66

@@ -61,13 +61,18 @@ Is simple and working (with sufficienty small ``dt``):
6161

6262
![](lotka.svg)
6363

64+
ODE of this kind is an example of a "complex" simulation code that we may want to use, interact with, modify or incorporate into a more complex scheme.
65+
- we will test how to re-define the elemnetary oeprations using custom types, automatic differnetiation and automatic code generation
66+
- we will redefine the plotting operation to display the new type correctly
67+
- we will use composition to incorporate the ODE into a more complex solver
68+
6469

6570
## Uncertainty propagation
6671

6772
Prediction of the ODE model is valid only if all parameters and all initial conditions are accurate. This is almost never the case. While the number of sheep can be known, the number of wolfes in a forest is more uncertain. The same model holds for predator-prey in insects where the number of individuals can be only estimated.
6873

6974
Uncertain initial conditions:
70-
- number given by a probability distribution
75+
- number of predators and prey given by a probability distribution
7176
- interval ``[0.8,1.2]`` corresponds to uniform distribution ``U(0.8,1.2)``
7277
- gaussian ``N(\mu,\sigma)``, with mean ``\mu`` and standard deviation ``\sigma`` e.g. ``N(1,0.1)``
7378
- more complicated distributions are more realistic (the number of animals is not negative!)
@@ -121,21 +126,18 @@ import Base: +, *
121126

122127
For the ODE we need multiplication of two Gaussians. Using Taylor expansion and neglecting covariances:
123128
```math
124-
g(x_1,x_2)=N(g(\mu_1,\mu_2), \sqrt{(\frac{dg}{dx_1}(\mu_1,\mu_2)\sigma_1)^2 + (\frac{dg}{dx_1}(\mu_1,\mu_2)\sigma_1)^2})
129+
g(x_1,x_2)=N\left(g(\mu_1,\mu_2), \sqrt{\left(\frac{dg}{dx_1}(\mu_1,\mu_2)\sigma_1\right)^2 + \left(\frac{dg}{dx_1}(\mu_1,\mu_2)\sigma_1\right)^2}\right)
125130
```
126131
which trivially applies to sum: ``x_1+x_2=N(\mu_1+\mu_2, \sqrt{\sigma_1^2 + \sigma_1^2})``
127132

128133
```julia
129134
+(x1::GaussNum{T},x2::GaussNum{T}) where T =GaussNum(x1.μ+x2.μ,sqrt(x1.σ.^2 + x2.σ.^2))
130-
*(x1::GaussNum{T},x2::GaussNum{T}) where T =GaussNum(x1.μ*x2.μ, sqrt(x1.σ.^2 + x2.σ.^2))
135+
*(x1::GaussNum{T},x2::GaussNum{T}) where T =GaussNum(x1.μ*x2.μ, sqrt(x2.μ*x1.σ.^2 + x1.μ*x2.σ.^2))
131136

132137
```
133138

134-
135-
139+
Following the principle of defining the necessary functions on the type, we can make it pass through the ODE:
136140
- it is necessary to define new initialization (functions `zero`)
137-
- function overloading can be automated (macro, generated functions)
138-
139141
- define nice-looking constructor (``±``)
140142
```julia
141143
±(a::T,b::T) where T:<Real =GaussNum(a,b)
@@ -147,7 +149,10 @@ GX=solve(f,[1.0±0.1,1.0±0.1],[0.1,0.2,0.3,0.2],0.1,1000)
147149

148150
![](LV_GaussNum.svg)
149151

150-
## Flexibility
152+
- function overloading follows a deterministic procedure => can be automated (macro, generated functions)
153+
154+
155+
### Flexibility
151156

152157
The great advantage of the former model was the ability to run an arbitrary code with uncertainty at an arbitrary number.
153158

@@ -159,7 +164,7 @@ GX=solve(f,[1.0±0.1,1.0±0.1],[0.1±0.1,0.2,0.3,0.2],0.1,1000)
159164

160165
![](LV_GaussNum2.svg)
161166

162-
## Disadvantage
167+
### Disadvantage
163168

164169
The result does not correspond to the ensemble version above.
165170
- we have ignored the covariances
@@ -176,10 +181,11 @@ The previous simple approach ignores the covariances between variables. Even if
176181
![](https://photos1.blogger.com/blogger/5955/293/1600/unscented-transform-explained.jpg)
177182

178183
- The linearization-based approach propogates through the non-linearity only the mean and models its neighborhood by a plane.
179-
- Propagating all samples
184+
- Propagating all samples is too expensive
185+
- Methods based on quadrature or cubature rules are a compromise
180186

181187

182-
A more sophisticated approach is based on moment matching:
188+
The cubature approach is based on moment matching:
183189
```math
184190
\mu_g = \int g(x) p(x) dx
185191
```
@@ -198,17 +204,12 @@ In multivariate setting, the same problem is typically solved with the aim to re
198204

199205
One of the most popular approaches today is based on cubature rules approximating the Gaussian in radial-spherical coordinates.
200206

201-
## Cubature rules
207+
### Cubature rules
202208

203209
Consider Gaussian distribution with mean ``\mu`` and covariance matrix ``\Sigma`` that is positive definite with square root ``\sqrt\Sigma``, such that ``\sqrt\Sigma \sqrt\Sigma^T=\Sigma``. The quadrature pints are:
204210
```math
205-
X_q = \mu .+ \sqrt\Sigma Q
206-
```
207-
where ``Q=[q_1,\ldots q_{2d}]`` are constant vectors
208-
```math
209-
Q = \sqrt{d} [ I_d, -I_d]
211+
x_i = \mu + \sqrt\Sigma q_i
210212
```
211-
i.e.
212213
```math
213214
\begin{align}
214215
q_{1}&=\sqrt{d}\begin{bmatrix}1\\
@@ -219,7 +220,7 @@ q_{1}&=\sqrt{d}\begin{bmatrix}1\\
219220
q_{2}&=\sqrt{d}\begin{bmatrix}0\\
220221
1\\
221222
\vdots
222-
\end{bmatrix}
223+
\end{bmatrix} \ldots
223224
&
224225
q_{d+1}&=\sqrt{d}\begin{bmatrix}-1\\
225226
0\\
@@ -228,9 +229,15 @@ q_{d+1}&=\sqrt{d}\begin{bmatrix}-1\\
228229
q_{d+2}&=\sqrt{d}\begin{bmatrix}0\\
229230
-1\\
230231
\vdots
231-
\end{bmatrix}
232+
\end{bmatrix} \ldots
232233
\end{align}
233234
```
235+
that can be composed into a matrix ``Q=[q_1,\ldots q_{2d}]`` that is constant:
236+
```math
237+
Q = \sqrt{d} [ I_d, -I_d]
238+
```
239+
240+
![](cubature.png)
234241

235242
Those quadrature points are in integration weighted by:
236243
```math
@@ -247,7 +254,7 @@ x' & \sim N(\mu',\Sigma')\\
247254
\end{align}
248255
```
249256

250-
- it is easy to check that if the sigma-points are propagated through an identity, they preserve the mean and variance.
257+
It is easy to check that if the sigma-points are propagated through an identity, they preserve the mean and variance.
251258
```math
252259
\begin{align}
253260
\mu' & = \frac{1}{2d}\sum_{j=1}^{2d} (\mu + \sqrt{\Sigma}q_i)\\
@@ -265,20 +272,23 @@ For our example:
265272
- only 4 trajectories propagated deterministically
266273
- can not be implemented using a single number type
267274
- the number of points to store is proportional to the dimension
268-
- we operations from linear algebra
269-
- moving to represenattions in vector form
275+
- manipulation requires operations from linear algebra
276+
- moving to representations in vector form
270277
- simple for initial conditions,
271278
- how to extend to operate also on parameters?
272279

273-
Easiest solution:
274-
- define the mapping between ODE and vectors manually
275-
- ode, its state and parameters can be wrapped into a ODEProblem
280+
### Smarter implementation
281+
Easiest solution is to put the corresponding parts of the problem together:
282+
- ode function ``f``,
283+
- its state ``x0``,
284+
- and parameters ``θ``
285+
can be wrapped into an ODEProblem
276286

277287
```julia
278-
struct ODEProblem{F,T,U<:AbstractVector,P<:AbstractVector}
288+
struct ODEProblem{F,T,X<:AbstractVector,P<:AbstractVector}
279289
f::F
280290
tspan::T
281-
u0::U
291+
x0::X
282292
θ::P
283293
end
284294
```
@@ -293,31 +303,33 @@ Quick and dirty:
293303
getuncertainty(o::ODEProblem) = [o.u0[1:2];o.θ[1]]
294304
setuncertainty!(o::ODEProblem,x::AbstractVector) = o.u0[1:2]=x[1:2],o.θ[1]=x[3]
295305
```
296-
297306
and write a general Cubature solver using multiple dispatch.
298-
- it would be smart to dispatch on subtypes
299307

300308
Practical issues:
301309
- how to check bounds? (Asserts)
302-
- what if we provide a different
303-
- define a type that speficies the type of uncertainty?
310+
- what if we provide an incompatible ODEProblem
311+
- define a type that specifies the type of uncertainty?
304312
```julia
305-
struct UncertainODEProblem
306-
OP::ODEProblem
313+
struct GaussODEProblem
314+
mean::ODEProblem
307315
unc_in_u # any indexing type accepted by to_index()
308316
unc_in_θ
309317
sqΣ0
310318
end
311319
```
312320

313-
We can dispatch cubature solve on UncODEProblem and solve on UncODEProblem.OP internally.
321+
We can dispatch the cubature solver on GaussODEProblem and the ordinary ``solve`` on GaussODEProblem.OP internally.
314322

315323
```julia
316-
getmean(o::UncertainODEProblem) =[ o.OP.u0[o.unc_in_u];o.OP.θ[o.unc_in_θ]]
317-
setmean!(o::UncertainODEProblem,x::AbstractVector) = begin
318-
o.OP.u0[o.unc_in_u]=x[1:length(unc_in_u)]
319-
o.OP.θ[o.unc_in_θ]=x[length(unc_in_u).+[1:length(unc_in_θ)]]
324+
getmean(gop::GaussODEProblem) =[ gop.mean.x0[gop.unc_in_u];gop.mean.θ[gop.unc_in_θ]]
325+
setmean!(gop::GaussODEProblem,x::AbstractVector) = begin
326+
gop.mean.x0[gop.unc_in_u]=x[1:length(gop.unc_in_u)]
327+
gop.mean.θ[gop.unc_in_θ]=x[length(gop.unc_in_u).+[1:length(gop.unc_in_θ)]]
320328
end
321329
```
322330

323-
- constructor accepts an ODEProblem with uncertain numbers and converts it
331+
Constructor accepts an ODEProblem with uncertain numbers and converts it to GaussODEProblem:
332+
- goes through ODEProblem ``x0`` and ``θ`` fields and checks their types
333+
- replaces GaussNums in ODEProblem by ordinary numbers
334+
- remembers indices of GaussNum in ``x0`` and ``θ``
335+
- copies standard deviations in GaussNum to ``sqΣ0``

0 commit comments

Comments
 (0)