---
title: "Prior distributions in lotri"
author: "Matthew Fidler"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Prior distributions in lotri}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(lotri)
```

# Why priors are in `lotri`

A `lotri({})` block is the `ini({})` block of a `nlmixr2` model.  Until now
it could only say what a parameter *is* -- an estimate, optional bounds, a
`fix` flag, a label -- but not what is believed about it beforehand.

Bayesian estimation methods need that missing piece.  This adds a way to
attach a prior distribution to any parameter in the block.

`lotri` deliberately stops at parsing, validating and storing the prior.  It
does not evaluate the density and it does not generate any 'Stan' code; that
is the job of the package doing the estimation.  What `lotri` guarantees is
that by the time the estimation code sees a prior, the distribution exists,
has the right number of arguments, and does not contradict the parameter's
bounds.

# The syntax

A prior is given with `prior(name) ~ dist(...)`:

```{r}
m <- lotri({
  tka <- 0.45
  tcl <- c(0, 1, 10)

  prior(tka) ~ dnorm(0, 10)
  prior(tcl) ~ dlnorm(1, 0.5)
})

lotriEst(m)
```

Because the statement names the parameter it applies to, prior lines are
**order independent**.  These two blocks are the same:

```{r}
m1 <- lotri({
  tka <- 0.45
  prior(tka) ~ dnorm(0, 10)
})

m2 <- lotri({
  prior(tka) ~ dnorm(0, 10)
  tka <- 0.45
})

identical(m1, m2)
```

That matters in practice: you can keep all the priors together at the bottom
of a long block instead of interleaving them with the estimates.

`prior()` is the general form and works for any distribution.  Normal priors
are common enough to have a shorthand as well, which is covered below in
[the normal prior shorthand](#the-normal-prior-shorthand).

# What a prior can be attached to

## Population parameters

```{r}
lotriEst(lotri({
  tka <- 0.45
  prior(tka) ~ dnorm(0, 10)
}))
```

## A single between subject variability term

```{r}
m <- lotri({
  eta.ka ~ 0.3
  prior(eta.ka) ~ dgamma(2, 1)
})

attr(m, "lotriPriors")
```

## A whole covariance block

Correlation and covariance matrices have their own distributions, and those
apply to the block rather than to any one element.  Give every name in the
block:

```{r}
m <- lotri({
  eta.cl + eta.v ~ c(0.1,
                     0.01, 0.2)
  prior(eta.cl, eta.v) ~ lkjCorr(2)
})

attr(m, "lotriPriors")
```

The prior is stored on the first diagonal element of the block it belongs
to, which is why only the first entry is filled in above.

### Degrees of freedom for an omega block

The scale matrix of the Wishart family is **optional**, because the block it
is put on already *is* that matrix.  So an inverse Wishart prior on an omega
block is written by giving only its degrees of freedom:

```{r}
m <- lotri({
  eta.cl + eta.v ~ c(0.1,
                     0.01, 0.2)
  eta.ka ~ 0.3
  prior(eta.cl, eta.v) ~ invWishart(4)
  prior(eta.ka) ~ invWishart(2)
})

as.data.frame(m)[, c("name", "est", "prior")]
```

This is the pair that a NONMEM `NWPRI` model writes as `$OMEGAP` and
`$OMEGAPD`: the omega values you already gave are the prior scale matrix,
and the number here is the degrees of freedom.

It works on a 1x1 block as well, since an inverse Wishart of dimension one
is an inverse gamma.

When every block shares the same degrees of freedom, a one-sided `~` sets
them all at once instead of naming each block:

```{r}
m <- lotri({
  eta.cl + eta.v ~ c(0.3,
                     0.01, 0.1)
  eta.ka ~ 0.5
  ~invWishart(4)
})

as.data.frame(m)[, c("name", "est", "prior")]
```

Both blocks got it -- the 2x2 and the 1x1.  Each is still checked
individually, so a degrees of freedom that is proper for one block and not
another is caught.  Naming a block as well is a duplicate rather than an
override:

```{r error=TRUE}
lotri({
  eta.cl + eta.v ~ c(0.3,
                     0.01, 0.1)
  ~invWishart(4)
  prior(eta.cl, eta.v) ~ invWishart(5)
})
```

Give the scale matrix explicitly only when it differs from the estimates:

```{r}
lotriEst(lotri({
  e1 + e2 ~ c(1,
              0.1, 1)
  prior(e1, e2) ~ invWishart(4, lotri(e1 + e2 ~ c(2,
                                                  0.5, 2)))
}))
attr(lotri({
  e1 + e2 ~ c(1,
              0.1, 1)
  prior(e1, e2) ~ invWishart(4, lotri(e1 + e2 ~ c(2,
                                                  0.5, 2)))
}), "lotriPriors")
```

Because both the degrees of freedom and the size of the block are known, an
improper prior is caught:

```{r error=TRUE}
lotri({
  e1 + e2 ~ c(1,
              0.1, 1)
  prior(e1, e2) ~ invWishart(1)
})
```

### A prior on the omega values themselves

The two NONMEM prior flavours want different things from an omega.  An
`NWPRI` model gives it degrees of freedom, which is the `invWishart()` above.
A `TNPRI` model instead puts a normal prior on the omega *elements*, jointly
with the thetas, so those elements need names of their own.

Prepending `om.` to a between subject variability names its omega element:

```{r}
m <- lotri({
  eta.cl ~ 0.3
  eta.v ~ 0.1
  om.eta.cl ~ 0.01
  om.eta.v ~ 0.04
})

