template<typename _MatrixType>
class Eigen::RealQZ< _MatrixType >
Выполняет вещественное QZ-разложение пары квадратных матриц.
Определено в модуле Eigenvalues.
#include <Eigen/Eigenvalues>
- Параметры шаблона
-
| _MatrixType |
тип матрицы, для которой вычисляется вещественное QZ-разложение; ожидается, что это будет экземпляр шаблона класса Matrix. |
Даны вещественные квадратные матрицы A и B, этот класс вычисляет вещественное QZ-разложение: \( A = Q S Z \), \( B = Q T Z \), где Q и Z — вещественные ортогональные матрицы, T — верхнетреугольная матрица, а S — верхнеквазитреугольная матрица. Ортогональная матрица — это матрица, обратная которой равна её транспонированной, \( U^{-1} = U^T \). Квазитреугольная матрица — это блочно-треугольная матрица, диагональ которой состоит из блоков 1x1 и 2x2, где дальнейшее сокращение невозможно из-за комплексных собственных значений.
Собственные значения пучка \( A - z B \) можно получить из блоков 1x1 и 2x2 на диагоналях S и T.
Вызовите функцию compute(), чтобы вычислить вещественное QZ-разложение заданной пары матриц. В качестве альтернативы можно использовать конструктор RealQZ(const MatrixType& B, const MatrixType& B, bool computeQZ), который вычисляет вещественное QZ-разложение во время создания. После вычисления разложения можно использовать функции matrixS(), matrixT(), matrixQ() и matrixZ() для получения матриц S, T, Q и Z в разложении. Если computeQZ == false, некоторое время экономится за счёт того, что матрицы Q и Z не вычисляются.
Пример:
MatrixXf A = MatrixXf::Random(4,4);
MatrixXf B = MatrixXf::Random(4,4);
RealQZ<MatrixXf> qz(4); // preallocate space for 4x4 matrices
qz.compute(A,B); // A = Q S Z, B = Q T Z
// print original matrices and result of decomposition
cout << "A:\n" << A << "\n" << "B:\n" << B << "\n";
cout << "S:\n" << qz.matrixS() << "\n" << "T:\n" << qz.matrixT() << "\n";
cout << "Q:\n" << qz.matrixQ() << "\n" << "Z:\n" << qz.matrixZ() << "\n";
// verify precision
cout << "\nErrors:"
<< "\n|A-QSZ|: " << (A-qz.matrixQ()*qz.matrixS()*qz.matrixZ()).norm()
<< ", |B-QTZ|: " << (B-qz.matrixQ()*qz.matrixT()*qz.matrixZ()).norm()
<< "\n|QQ* - I|: " << (qz.matrixQ()*qz.matrixQ().adjoint() - MatrixXf::Identity(4,4)).norm()
<< ", |ZZ* - I|: " << (qz.matrixZ()*qz.matrixZ().adjoint() - MatrixXf::Identity(4,4)).norm()
<< "\n";
Вывод:
A:
0.68 0.823 -0.444 -0.27
-0.211 -0.605 0.108 0.0268
0.566 -0.33 -0.0452 0.904
0.597 0.536 0.258 0.832
B:
0.271 -0.967 -0.687 0.998
0.435 -0.514 -0.198 -0.563
-0.717 -0.726 -0.74 0.0259
0.214 0.608 -0.782 0.678
S:
-0.668 1.26 -0.598 0.0941
0.317 -0.27 -0.279 0.64
0 0 -0.398 -0.164
0 0 0 -1.12
T:
-1.55 0 0.342 -0.54
0 1.01 -0.457 0.128
0 0 -1.25 0.438
0 0 0 0.746
Q:
-0.587 -0.138 0.552 0.576
0.19 -0.208 0.761 -0.585
-0.292 0.918 0.152 -0.223
-0.731 -0.31 -0.306 -0.526
Z:
-0.0204 0.213 -0.78 0.588
-0.961 -0.184 -0.14 -0.153
-0.269 0.783 0.462 0.32
-0.0674 -0.555 0.398 0.727
Errors:
|A-QSZ|: 1.36e-06, |B-QTZ|: 1.83e-06
|QQ* - I|: 8.18e-07, |ZZ* - I|: 7.36e-07
- Примечание
- Реализация основана на алгоритме из книги «Матричные вычисления» Дж. Голуба и Ч. Вэн Лоана, а также на статье «Алгоритм для обобщённых задач на собственные значения» К. Молера и Дж. Стюарта.
- См. также
- класс RealSchur, класс ComplexSchur, класс EigenSolver, класс ComplexEigenSolver