Parameter transformation functions
in dMod are generated with P(). The method
argument of P() allows to specify the transformation
explicitly or implicitly. Here, we
explain the difference.
Explicit parameter transformations express parameters (e.g. model
parameters) in terms of other or new parameters. Let us assume we have
model parameters X and Y. Then we could write
X = a + b and Y = a - b to parameterize the
original parameters in terms of new parameters a and
b. The implementation reads:
Here, the names of the vector denote the original parameters and the vector entries are expressions of the new parameters. We test the result:
## [[1]]
## X: 5
## Y: 1
In dMod, we call X and Y the inner
parameters and a and b the
outer parameters.
Implicit parameter transformations express the current parameters in
terms of constraints which need to be satisfied. The constraint is that
a certain function of the parameters vanishes. We could for example
require that X + Y - 2*a = 0 and
X - Y - 2*b = 0 (the transformation from above
reformulated). X and Y are the inner
parameters, a and b are the outer parameters
which determine the inner ones. To implement this, we write:
Here, the names of the vector denote the parameters which should be expressed in terms of other parameters and the vector entries denote the constraints which must cancel out.
We test the result:
## [[1]]
## a: 3
## b: 2
## X: 5.00000002430988
## Y: 1
Compared to the result above, the parameter transformation not only
returns the implicitly defined inner parameters X and
Y but also returns the outer parameters a and
b which were used to determine X and
Y. The reason for the different default behavior is the
following application of implicit transformations.
A frequent application of implicit parameter transformations are steady state constraints. Let’s assume the following reactions:
reactions <- eqnlist() %>%
addReaction("A", "B", "k_on*A") %>%
addReaction("B", "A", "k_off*B")
reactions## Conserved quantities: 1
## 1 1*A+1*B
##
## Check Educt -> Product Rate Description
## 1 A -> B k_on*A
## 2 B -> A k_off*B
The reactions correspond to the following differential equations:
## [1] "d/dt A = -1*(k_on*A) +1*(k_off*B)" "d/dt B = 1*(k_on*A) -1*(k_off*B)"
\((A^*, B^*)\) is a steady state if
the derivatives vanish for \(A = A^*\)
and \(B = B^*\). Therefore, the idea is
that equations itself takes the role of the constraints.
The names of equations are already A and
B, i.e. the initial value parameters we aim to implicitly
define.
However, frequently with steady state constraints, the equations are not independent. In our case \(\frac{dA}{dt} = - \frac{dB}{dt}\). Consequently, whenever \(\frac{dA}{dt} = 0\) is satisfied, \(\frac{dB}{dt} = 0\) is automatically satisfied, too, for all \(k_{\rm on}\) and \(k_{\rm off}\).
Because effectively we have only one constraint equation, we could
keep one initial value, say A, and determine B
such that we are in steady state. We would do this writing:
constraint <- eqnvec(
B = equations[["B"]]
)
p <- P(constraint, method = "implicit")
pars <- c(k_on = 1, k_off = 3, A = 2)
p(pars)## [[1]]
## A: 2
## B: 0.666666664640843
## k_off: 3
## k_on: 1
Another way to deal with the situation would be to introduce
additional constraints. In our case we could introduce
total = A + B as a new parameter. To implement this, we
write:
constraint <- eqnvec(
A = equations[["A"]],
B = "A + B - total"
)
p <- P(constraint, method = "implicit")
pars <- c(k_on = 1, k_off = 3, total = 3)
p(pars)## [[1]]
## A: 2.25000000759684
## B: 0.749999998480632
## k_off: 3
## k_on: 1
## total: 3
In the spirit of dMod, the parameter transformations can be
concatenated. This means that parameter estimation with steady state
constraints can be implemented using a mixture of explicit and implicit
parameter transformations: prd <- x*pSS*p with the
implicit steady state transformation pSS and the
conventional transformation p, e.g. log-transformation of
parameters, etc.
dMod uses the package rootSolve to find the root of
the constraint function. The method used is a Newton method. This means,
the algorithm needs to start with some initial guess of the parameters
to be determined. The user can provide initial guesses with
pars, i.e., we could call p() with
pars = c(k_on = 1, k_off = 3, total = 3, A = 0.1, B = 0.1).
If no guess is provided, the algorithm starts with 1 for all unknown
parameters.
Happy parameter transforming!!