Translating between parameters and Problem
SciMLBase.remake — Method
remake(prob::AbstractSciMLProblem, popt, ps::AbstractProblemParSetter)Return an updated problem given the parameters. Subtypes need to implement method remake_pset(prob, popt, pset)
MTKHelpers.get_paropt — Method
get_paropt(pset::AbstractProblemParSetter, prob::SciMLBase.AbstractSciMLProblem; kwargs...)
get_paropt_labeled(pset::AbstractProblemParSetter, prob::SciMLBase.AbstractSciMLProblem; kwargs...)Extract optimized parameters from the Problem. The labeled versions additionally calls label_paropt on the return value.
Helper functions to access optimized parameters
MTKHelpers.axis_paropt — Method
axis_paropt(pset::AbstractProblemParSetter)
axis_paropt_scalar(pset::AbstractProblemParSetter)
axis_paropt_flat1(pset::AbstractProblemParSetter)Report the Axis of a ComponentVector of parameters. The second version has a scalarized entry for state for each subvector of state. The third version provides an axis corresponding to flatten1(paropt).
MTKHelpers.classes_paropt — Method
function classes_paropt(pset::AbstractProblemParSetter)Get the classes (as NTuple{Symbol}) which the AbstractProblemParSetter supports and requires in paropt.
MTKHelpers.count_paropt — Method
count_paropt(::AbstractProblemParSetter)Report length of the optimized parameters vector. This generally is different from the length of keys, because each key can describe a array.
MTKHelpers.keys_paropt — Method
keys_paropt(::AbstractProblemParSetter)Report the keys of paropt below the classification level.
MTKHelpers.symbols_paropt — Method
symbols_paropt(pset::AbstractProblemParSetter)Report the names, i.e. symbols of optimized parameters respectively, i.e. the concatenation of components. Similar to ComponentArrays.label, but inferred from Axis object. Returns a Vector of length count_paropt
Labeling parameter vectors
MTKHelpers.label_paropt — Method
label_paropt(pset::AbstractProblemParSetter, popt::AbstractVector)
label_paropt_flat1(pset::AbstractProblemParSetter, popt::AbstractVector)Produce a labeled version, i.e. a ComponentVector of optimized parameters. The second version omits the highest level of labels, e.g. state and par in ODEProblemParSetter.
MTKHelpers.name_paropt — Method
name_paropt(pset, popt::AbstractVector)
name_paropt(pset, prob::AbstractSciMLProblem)Produce a NamedVector of given state optimized parameters vector. Similar to label_paropt, but may print nicer. The second form calls get_paropt on the Problem.
ProblemUpdater
The functioonality of ProblemUpdater can be better modeled since MTK version 10 using bindings.
Bindings
First, create an example system and example problem.
using ModelingToolkit, OrdinaryDiffEq, ComponentArrays
using ModelingToolkit: ModelingToolkit as MTK
using MTKHelpers
using ModelingToolkit: t_nounits as t, D_nounits as D
function get_sys1()
sts = @variables L(t)
ps = @parameters k_L, k_R, k_P
eq = [D(L) ~ 0]
sys1 = System(eq, t, sts, vcat(ps...); name = :sys1)
end
sys1 = mtkcompile(get_sys1())
ps1 = [sys1.L => 10.0, sys1.k_L => 1.0, sys1.k_R => 1.0/20.0, sys1.k_P => 2.0]
prob = ODEProblem(sys1, ps1, (0.0, 1.0))The bindings cannot be changed after the system is created. MTKHelper provides function override_system that allows to create a new system with several properties changes. Note that this is has been developed and tested only for basic ODESystems.
sys2 = mtkcompile(override_system(sys1,
bindings = [sys1.k_R => sys1.k_L / 20.0, sys1.k_P => sys1.k_L * 2.0]))
ps2 = [sys2.L => 10.0, sys2.k_L => 1.0]
prob2 = ODEProblem(sys2, ps2, (0.0, 1.0))
prob3 = remake(prob, p = [sys2.k_L => 1.1])
prob.ps[sys2.k_P], prob2.ps[sys2.k_P](2.0, 2.0)If initial conditions are bound, then initial conditions could be specified for the bound property instead of the original one.
Alternative: Problemupdater
Bindings were introduced in MTK10. Before, a ProblemUpdater could be used to take care of updating dependent parameters.
A ODEProblemParSetterConcrete can be combined with a KeysProblemParGetter or another specific implementation of AbstractProblemParGetter to update an AbstractODEProblem based on information already present in the AbstractODEProblem.
The following example updates parameters k_R and k_P in the AbstractODEProblem to the value of k_L. This can be useful to ensure that these parameters are also changed when optimizing parameter k_L.
An implementations of AbstractProblemParGetter can use any computation of the source keys to provide its destination keys. It should implement the keys method, so that when constructing the ProblemUpdater, consistent keys are used, as in the example below.
Next, setup a ProblemUpdater, pu, and apply it to the problem via prob2 = pu(prob).
mapping = (:k_L => :k_R, :k_L => :k_P)
pu = get_ode_problemupdater(KeysProblemParGetter(mapping, prob), get_system(prob))
prob2 = pu(prob)
p2 = get_par_labeled(par_setter(pu), prob2)
p2.k_P == p2.k_R == Dict(ps1)[sys1.k_L]MTKHelpers.ProblemUpdater — Type
ProblemUpdater(par_getter, par_setter)Encapsulates updating an AbstractODEProblem based on the problem itself by Callable (pu::ProblemUpdater)(prob).
Must be initialized with a callable AbstractProblemParGetter, e.g. KeysProblemParGetter and on a AbstractODEProblemParSetter, e.g. ODEProblemParSetter.
There are special functions to construct ProblemUpdater based on a given Problem:
MTKHelpers.get_ode_problemupdater — Function
get_ode_problemupdater(par_getter::AbstractProblemParGetter, u0, p)
get_ode_problemupdater(par_getter::AbstractProblemParGetter, sys::AbstractSystem)Construct a ProblemUpdater based on an constructed ODEProblemParSetterConcrete.
get_ode_problemupdater(par_getter::AbstractProblemParGetter, u0, p)
get_ode_problemupdater(par_getter::AbstractProblemParGetter, sys::AbstractSystem)Construct a ProblemUpdater based on an constructed ODEProblemParSetterConcrete.
MTKHelpers.NullProblemUpdater — Type
AbstractProblemUpdater that returns the original AbstractODEProblem.
ProblemParGetter
In order to provide computations for parameters to set, declare a concrete subtype of AbstractProblemParGetter, and implement a custom method (pg::MyProblemParGetter)(pu::ProblemUpdater, prob) that returns a vector of parameter values.
MTKHelpers.AbstractProblemParGetter — Type
Supertype for callables that implement (::AbstractProblemParGetter)(problem) -> updated_problem
Concrete subtypes should implement function keys, so that an appropriate AbstractODEProblemParSetter can be constructed for ProblemUpdater.
One simple subtype of AbstractProblemParGetter is KeysProblemParGetter, which just extracts variables from the original problem to update other parameters. It can be used to ensure that some parameter of a problem will always equal another parameter of the problem.
MTKHelpers.KeysProblemParGetter — Type
KeysProblemParGetter(mapping::NTuple{N,Pair{Symbol, Symbol}, keys_state)Provides callable (pg::KeysProblemParGetter)(pu::ProblemUpdater, prob), keys_state]. To be used to get the parameters/state vector to be set by ProblemUpdater.
Initialize with an mapping of NTuples of symbols (source -> target) that index into either get_state_labeled(pu.pset, prob) or get_par_labeled(pu.pset, prob)). Argument keys_state is a Tuple or Vector that iterates the Symbols in the state of an ODEProblem. It is required to know from which part of the problem to extract.
ProblemParSetter
Abstract supertype of ODEProblemParSetter
MTKHelpers.AbstractProblemParSetter — Type
During an optimization, one does not want to recreate the problem from a symbolic system, but only update the problem. This can be difficult, because the parameters to update may be spread across initial state and other parameters. Further, the order of parameters after simplifying a system is not fixed.
A AbstractProblemUpdater helps with
remake: translate the set of parameters -> an updated problemget_paropt: problem -> extract/approximate subset of parameters to optimize
The structure of optimized parameter Vector is described by an Axis object of ComponentArrays.jl. And several functions are defined to work with it. Specifically, the ComponentVector it employs a classification (classes_paropt), ,e.g. :state and :par for ODEProblems, below which, ComponentVectors of actual parameters are listed (keys_paropt](@ref)). Further functions extract information about the ComponentVector: axis_paropt, , count_paropt, symbols_paropt or attach information to a plain vector for convenient access or display: label_paropt, name_paropt.