如何从 QR 分解输出中获取 Q?
How to get the Q from the QR factorization output?
DGEQRF and SGEQRF 来自 LAPACK return 打包格式的 QR 因式分解的 Q 部分。解包好像需要O(k^3)
步(k个低阶产品),好像不是很直接。另外,我不清楚进行 k
顺序乘法的数值稳定性。
LAPACK是否包含解包Q的子程序,如果没有,我应该怎么做?
您正在寻找
DORMQR(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
它计算 Q * C
,其中 Q = H(1) H(2) . . . H(k)
从 DGEQRF
返回。只需使用 C = I
.
有关更多信息,请查看 here。
是的,LAPACK确实提供了从基本反射器(即DGEQRF编辑的return数据部分)检索Q的例程,它被称为DORGQR。来自描述:
* DORGQR generates an M-by-N real matrix Q with orthonormal columns,
* which is defined as the first N columns of a product of K elementary
* reflectors of order M
*
* Q = H(1) H(2) . . . H(k)
* as returned by DGEQRF.
使用 C
-wrapper LAPACKE 从 A
完整计算 Q
和 R
可能看起来像这样(Fortran 改编应该是直截了当的):
void qr( double* const _Q, double* const _R, double* const _A, const size_t _m, const size_t _n) {
// Maximal rank is used by Lapacke
const size_t rank = std::min(_m, _n);
// Tmp Array for Lapacke
const std::unique_ptr<double[]> tau(new double[rank]);
// Calculate QR factorisations
LAPACKE_dgeqrf(LAPACK_ROW_MAJOR, (int) _m, (int) _n, _A, (int) _n, tau.get());
// Copy the upper triangular Matrix R (rank x _n) into position
for(size_t row =0; row < rank; ++row) {
memset(_R+row*_n, 0, row*sizeof(double)); // Set starting zeros
memcpy(_R+row*_n+row, _A+row*_n+row, (_n-row)*sizeof(double)); // Copy upper triangular part from Lapack result.
}
// Create orthogonal matrix Q (in tmpA)
LAPACKE_dorgqr(LAPACK_ROW_MAJOR, (int) _m, (int) rank, (int) rank, _A, (int) _n, tau.get());
//Copy Q (_m x rank) into position
if(_m == _n) {
memcpy(_Q, _A, sizeof(double)*(_m*_n));
} else {
for(size_t row =0; row < _m; ++row) {
memcpy(_Q+row*rank, _A+row*_n, sizeof(double)*(rank));
}
}
}
这是我自己的一段代码,我在其中删除了所有检查以提高可读性。对于生产性使用,您需要检查输入是否有效,并且还要注意 LAPACK 调用的 return 值。注意输入A
被销毁
DGEQRF and SGEQRF 来自 LAPACK return 打包格式的 QR 因式分解的 Q 部分。解包好像需要O(k^3)
步(k个低阶产品),好像不是很直接。另外,我不清楚进行 k
顺序乘法的数值稳定性。
LAPACK是否包含解包Q的子程序,如果没有,我应该怎么做?
您正在寻找
DORMQR(SIDE, TRANS, M, N, K, A, LDA, TAU, C, LDC, WORK, LWORK, INFO)
它计算 Q * C
,其中 Q = H(1) H(2) . . . H(k)
从 DGEQRF
返回。只需使用 C = I
.
有关更多信息,请查看 here。
是的,LAPACK确实提供了从基本反射器(即DGEQRF编辑的return数据部分)检索Q的例程,它被称为DORGQR。来自描述:
* DORGQR generates an M-by-N real matrix Q with orthonormal columns,
* which is defined as the first N columns of a product of K elementary
* reflectors of order M
*
* Q = H(1) H(2) . . . H(k)
* as returned by DGEQRF.
使用 C
-wrapper LAPACKE 从 A
完整计算 Q
和 R
可能看起来像这样(Fortran 改编应该是直截了当的):
void qr( double* const _Q, double* const _R, double* const _A, const size_t _m, const size_t _n) {
// Maximal rank is used by Lapacke
const size_t rank = std::min(_m, _n);
// Tmp Array for Lapacke
const std::unique_ptr<double[]> tau(new double[rank]);
// Calculate QR factorisations
LAPACKE_dgeqrf(LAPACK_ROW_MAJOR, (int) _m, (int) _n, _A, (int) _n, tau.get());
// Copy the upper triangular Matrix R (rank x _n) into position
for(size_t row =0; row < rank; ++row) {
memset(_R+row*_n, 0, row*sizeof(double)); // Set starting zeros
memcpy(_R+row*_n+row, _A+row*_n+row, (_n-row)*sizeof(double)); // Copy upper triangular part from Lapack result.
}
// Create orthogonal matrix Q (in tmpA)
LAPACKE_dorgqr(LAPACK_ROW_MAJOR, (int) _m, (int) rank, (int) rank, _A, (int) _n, tau.get());
//Copy Q (_m x rank) into position
if(_m == _n) {
memcpy(_Q, _A, sizeof(double)*(_m*_n));
} else {
for(size_t row =0; row < _m; ++row) {
memcpy(_Q+row*rank, _A+row*_n, sizeof(double)*(rank));
}
}
}
这是我自己的一段代码,我在其中删除了所有检查以提高可读性。对于生产性使用,您需要检查输入是否有效,并且还要注意 LAPACK 调用的 return 值。注意输入A
被销毁