Проблемы, в которых вы не используете правильный решатель собственных значений.
Поскольку матрица Y симметрична c по конструкции, вам необходимо использовать SelfAdjointEigenSolver
. Эта симметрия гарантирует, что ваша реальная матрица диагонализируется и имеет действительные собственные значения и собственные векторы, поэтому вам не нужно иметь дело с комплексными числами.
Общий EigenSolver
не делает этого предположения и, следовательно, не в этом случае будет работать так, как вы собираетесь. Вы можете получить с ним тот же результат (вы получите комплексные собственные значения, которые будут фактически действительными, но вам нужно будет создать векторы комплексов et c. Кроме того, это намного менее эффективно).
Это даст вам собственные значения и собственные векторы, которые вы можете использовать для построения своей ортогональной базисной матрицы Q .
const MatrixXd Y = 0.5 * (X + X.transpose());
const SelfAdjointEigenSolver<MatrixXd> solver(Y);
const VectorXd D = solver.eigenvalues();
const MatrixXd Q = solver.eigenvectors();
const VectorXd Dplus = D.cwiseMax(0);
const MatrixXd Z = Q * Dplus.asDiagonal() * Q.transpose();
Конечно, если вам нравятся однострочники, вы всегда можете сократить его до:
const SelfAdjointEigenSolver<MatrixXd> solver(0.5 * (X + X.transpose()));
const MatrixXd Z = solver.eigenvectors() * solver.eigenvalues().cwiseMax(0).asDiagonal() * solver.eigenvectors().transpose();