attr(m, "lotriPriors")
```

`om.eta.cl ~ 0.01` reads exactly like the shorthand for a population
estimate: a normal prior with a variance of 0.01, centered on the omega
value the model already gives.  The omega itself is untouched -- only the
prior was added:

```{r}
diag(m)
```

Correlated omega priors work the same way, including the per-row line form:

```{r}
m2 <- lotri({
  eta.cl + eta.v ~ c(0.3,
                     0.01, 0.1)
  om.eta.cl ~ 0.01
  om.eta.v ~ c(0.001, 0.02)
})

attr(m2, "lotriPriors")[1]
```

An `om.` name has to match a real between subject variability; it never
quietly creates one:

```{r error=TRUE}
lotri({
  eta.ka ~ 0.3
  om.eta.nope ~ 0.1
})
```

Naming the eta directly means the same thing, so `prior(om.eta.cl)` and
`prior(eta.cl)` are interchangeable.  The `om.` spelling exists so the
shorthand has a name to put on the left of the `~`, since `eta.cl ~ ...`
already means the omega value itself.

The two are alternatives, not additions, so a model that gives an omega both
degrees of freedom and a normal prior is rejected:

```{r error=TRUE}
lotri({
  eta.cl + eta.v ~ c(0.3,
                     0.01, 0.1)
  eta.ka ~ 0.5
  prior(eta.cl, eta.v) ~ invWishart(4)
  om.eta.ka ~ 0.01
})
```

### One joint block over thetas and omega elements

A `TNPRI` variance matrix does not stop at the omegas -- it covers the
thetas *and* the omega elements together, with covariances between them.  A
block may therefore name both:

```{r}
m <- lotri({
  tcl <- 1
  eta.cl ~ 0.3
  tcl + om.eta.cl ~ c(0.01,
                      0.002, 0.005)
})

lotriEst(m)$prior
```

The mean is what the model already says: the estimate for `tcl`, the omega
value for `om.eta.cl`.  The prior is stored once, on the first name of the
block, because the block spans two places -- the estimates and the omega --
and there is no one row that owns it.  The covariance keeps every name, so
the members are recovered from it rather than from where it is stored:

```{r}
attr(m, "lotriPriors")
diag(m)
```

Naming the block with `prior()` means the same thing:

```{r}
lotriEst(lotri({
  tcl <- 1
  eta.cl ~ 0.3
  prior(tcl, om.eta.cl) ~ multiNormal(c(1, 0.3),
                                      lotri(tcl + om.eta.cl ~ c(0.01,
                                                                0.002, 0.005)))
}))$prior
```

Unlike a prior on the omega itself, a joint block does not have to be one
covariance block -- a `TNPRI` matrix covers whichever elements it likes:

```{r}
lotriEst(lotri({
  tcl <- 1
  eta.cl ~ 0.3
  eta.v ~ 0.1
  tcl + om.eta.cl + om.eta.v ~ c(0.01,
                                 0.002, 0.005,
                                 0.001, 0.0005, 0.004)
}))$prior
```

### One block at a time

The names have to be *exactly* one block.  Two unrelated diagonal elements
are two 1x1 blocks, not one 2x2 block, so this is an error:

```{r error=TRUE}
lotri({
  eta.a ~ 1
  eta.b ~ 1
  prior(eta.a, eta.b) ~ lkjCorr(2)
})
```

# The normal prior shorthand

Normal priors are by far the most common, so they have a shorthand that
reuses the matrix syntax you already know.  Putting a **population
estimate** on the left of a `~` gives it a normal prior:

```{r}
lotriEst(lotri({
  tka <- 1
  tka ~ 4
}))
```

The number on the right is a **variance**, so `tka ~ 4` is a normal prior
with a standard deviation of 2.  The mean is the `<-` estimate, so the prior
is centered on what the model already says the parameter is -- the pair a
NONMEM `NWPRI` model writes as `$THETAP` and `$THETAPV`.  Write
`prior(tka) ~ dnorm(mu, sd)` when the prior is *not* centered there.

This is unambiguous because a name cannot be both an estimate and an eta --
that combination used to be an error.

## More than one parameter

The full matrix syntax works, so a covariance between the priors is written
the same way a covariance between etas is:

```{r}
m <- lotri({
  tka <- 1
  tcl <- 3
  tv  <- 4
  tcl + tv ~ c(1,
               0.01, 1)
})

