quad.form {emulator}R Documentation

Evaluate a quadratic form efficiently

Description

Given a square matrix M of size n*n, and a matrix x of size n*p (or a vector of length n), evaluate t(x) %*% M %*% x in an efficient manner.

Function quad.form.inv() returns t(x) %*% solve(M) %*% x using an efficient method that avoids inverting M.

Function quad.3form() returns t(l) %*'% M %*% r using nested calls to crossprod(). It's no faster than calling crossprod() directly, but makes code neater (IMHO)

Function quad.tform() returns x %*% A %*% t(x) using tcrossprod() in such a way as to not take a transpose.

Usage

quad.form(M, x, chol=FALSE)
quad.form.inv(M, x)
quad.tform(M, x)
quad.3form(M,left,right)

Arguments

M Square matrix of size n*n
x Matrix of size n*p, or vector of length n
chol Boolean, with TRUE meaning to interpret argument M as the lower triangular Cholesky decomposition of the quadratic form. Remember that M.lower %*% M.upper == M, and chol() returns the upper triangular matrix, so one needs to use the transpose t(chol(M)).
left,right In function quad.3form(), matrices with n rows and arbitrary number of columns

Details

The “meat” of quad.form() for chol=FALSE is just crossprod(crossprod(M, x), x), and that of quad.form.inv() is crossprod(x, solve(M, x)).

If the Cholesky decomposition of M is available, then calling with chol=TRUE and supplying M.upper should generally be faster (for large matrices) than calling with chol=FALSE and using M directly. The time saving is negligible for matrices smaller than about 50*50, even if the overhead of computing M.upper is ignored.

Note

These functions are used extensively in the emulator and calibrator packages' R code in the interests of speed. They are not really intended for the end user.

I have not yet figured out how to calculate x %*% solve(A) %*% t(X) efficiently (the function would be called quad.tform.inv(), if it existed).

Author(s)

Robin K. S. Hankin

See Also

optimize

Examples

jj <- matrix(rnorm(80),20,4)
M <- crossprod(jj,jj)
M.lower <- t(chol(M))
x <- matrix(rnorm(8),4,2)

jj.1 <- t(x) %*% M %*% x
jj.2 <- quad.form(M,x)
jj.3 <- quad.form(M.lower,x,chol=TRUE)

print(jj.1)
print(jj.2)
print(jj.3)

## Now consider accuracy:
quad.form(solve(M),x) - quad.form.inv(M,x)  # should be zero

quad.form(M,x) - quad.tform(M,t(x)) # Should be zero


[Package emulator version 1.0-58 Index]