C++ 用特征值求最近的正定矩阵

C++ 用特征值求最近的正定矩阵,c++,matrix,eigen,C++,Matrix,Eigen,我想找到与某个X矩阵最近的正定矩阵 我在这里看到了这个答案: 但我很难用Eigen将其翻译成答案。我尝试了以下方法: Matrix<double, 9, 9> X, D, DPLUS, Z, Y; X.setRandom(); Y = 0.5 * (X + X.transpose().eval()); EigenSolver<Matrix<double, 9, 9>> es; es.compute(Y); D = es.eigenvalues().asDiag

我想找到与某个X矩阵最近的正定矩阵

我在这里看到了这个答案:

但我很难用Eigen将其翻译成答案。我尝试了以下方法:

Matrix<double, 9, 9> X, D, DPLUS, Z, Y;
X.setRandom();
Y = 0.5 * (X + X.transpose().eval());
EigenSolver<Matrix<double, 9, 9>> es;
es.compute(Y);
D = es.eigenvalues().asDiagonal();
DPlus = D.cwiseMax(0);
Z = es.eigenvectors() * DPLUS * es.eigenvectors().transpose().eval();
矩阵X,D,DPLUS,Z,Y;
X.setRandom();
Y=0.5*(X+X.transpose().eval());
特征解算器;
es.计算(Y);
D=特征值()为对角线();
DPlus=D.cwiseMax(0);
Z=es.eignvectors()*DPLUS*es.eignvectors().transpose().eval();

这给了我一个关于复杂问题的错误,但这与链接答案的建议一致吗?

您没有使用正确的特征值解算器的问题

由于矩阵Y通过构造是对称的,因此需要使用
自伴特征解算器
。 这种对称性保证了实矩阵是可对角化的,并且具有实特征值和特征向量,因此不必处理复数

通用的
特征解算器
不作此假设,因此在本例中不会按您的预期工作。你可以用它得到同样的结果(你会得到复数特征值,它们实际上都是实数,但是你需要创建复数向量等等,而且效率要低得多)

这将为您提供特征值和特征向量,您可以使用它们来构造正交基矩阵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 MatrixXd Y=0.5*(X+X.transpose());
常数自伴特征解算器(Y);
const VectorXd D=解算器特征值();
const MatrixXd Q=解算器特征向量();
常量向量xd 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();
const selfadjointeignsolver(0.5*(X+X.transpose());
const MatrixXd Z=解算器.特征向量()*解算器.特征值().cwiseMax(0).asDiagonal()*解算器.特征向量().transpose();

为什么在回答的第一步之后就停止了?@Aziuth我想我不知道如何完成其他部分,例如,如何从第2步的特征分解中得到对角矩阵?@Aziuth我编辑了以下步骤的问题,是否更内联?如果矩阵是对称的,请使用
自伴特征解算器
。否则,请尝试:
DPlus=es.characterizationals().real().cwiseMax(0.asDiagonal()