lotriEst(m)$prior
```

That is a multivariate normal whose mean vector is the estimates.  The
covariance is kept as the `lotri` expression that built it, which is valid R
and round trips exactly.

The matrix means exactly what it means for etas: the off-diagonal is a
**covariance**, not a correlation.  A prior block and an eta block written
the same way give the same matrix:

```{r}
.eta <- lotri({ a + b ~ c(1,
                          0.5, 2) })

.prior <- lotri({
  a <- 1
  b <- 2
  a + b ~ c(1,
            0.5, 2)
})

## pull the covariance back out of the stored prior
identical(unname(as.matrix(eval(str2lang(lotriEst(.prior)$prior[1])[[3]]))),
          unname(as.matrix(.eta)))
```

The per-row line form builds up the block, exactly as it does for etas:

```{r}
m2 <- lotri({
  tka <- 1
  tcl <- 3
  tv  <- 4
  tcl ~ 1
  tv ~ c(0.01, 1)
})

identical(m, m2)
```

When the parameters are uncorrelated the result is simply independent
normal priors, since that is what an MVN with a diagonal covariance is:

```{r}
lotriEst(lotri({
  tcl <- 3
  tv  <- 4
  tcl + tv ~ c(1,
               0, 1)
}))$prior
```

## Transformations

`sd()`, `var()`, `cor()`, `cov()` and `chol()` all work here too, so the
prior can be written whichever way is most natural:

```{r}
lotriEst(lotri({
  tcl <- 3
  tv  <- 4
  tcl + tv ~ sd(2,
                0.5, 3)
}))$prior
```

`sd(2, ..., 3)` gives variances of 4 and 9, as the stored prior shows.

## Zero variance

A zero variance is a point mass rather than a prior, so it is rejected
rather than quietly accepted:

```{r error=TRUE}
lotri({
  tka <- 1
  tka ~ 0
})
```

# Distribution names

There are three spellings of every distribution, and all of them are
accepted on input:

1. the **R** name, when R parameterizes the distribution the same way
   'Stan' does -- `dnorm()`, `dlnorm()`, `dgamma()`, `dbeta()`
2. the **camelCase** name, which is the 'Stan' name written the way the rest
   of this package is written -- `invWishart()`, `lkjCorr()`, `studentT()`
3. the **'Stan'** name itself -- `inv_wishart()`, `lkj_corr()`, `student_t()`

The canonical one -- what gets stored and printed back -- is the R name when
there is a faithful one, and the camelCase name otherwise.  Whichever you
write, you get the same thing:

```{r}
a <- lotri({ tka <- 0.45; prior(tka) ~ dnorm(0, 10) })
b <- lotri({ tka <- 0.45; prior(tka) ~ normal(0, 10) })

identical(a, b)
lotriEst(a)$prior
```

```{r}
.camel <- lotri({ e1 ~ 1; prior(e1) ~ invWishart(2) })
.stan  <- lotri({ e1 ~ 1; prior(e1) ~ inv_wishart(2) })

identical(.camel, .stan)
attr(.camel, "lotriPriors")
```

Arguments may be positional or named, in any order:

```{r}
lotriEst(lotri({
  tka <- 0.45
  prior(tka) ~ dnorm(sd=10, mean=0)
}))$prior
```

## Why `dt()` is not `studentT()`

The one place where an R name is *refused* is `dt()`.  R's `dt(x, df, ncp)`
is the standardized (or noncentral) t, while `studentT(nu, mu, sigma)`
(the 'Stan' `student_t`) is a location-scale t.  They are different
distributions, so aliasing them would silently change the model:

```{r error=TRUE}
lotri({
  tka <- 0.45
  prior(tka) ~ dt(3)
})
```

Use `studentT()` with its own parameterization instead:

```{r}
lotriEst(lotri({
  tka <- 0.45
  prior(tka) ~ studentT(3, 0, 10)
}))$prior
```

## The supported distributions

`lotriPriorDists()` returns the whole table, including the 'Stan' name for
each distribution, which is what a package generating 'Stan' code needs:

```{r}
d <- lotriPriorDists()
nrow(d)
head(d, 10)
```

The `kind` column says what a distribution may be attached to --
`univariate` for a single parameter, `matrix` and `multivariate` for a
covariance block:

```{r}
subset(d, kind == "matrix", select=c(name, stanName, parNames))
```

# Bounds and truncated priors

The bounds are not repeated in the prior.  They already live on the
parameter, so a symmetric distribution on a parameter bounded below by zero
*is* a half distribution:

```{r}
m <- lotri({
  propSd <- c(0, 0.1)
  prior(propSd) ~ dcauchy(0, 5)
})

