# deriv: Symbolic and Algorithmic Derivatives of Simple Expressions

## Description

Compute derivatives of simple expressions, symbolically and algorithmically.

## Usage

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17``` ``` D (expr, name) deriv(expr, ...) deriv3(expr, ...) ## Default S3 method: deriv(expr, namevec, function.arg = NULL, tag = ".expr", hessian = FALSE, ...) ## S3 method for class 'formula' deriv(expr, namevec, function.arg = NULL, tag = ".expr", hessian = FALSE, ...) ## Default S3 method: deriv3(expr, namevec, function.arg = NULL, tag = ".expr", hessian = TRUE, ...) ## S3 method for class 'formula' deriv3(expr, namevec, function.arg = NULL, tag = ".expr", hessian = TRUE, ...) ```

## Arguments

 `expr` a `expression` or `call` or (except `D`) a formula with no lhs. `name,namevec` character vector, giving the variable names (only one for `D()`) with respect to which derivatives will be computed. `function.arg` if specified and non-`NULL`, a character vector of arguments for a function return, or a function (with empty body) or `TRUE`, the latter indicating that a function with argument names `namevec` should be used. `tag` character; the prefix to be used for the locally created variables in result. `hessian` a logical value indicating whether the second derivatives should be calculated and incorporated in the return value. `...` arguments to be passed to or from methods.

## Details

`D` is modelled after its S namesake for taking simple symbolic derivatives.

`deriv` is a generic function with a default and a `formula` method. It returns a `call` for computing the `expr` and its (partial) derivatives, simultaneously. It uses so-called algorithmic derivatives. If `function.arg` is a function, its arguments can have default values, see the `fx` example below.

Currently, `deriv.formula` just calls `deriv.default` after extracting the expression to the right of `~`.

`deriv3` and its methods are equivalent to `deriv` and its methods except that `hessian` defaults to `TRUE` for `deriv3`.

The internal code knows about the arithmetic operators `+`, `-`, `*`, `/` and `^`, and the single-variable functions `exp`, `log`, `sin`, `cos`, `tan`, `sinh`, `cosh`, `sqrt`, `pnorm`, `dnorm`, `asin`, `acos`, `atan`, `gamma`, `lgamma`, `digamma` and `trigamma`, as well as `psigamma` for one or two arguments (but derivative only with respect to the first). (Note that only the standard normal distribution is considered.)
Since R 3.4.0, the single-variable functions `log1p`, `expm1`, `log2`, `log10`, `cospi`, `sinpi`, `tanpi`, `factorial`, and `lfactorial` are supported as well.

## Value

`D` returns a call and therefore can easily be iterated for higher derivatives.

`deriv` and `deriv3` normally return an `expression` object whose evaluation returns the function values with a `"gradient"` attribute containing the gradient matrix. If `hessian` is `TRUE` the evaluation also returns a `"hessian"` attribute containing the Hessian array.

If `function.arg` is not `NULL`, `deriv` and `deriv3` return a function with those arguments rather than an expression.

## References

Griewank, A. and Corliss, G. F. (1991) Automatic Differentiation of Algorithms: Theory, Implementation, and Application. SIAM proceedings, Philadelphia.

Bates, D. M. and Chambers, J. M. (1992) Nonlinear models. Chapter 10 of Statistical Models in S eds J. M. Chambers and T. J. Hastie, Wadsworth & Brooks/Cole.

`nlm` and `optim` for numeric minimization which could make use of derivatives,
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74``` ```## formula argument : dx2x <- deriv(~ x^2, "x") ; dx2x ## Not run: expression({ .value <- x^2 .grad <- array(0, c(length(.value), 1), list(NULL, c("x"))) .grad[, "x"] <- 2 * x attr(.value, "gradient") <- .grad .value }) ## End(Not run) mode(dx2x) x <- -1:2 eval(dx2x) ## Something 'tougher': trig.exp <- expression(sin(cos(x + y^2))) ( D.sc <- D(trig.exp, "x") ) all.equal(D(trig.exp[], "x"), D.sc) ( dxy <- deriv(trig.exp, c("x", "y")) ) y <- 1 eval(dxy) eval(D.sc) ## function returned: deriv((y ~ sin(cos(x) * y)), c("x","y"), func = TRUE) ## function with defaulted arguments: (fx <- deriv(y ~ b0 + b1 * 2^(-x/th), c("b0", "b1", "th"), function(b0, b1, th, x = 1:7){} ) ) fx(2, 3, 4) ## First derivative D(expression(x^2), "x") stopifnot(D(as.name("x"), "x") == 1) ## Higher derivatives deriv3(y ~ b0 + b1 * 2^(-x/th), c("b0", "b1", "th"), c("b0", "b1", "th", "x") ) ## Higher derivatives: DD <- function(expr, name, order = 1) { if(order < 1) stop("'order' must be >= 1") if(order == 1) D(expr, name) else DD(D(expr, name), name, order - 1) } DD(expression(sin(x^2)), "x", 3) ## showing the limits of the internal "simplify()" : ## Not run: -sin(x^2) * (2 * x) * 2 + ((cos(x^2) * (2 * x) * (2 * x) + sin(x^2) * 2) * (2 * x) + sin(x^2) * (2 * x) * 2) ## End(Not run) ## New (R 3.4.0, 2017): D(quote(log1p(x^2)), "x") ## log1p(x) = log(1 + x) stopifnot(identical( D(quote(log1p(x^2)), "x"), D(quote(log(1+x^2)), "x"))) D(quote(expm1(x^2)), "x") ## expm1(x) = exp(x) - 1 stopifnot(identical( D(quote(expm1(x^2)), "x") -> Dex1, D(quote(exp(x^2)-1), "x")), identical(Dex1, quote(exp(x^2) * (2 * x)))) D(quote(sinpi(x^2)), "x") ## sinpi(x) = sin(pi*x) D(quote(cospi(x^2)), "x") ## cospi(x) = cos(pi*x) D(quote(tanpi(x^2)), "x") ## tanpi(x) = tan(pi*x) stopifnot(identical(D(quote(log2 (x^2)), "x"), quote(2 * x/(x^2 * log(2)))), identical(D(quote(log10(x^2)), "x"), quote(2 * x/(x^2 * log(10))))) ```