Generating Data for an ODEProblem
To train a DigitalEcho
we need to generate the training data. To generate this data, we simulate the system which can be an ODEProblem or a FMU. In this section, we will demonstrate how to generate data using an ODEProblem for training a DigitalEcho
.
We start by setting up our environment. We load DataGeneration
and OrdinaryDiffEq
for defining an ODEProblem
.
using DataGeneration
using OrdinaryDiffEq
For this demonstration, we choose a simple Lotka Volterra system. This system is a pair of non-linear differential equations used to describe the dynamics of a biological system. The system has a set of parameters α
, β
, γ
, δ
.
\[\frac{du₁}{dt} = \alpha u₁ - \beta u₁u₂\]
\[\frac{du₂}{dt} = \delta u₁u₂ - \gamma u₂\]
ODEProblem with parameters
We define the dynamics in the above equations in a function lotka_volterra
.
function lotka_volterra(u, p, t)
u₁, u₂ = u
α, β, γ, δ = p
dx = α * u₁ - β * u₁ * u₂
dy = δ * u₁ * u₂ - γ * u₂
[dx, dy]
end
lotka_volterra (generic function with 1 method)
Next we define the initial condition for the states : u₁
and u₂
, and the timespan : tspan
.
u0 = [1.0, 1.0]
tspan = (0, 12.5)
(0, 12.5)
We define the ODEProblem
as:
lv_ode_problem = ODEProblem{false}(lotka_volterra, u0, tspan)
ODEProblem with uType Vector{Float64} and tType Float64. In-place: false
timespan: (0.0, 12.5)
u0: 2-element Vector{Float64}:
1.0
1.0
For more detailed examples on defining ODEProblem
see: OrdinaryDiffEq.jl. Note one needs to define it with the {false} flag. For generating data, we need to define a ParameterSpace
for sampling parameters: α
, β
, γ
, δ
. We start by defining the lower bound and upper bound.
param_lb = [1.5, 1.75, 1.5, 1.75]
param_lb = [2.0, 2.25, 2.25, 2.0]
n_samples = 10
10
And then we define the ParameterSpace
:
param_space = ParameterSpace(param_lb, param_lb, n_samples; labels = ["α", "β", "γ", "δ"]);
We define the SimulatorConfig
with this parameter space:
simconfig = SimulatorConfig(param_space);
And finally to generate the data, we call this SimulatorConfig
on our problem. This returns an ExperimentData
object that is consumed by DigitalEcho
for training.
ed = simconfig(lv_ode_problem);
[ Info: #Processes = 1
[ Info: Simulating samples from worker processes
Additionally we can provide keyword arguments such as alg
to the SimulatorConfig
object call.
ed = simconfig(lv_ode_problem; alg = Tsit5())
Number of Trajectories in ExperimentData: 10
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1 │ 1 │ 1 │ 0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1 │ 1 │ 1 │ 0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2 │ 2 │ 2 │ 0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2 │ 2 │ 2 │ 0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
╭──────────┬─────────────────────────────────────────────────────────────────...
───────╮...
│ Field │...
│...
├──────────┼─────────────────────────────────────────────────────────────────...
───────┤...
│ │ ╭────────────┬──────────────┬──────────────┬────────────┬──────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼──────...
│ │ │ states_1 │ 0.951337 │ 1.30017 │ 1.09613 │...
│ states │ ├────────────┼──────────────┼──────────────┼────────────┼──────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼──────...
│ │ │ states_2 │ 0.745919 │ 1.0482 │ 0.889332 │...
│ │ ╰────────────┴──────────────┴──────────────┴────────────┴──────...
╰──────────┴─────────────────────────────────────────────────────────────────...
───────╯...
ODEProblem with parameters and inputs
The above system of equations can be modified to use control inputs as:
\[\frac{du₁}{dt} = \alpha u₁ - \beta u₁u₂ + x₁ \]
\[\frac{du₂}{dt} = \delta u₁u₂ - \gamma u₂ - x₂\]
And thus our new function would be:
function lotka_volterra_ctrl(u, x, p, t)
u₁, u₂ = u
α, β, γ, δ = p
x₁, x₂ = x
dx = α * u₁ - β * u₁ * u₂ + x₁
dy = δ * u₁ * u₂ - γ * u₂ - x₂
[dx, dy]
end
lotka_volterra_ctrl (generic function with 1 method)
Now we can define a new ODEProblem
for this controlled lotka-volterra system as:
controlled_lv_ode_problem = ODEProblem{false}(lotka_volterra_ctrl, u0, tspan)
ODEProblem with uType Vector{Float64} and tType Float64. In-place: false
timespan: (0.0, 12.5)
u0: 2-element Vector{Float64}:
1.0
1.0
Since we have introduced control inputs in this system, lets define a CtrlSpace
to sample control functions.
nsamples_ctrl = 10
ctrl_lb = [0.0, 0.0]
ctrl_ub = [0.1, 0.1]
ctrl_func(u, p, t) = [p[1] * sin(t), p[2] * sin(t)]
ctrl_space = CtrlSpace(ctrl_lb, ctrl_ub, ctrl_func, nsamples_ctrl; labels = ["x₁", "x₂"]);
We have previously defined a ParameterSpace
, which we will reuse for data generation in this case. So we can define a SimulatorConfig
with ParameterSpace
as well as CtrlSpace
.
simconfig = SimulatorConfig(param_space, ctrl_space)
Simulator Config with : CtrlSpace ParameterSpace
Statistics for all Spaces
2 dimensional CtrlSpace with 10 samples
With controls : x₁, x₂
╭──────────────┬──────────────────────────────────────────────┬──────────────...
─────╮...
│ Space Type │ Statistics │ Number...
Samples │...
├──────────────┼──────────────────────────────────────────────┼──────────────...
─────┤...
│ │ ╭──────────┬──────────────┬──────────────╮ │...
│ │ │ Labels │ LowerBound │ UpperBound │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ x_1 │ 0 │ 0.1 │ │...
│ CtrlSpace │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ x_2 │ 0 │ 0.1 │ │...
│ │ ╰──────────┴──────────────┴──────────────╯ │...
╰──────────────┴──────────────────────────────────────────────┴──────────────...
─────╯...
4 dimensional ParameterSpace with 10 samples
╭──────────────────┬──────────────────────────────────────────────┬──────────...
─────────╮...
│ Space Type │ Statistics │ Number...
of Samples │...
├──────────────────┼──────────────────────────────────────────────┼──────────...
─────────┤...
│ │ ╭──────────┬──────────────┬──────────────╮ │...
│ │ │ Labels │ LowerBound │ UpperBound │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ α │ 2 │ 2 │ │...
│ ParameterSpace │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ │ ⋮ │ ⋮ │ ⋮ │ │...
│ │ ├──────────┼──────────────┼──────────────┤ │...
│ │ │ δ │ 2 │ 2 │ │...
│ │ ╰──────────┴──────────────┴──────────────╯ │...
╰──────────────────┴──────────────────────────────────────────────┴──────────...
─────────╯...
Similar to the previous example, we can generate the ExperimentData
by calling the SimulatorConfig
on our controlled_lv_ode_problem
.
ed_ctrl = simconfig(controlled_lv_ode_problem)
Number of Trajectories in ExperimentData: 100
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1 │ 1 │ 1 │ 0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1 │ 1 │ 1 │ 0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2 │ 2 │ 2 │ 0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2 │ 2 │ 2 │ 0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
Number of controls in the ExperimentData: 2
╭────────────┬───────────────────────────────────────────────────────────────...
──────────╮...
│ Field │...
│...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│ │ ╭────────────┬──────────────┬──────────────┬────────────┬────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ states_1 │ 0.887627 │ 1.42643 │ 1.0959...
│ states │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ states_2 │ 0.709326 │ 1.13012 │ 0.889302...
│ │ ╰────────────┴──────────────┴──────────────┴────────────┴────...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│ │ ╭──────────┬──────────────┬──────────────┬──────────────┬────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean...
│ │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ x₁ │ -0.0929809 │ 0.0949977 │ 0.00341274...
│ controls │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ x₂ │ -0.0930931 │ 0.0949977 │ 0.00331477...
│ │ ╰──────────┴──────────────┴──────────────┴──────────────┴────...
╰────────────┴───────────────────────────────────────────────────────────────...
──────────╯...
Parallelization
The Data Generation supports distributed computing via multiple processes. To enable multi-processing using processes, we need to load Distributed
.
using Distributed
We add processes using addprocs
. For more detailed understanding about distributed computing see: Distributed.jl.
addprocs(2, exeflags = ["--project=."])
We need to load DataGeneration
module of JuliaSimSurrogates
on all the processes.
@everywhere using DataGeneration
We need to use @everywhere
to define functions on these added processes.
@everywhere function lotka_volterra_ctrl(u, x, p, t)
u₁, u₂ = u
α, β, γ, δ = p
x₁, x₂ = x
dx = α * u₁ - β * u₁ * u₂ + x₁
dy = δ * u₁ * u₂ - γ * u₂ - x₂
[dx, dy]
end
@everywhere ctrl_func(u, p, t) = [p[1] * sin(t), p[2] * sin(t)]
Once we have defined the necessary functions on these processes, we can take advantage of multi-processing for data generation.
ed_ctrl = simconfig(controlled_lv_ode_problem)
Number of Trajectories in ExperimentData: 100
Basic Statistics for Given Dynamical System's Specifications
Number of u0s in the ExperimentData: 2
Number of ps in the ExperimentData: 4
╭─────────┬────────────────────────────────────────────────────────────────────╮
│ Field │ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭────────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_1 │ 1 │ 1 │ 1 │ 0 │ │
│ u0s │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├────────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ states_2 │ 1 │ 1 │ 1 │ 0 │ │
│ │ ╰────────────┴──────────────┴──────────────┴────────┴──────────╯ │
├─────────┼────────────────────────────────────────────────────────────────────┤
│ │ ╭──────────┬──────────────┬──────────────┬────────┬──────────╮ │
│ │ │ Labels │ LowerBound │ UpperBound │ Mean │ StdDev │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ α │ 2 │ 2 │ 2 │ 0 │ │
│ ps │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ ⋮ │ │
│ │ ├──────────┼──────────────┼──────────────┼────────┼──────────┤ │
│ │ │ δ │ 2 │ 2 │ 2 │ 0 │ │
│ │ ╰──────────┴──────────────┴──────────────┴────────┴──────────╯ │
╰─────────┴────────────────────────────────────────────────────────────────────╯
Basic Statistics for Given Dynamical System's Continuous Fields
Number of states in the ExperimentData: 2
Number of controls in the ExperimentData: 2
╭────────────┬───────────────────────────────────────────────────────────────...
──────────╮...
│ Field │...
│...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│ │ ╭────────────┬──────────────┬──────────────┬────────────┬────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ states_1 │ 0.887627 │ 1.42643 │ 1.0959...
│ states │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ ├────────────┼──────────────┼──────────────┼────────────┼────...
│ │ │ states_2 │ 0.709326 │ 1.13012 │ 0.889302...
│ │ ╰────────────┴──────────────┴──────────────┴────────────┴────...
├────────────┼───────────────────────────────────────────────────────────────...
──────────┤...
│ │ ╭──────────┬──────────────┬──────────────┬──────────────┬────...
│ │ │ Labels │ LowerBound │ UpperBound │ Mean...
│ │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ x₁ │ -0.0929809 │ 0.0949977 │ 0.00341274...
│ controls │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ │ ⋮ │ ⋮ │ ⋮ │ ⋮...
│ │ ├──────────┼──────────────┼──────────────┼──────────────┼────...
│ │ │ x₂ │ -0.0930931 │ 0.0949977 │ 0.00331477...
│ │ ╰──────────┴──────────────┴──────────────┴──────────────┴────...
╰────────────┴───────────────────────────────────────────────────────────────...
──────────╯...