as.data.frame(m)[, c("name", "lower", "est", "upper", "prior")]
```

Here `propSd` has `lower = 0` and a Cauchy prior, so it is a half-Cauchy.  A
package generating 'Stan' code has everything it needs to emit the
`T[0, ]` truncation.

Because the bounds are known, `lotri` can also check that the prior does not
contradict them.  A distribution with positive support on a parameter that
allows negative values is an error:

```{r error=TRUE}
lotri({
  a <- c(-10, 1, 10)
  prior(a) ~ dlnorm(0, 1)
})
```

# What else is checked

Unknown distributions are rejected, with a suggestion when there is an
obvious near match:

```{r error=TRUE}
lotri({ a <- 1; prior(a) ~ dnorml(0, 1) })
```

So are the wrong number of arguments, and argument names that do not belong
to the distribution:

```{r error=TRUE}
lotri({ a <- 1; prior(a) ~ dnorm(0) })
```

```{r error=TRUE}
lotri({ a <- 1; prior(a) ~ dnorm(mu=0, sd=1) })
```

A matrix-valued distribution on a single parameter, a univariate one on a
block, a prior on a parameter that does not exist, and two priors on the
same parameter are all errors as well.

# Getting the priors back out

Priors round trip.  They appear in the `prior` column of the estimate data
frame and of `as.data.frame()`, and they are printed back as valid `lotri`
code:

```{r}
m <- lotri({
  tka <- 0.45
  label("Ka")
  tcl <- c(0, 1, 10)

  eta.cl + eta.v ~ c(0.1,
                     0.01, 0.2)
  eta.ka ~ 0.3

  prior(tka) ~ dnorm(0, 10)
  prior(tcl) ~ dlnorm(1, 0.5)
  prior(eta.ka) ~ dgamma(2, 1)
  prior(eta.cl, eta.v) ~ lkjCorr(2)
})

as.data.frame(m)[, c("name", "est", "condition", "prior")]
```

```{r}
as.expression(m)
```

Note that the block prior comes back as `prior(eta.cl, eta.v)`, with the
whole block recovered, not just the element it was stored on.  Since the
deparsed form is valid input, it can be fed straight back in:

```{r}
identical(as.data.frame(eval(as.expression(m))), as.data.frame(m))
```

Priors are matched to parameters **by name**, never by position, so they are
unaffected by the matrix re-ordering that `lotri` does when `rcm=TRUE` (which
is what `nlmixr2` uses):

```{r}
m <- lotri({
  a ~ 1
  b ~ c(0, 1)
  c ~ c(0.5, 0, 1)
  prior(a) ~ dgamma(1, 1)
}, rcm=TRUE)

dimnames(m)[[1]]
attr(m, "lotriPriors")
```

The matrix has been re-ordered, and the prior has followed `a` rather than
staying on the first row.

# Using this downstream

A package that generates 'Stan' code needs two things from `lotri`, and both
are available:

1. the prior itself, from the `prior` column of `as.data.frame()` (which is
   the `$iniDf` of a `nlmixr2` model) together with that row's `lower` and
   `upper` for any truncation, and
2. the 'Stan' spelling of the distribution, from `lotriPriorDists()`.

```{r}
m <- lotri({
  tka <- 0.45
  prior(tka) ~ dnorm(0, 10)
})

.df <- as.data.frame(m)
.p <- .df$prior[!is.na(.df$prior)]
.p

## map the canonical name to the Stan one
.fn <- as.character(str2lang(.p)[[1]])
lotriPriorDists()$stanName[lotriPriorDists()$name == .fn]
```

which is enough to write `target += normal_lpdf(tka | 0, 10);`.

## A prior must never be silently ignored

The one thing a consumer of this column must *not* do is skip it.  If a
method cannot use a prior, quietly ignoring it means the fit does something
other than what the model says, with nothing to tell the user.  A prior that
is present should either be used or be an error.

`rxode2` provides the assertions for this, so an estimation method can
declare what it supports in one line:

- `assertRxUiNoPriors()` for a method that cannot use priors at all
- `assertRxUiNormalPriors()` for a method that supports priors, but only
  normal ones -- `dnorm()`, `stdNormal()` and the `multiNormal()` family,
  which is what the shorthand above produces when the parameters are
  correlated.  A covariance matrix prior such as `lkjCorr()` is rejected.

Note that these live in `rxode2` rather than here, because what counts as
supported is a property of the estimation method, not of the specification.
