Ответ 1
Введение
R использует LINPACK dqrdc
по умолчанию, или LAPACK DGEQP3
, когда это указано, для вычисления QR-декомпозиции. Обе процедуры вычисляют разложение с помощью отражений Householder. Матрица mxn A разбивается на ортогональную матрицу (Q) экономного размера mxn и верхнюю треугольную матрицу nxn (R) как A = QR, где Q можно вычислить произведением t матриц отражения дома, причем t является меньшим m-1 и n: Q = H 1 H 2... H t.
Каждая матрица отражения H i может быть представлена вектором длины - (m-i + 1). Например, для H 1 требуется вектор length-m для компактного хранения. Все, кроме одной записи этого вектора, помещаются в первый столбец нижнего треугольника входной матрицы (диагональ используется фактором R). Поэтому для каждого отражения требуется еще один скаляр памяти, и это обеспечивается вспомогательным вектором (называемым $qraux
в результате от R qr
).
Используемое компактное представление отличается между подпрограммами LINPACK и LAPACK.
Путь LINPACK
Отражение домохозяйства вычисляется как H i= я - v i v i T/p i, где я - единичная матрица, p i является соответствующей записью в $qraux
, а v i выглядит следующим образом:
- v i [1..i-1] = 0,
- v i [i] = p i
- v i [i + 1: m] = A [i + 1..m, i] (т.е. столбец нижнего треугольника A после вызова
qr
)
Пример LINPACK
Позвольте работать с помощью примера из статьи декомпозиции QR в Википедии в R.
Разлагаемая матрица
> A <- matrix(c(12, 6, -4, -51, 167, 24, 4, -68, -41), nrow=3)
> A
[,1] [,2] [,3]
[1,] 12 -51 4
[2,] 6 167 -68
[3,] -4 24 -41
Делаем разложение, и наиболее важные части результата показаны ниже:
> Aqr = qr(A)
> Aqr
$qr
[,1] [,2] [,3]
[1,] -14.0000000 -21.0000000 14
[2,] 0.4285714 -175.0000000 70
[3,] -0.2857143 0.1107692 -35
[snip...]
$qraux
[1] 1.857143 1.993846 35.000000
[snip...]
Это разложение было выполнено (под обложками), вычисляя два отражения Домовладельца и умножая их на A, чтобы получить R. Теперь мы воссоздаем отражения от информации в $qr
.
> p = Aqr$qraux # for convenience
> v1 <- matrix(c(p[1], Aqr$qr[2:3,1]))
> v1
[,1]
[1,] 1.8571429
[2,] 0.4285714
[3,] -0.2857143
> v2 <- matrix(c(0, p[2], Aqr$qr[3,2]))
> v2
[,1]
[1,] 0.0000000
[2,] 1.9938462
[3,] 0.1107692
> I = diag(3) # identity matrix
> H1 = I - v1 %*% t(v1)/p[1] # I - v1*v1^T/p[1]
> H2 = I - v2 %*% t(v2)/p[2] # I - v2*v2^T/p[2]
> Q = H1 %*% H2
> Q
[,1] [,2] [,3]
[1,] -0.8571429 0.3942857 0.33142857
[2,] -0.4285714 -0.9028571 -0.03428571
[3,] 0.2857143 -0.1714286 0.94285714
Теперь давайте проверим, что Q, вычисленное выше, правильно:
> qr.Q(Aqr)
[,1] [,2] [,3]
[1,] -0.8571429 0.3942857 0.33142857
[2,] -0.4285714 -0.9028571 -0.03428571
[3,] 0.2857143 -0.1714286 0.94285714
Выглядит хорошо! Мы также можем проверить, что QR равно A.
> R = qr.R(Aqr) # extract R from Aqr$qr
> Q %*% R
[,1] [,2] [,3]
[1,] 12 -51 4
[2,] 6 167 -68
[3,] -4 24 -41
Путь LAPACK
Отражение домохозяйства вычисляется как H i= я - p i v i v i T где я - единичная матрица, p i является соответствующей записью в $qraux
, а v i выглядит следующим образом:
- v i [1..i-1] = 0,
- v i [i] = 1
- v i [i + 1: m] = A [i + 1..m, i] (т.е. столбец нижнего треугольника A после вызова
qr
)
При использовании LAPACK-подпрограммы в R используется другой поворот: используется разворот столбцов, поэтому разложение решает другую связанную проблему: AP = QR, где P является матрица перестановок.
Пример LAPACK
В этом разделе показан тот же пример, что и раньше.
> A <- matrix(c(12, 6, -4, -51, 167, 24, 4, -68, -41), nrow=3)
> Bqr = qr(A, LAPACK=TRUE)
> Bqr
$qr
[,1] [,2] [,3]
[1,] 176.2554964 -71.1694118 1.668033
[2,] -0.7348557 35.4388886 -2.180855
[3,] -0.1056080 0.6859203 -13.728129
[snip...]
$qraux
[1] 1.289353 1.360094 0.000000
$pivot
[1] 2 3 1
attr(,"useLAPACK")
[1] TRUE
[snip...]
Обратите внимание на поле $pivot
; мы вернемся к этому. Теперь мы генерируем Q из информации Aqr
.
> p = Bqr$qraux # for convenience
> v1 = matrix(c(1, Bqr$qr[2:3,1]))
> v1
[,1]
[1,] 1.0000000
[2,] -0.7348557
[3,] -0.1056080
> v2 = matrix(c(0, 1, Bqr$qr[3,2]))
> v2
[,1]
[1,] 0.0000000
[2,] 1.0000000
[3,] 0.6859203
> H1 = I - p[1]*v1 %*% t(v1) # I - p[1]*v1*v1^T
> H2 = I - p[2]*v2 %*% t(v2) # I - p[2]*v2*v2^T
> Q = H1 %*% H2
[,1] [,2] [,3]
[1,] -0.2893527 -0.46821615 -0.8348944
[2,] 0.9474882 -0.01602261 -0.3193891
[3,] 0.1361660 -0.88346868 0.4482655
Опять же, Q, вычисленное выше, согласуется с R-предоставленным Q.
> qr.Q(Bqr)
[,1] [,2] [,3]
[1,] -0.2893527 -0.46821615 -0.8348944
[2,] 0.9474882 -0.01602261 -0.3193891
[3,] 0.1361660 -0.88346868 0.4482655
Наконец, пусть вычислить QR.
> R = qr.R(Bqr)
> Q %*% R
[,1] [,2] [,3]
[1,] -51 4 12
[2,] 167 -68 6
[3,] 24 -41 -4
Обратите внимание на разницу? QR - это A с его столбцами, перестановоченными с учетом порядка в Bqr$pivot
выше.