sparseQR-class {Matrix} | R Documentation |
Sparse QR Factorizations
Description
sparseQR
is the class of sparse, row- and column-pivoted
QR factorizations of (
)
real matrices, having the general form
or (equivalently)
where
and
are permutation matrices,
is an
orthogonal matrix
(
contains the first
column vectors)
equal to the product of
Householder matrices
, and
is an
upper trapezoidal matrix
(
contains the first
row vectors and is
upper triangular).
Usage
qrR(qr, complete = FALSE, backPermute = TRUE, row.names = TRUE)
Arguments
qr |
an object of class |
complete |
a logical indicating if |
backPermute |
a logical indicating if |
row.names |
a logical indicating if |
Details
The method for qr.Q
does not return but rather the
(also orthogonal) product
. This behaviour
is algebraically consistent with the base implementation
(see
qr
), which can be seen by noting that
qr.default
in base does not pivot rows, constraining
to be an identity matrix. It follows that
qr.Q(qr.default(x))
also returns .
Similarly, the methods for qr.qy
and qr.qty
multiply
on the left by and
rather than
and
.
It is wrong to expect the values of qr.Q
(or qr.R
,
qr.qy
, qr.qty
) computed from “equivalent”
sparse and dense factorizations
(say, qr(x)
and qr(as(x, "matrix"))
for x
of class dgCMatrix
) to compare equal.
The underlying factorization algorithms are quite different,
notably as they employ different pivoting strategies,
and in general the factorization is not unique even for fixed
and
.
On the other hand, the values of qr.X
, qr.coef
,
qr.fitted
, and qr.resid
are well-defined, and
in those cases the sparse and dense computations should
compare equal (within some tolerance).
The method for qr.R
is a simple wrapper around qrR
,
but not back-permuting by default and never giving row names.
It did not support backPermute = TRUE
until Matrix
1.6-0
, hence code needing the back-permuted result should
call qrR
if Matrix >= 1.6-0
is not known.
Slots
Dim
,Dimnames
inherited from virtual class
MatrixFactorization
.beta
a numeric vector of length
Dim[2]
, used to construct Householder matrices; seeV
below.V
an object of class
dgCMatrix
withDim[2]
columns. The number of rowsnrow(V)
is at leastDim[1]
and at mostDim[1]+Dim[2]
.V
is lower trapezoidal, and its column vectors generate the Householder matricesthat compose the orthogonal
factor. Specifically,
is constructed as
diag(Dim[1]) - beta[j] * tcrossprod(V[, j])
.R
an object of class
dgCMatrix
withnrow(V)
rows andDim[2]
columns.R
is the upper trapezoidalfactor.
p
,q
0-based integer vectors of length
nrow(V)
andDim[2]
, respectively, specifying the permutations applied to the rows and columns of the factorized matrix.q
of length 0 is valid and equivalent to the identity permutation, implying no column pivoting. Using R syntax, the matrixis precisely
A[p+1, q+1]
(A[p+1, ]
whenq
has length 0).
Extends
Class QR
, directly.
Class MatrixFactorization
, by class
QR
, distance 2.
Instantiation
Objects can be generated directly by calls of the form
new("sparseQR", ...)
, but they are more typically obtained
as the value of qr(x)
for x
inheriting from
sparseMatrix
(often dgCMatrix
).
Methods
determinant
signature(from = "sparseQR", logarithm = "logical")
: computes the determinant of the factorized matrixor its logarithm.
expand1
signature(x = "sparseQR")
: seeexpand1-methods
.expand2
signature(x = "sparseQR")
: seeexpand2-methods
.qr.Q
signature(qr = "sparseQR")
: returns as adgeMatrix
eitheror
, depending on optional argument
complete
. The default isFALSE
, indicating.
qr.R
signature(qr = "sparseQR")
:qrR
returns,
,
, or
, depending on optional arguments
complete
andbackPermute
. The default in both cases isFALSE
, indicating, for compatibility with base. The class of the result in that case is
dtCMatrix
. In the other three cases, it isdgCMatrix
.qr.X
signature(qr = "sparseQR")
: returnsas a
dgeMatrix
, by default. Ifand optional argument
ncol
is greater than, then the result is augmented with
, where
is composed of columns
through
ncol
of theidentity matrix.
qr.coef
signature(qr = "sparseQR", y = .)
: returns as adgeMatrix
or vector the result of multiplyingy
on the left by.
qr.fitted
signature(qr = "sparseQR", y = .)
: returns as adgeMatrix
or vector the result of multiplyingy
on the left by.
qr.resid
signature(qr = "sparseQR", y = .)
: returns as adgeMatrix
or vector the result of multiplyingy
on the left by.
qr.qty
signature(qr = "sparseQR", y = .)
: returns as adgeMatrix
or vector the result of multiplyingy
on the left by.
qr.qy
signature(qr = "sparseQR", y = .)
: returns as adgeMatrix
or vector the result of multiplyingy
on the left by.
solve
signature(a = "sparseQR", b = .)
: seesolve-methods
.
References
Davis, T. A. (2006). Direct methods for sparse linear systems. Society for Industrial and Applied Mathematics. doi:10.1137/1.9780898718881
Golub, G. H., & Van Loan, C. F. (2013). Matrix computations (4th ed.). Johns Hopkins University Press. doi:10.56021/9781421407944
See Also
Class dgCMatrix
.
Generic function qr
from base,
whose default method qr.default
“defines”
the S3 class qr
of dense QR factorizations.
qr-methods
for methods defined in Matrix.
Generic functions expand1
and expand2
.
The many auxiliary functions for QR factorizations:
qr.Q
, qr.R
, qr.X
,
qr.coef
, qr.fitted
, qr.resid
,
qr.qty
, qr.qy
, and qr.solve
.
Examples
showClass("sparseQR")
set.seed(2)
m <- 300L
n <- 60L
A <- rsparsematrix(m, n, 0.05)
## With dimnames, to see that they are propagated :
dimnames(A) <- dn <- list(paste0("r", seq_len(m)),
paste0("c", seq_len(n)))
(qr.A <- qr(A))
str(e.qr.A <- expand2(qr.A, complete = FALSE), max.level = 2L)
str(E.qr.A <- expand2(qr.A, complete = TRUE), max.level = 2L)
t(sapply(e.qr.A, dim))
t(sapply(E.qr.A, dim))
## Horribly inefficient, but instructive :
slowQ <- function(V, beta) {
d <- dim(V)
Q <- diag(d[1L])
if(d[2L] > 0L) {
for(j in d[2L]:1L) {
cat(j, "\n", sep = "")
Q <- Q - (beta[j] * tcrossprod(V[, j])) %*% Q
}
}
Q
}
ae1 <- function(a, b, ...) all.equal(as(a, "matrix"), as(b, "matrix"), ...)
ae2 <- function(a, b, ...) ae1(unname(a), unname(b), ...)
## A ~ P1' Q R P2' ~ P1' Q1 R1 P2' in floating point
stopifnot(exprs = {
identical(names(e.qr.A), c("P1.", "Q1", "R1", "P2."))
identical(names(E.qr.A), c("P1.", "Q" , "R" , "P2."))
identical(e.qr.A[["P1."]],
new("pMatrix", Dim = c(m, m), Dimnames = c(dn[1L], list(NULL)),
margin = 1L, perm = invertPerm(qr.A@p, 0L, 1L)))
identical(e.qr.A[["P2."]],
new("pMatrix", Dim = c(n, n), Dimnames = c(list(NULL), dn[2L]),
margin = 2L, perm = invertPerm(qr.A@q, 0L, 1L)))
identical(e.qr.A[["R1"]], triu(E.qr.A[["R"]][seq_len(n), ]))
identical(e.qr.A[["Q1"]], E.qr.A[["Q"]][, seq_len(n)] )
identical(E.qr.A[["R"]], qr.A@R)
## ae1(E.qr.A[["Q"]], slowQ(qr.A@V, qr.A@beta))
ae1(crossprod(E.qr.A[["Q"]]), diag(m))
ae1(A, with(e.qr.A, P1. %*% Q1 %*% R1 %*% P2.))
ae1(A, with(E.qr.A, P1. %*% Q %*% R %*% P2.))
ae2(A.perm <- A[qr.A@p + 1L, qr.A@q + 1L], with(e.qr.A, Q1 %*% R1))
ae2(A.perm , with(E.qr.A, Q %*% R ))
})
## More identities
b <- rnorm(m)
stopifnot(exprs = {
ae1(qrX <- qr.X (qr.A ), A)
ae2(qrQ <- qr.Q (qr.A ), with(e.qr.A, P1. %*% Q1))
ae2( qr.R (qr.A ), with(e.qr.A, R1))
ae2(qrc <- qr.coef (qr.A, b), with(e.qr.A, solve(R1 %*% P2., t(qrQ)) %*% b))
ae2(qrf <- qr.fitted(qr.A, b), with(e.qr.A, tcrossprod(qrQ) %*% b))
ae2(qrr <- qr.resid (qr.A, b), b - qrf)
ae2(qrq <- qr.qy (qr.A, b), with(E.qr.A, P1. %*% Q %*% b))
ae2(qr.qty(qr.A, qrq), b)
})
## Sparse and dense computations should agree here
qr.Am <- qr(as(A, "matrix")) # <=> qr.default(A)
stopifnot(exprs = {
ae2(qrX, qr.X (qr.Am ))
ae2(qrc, qr.coef (qr.Am, b))
ae2(qrf, qr.fitted(qr.Am, b))
ae2(qrr, qr.resid (qr.Am, b))
})