[英]MEX-file implementing Eigen library pseudo-inverse function crashes
我正在嘗試在Matlab MEX文件中實現本征庫偽逆函數。 它編譯成功,但是在運行時崩潰。
我正在嘗試按照FAQ上的有關如何使用Eigen庫實現偽逆函數的知識 。
FAQ建議將其作為方法添加到JacobiSVD
類中,但是由於您無法在C ++中做到這一點,因此將其添加至子類中。 它編譯成功,但隨后崩潰,沒有錯誤消息。 如果我用.pinv
調用注釋掉該行,它會成功輸出“ hi”而不會崩潰,這就是問題所在。 要運行,我只需編譯它(如test.cpp
),然后在命令行中輸入test
。 我正在MacOS 10.14.5和Eigen 3.3.7下使用Matlab R2019a。 在我的完整代碼中,我還收到許多有關pinv
代碼的怪異錯誤消息,但是在進行故障排除之前,我需要一個簡單的測試用例來工作。 這一切都是我對C ++理解的極限。 任何幫助表示贊賞。
#include "mex.h"
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <cstdlib>
#include <cmath>
#include <iostream>
using namespace Eigen;
using namespace std;
//https://stackoverflow.com/questions/18804402/add-a-method-to-existing-c-class-in-other-file
class JacobiSVDext : public JacobiSVD<MatrixXf> {
typedef SVDBase<JacobiSVD<MatrixXf>> Base;
public:
using JacobiSVD::JacobiSVD; //inherit constructors //https://stackoverflow.com/questions/347358/inheriting-constructors
MatrixXf pinv() //http://eigen.tuxfamily.org/index.php?title=FAQ
{
eigen_assert(m_isInitialized && "SVD is not initialized.");
double pinvtoler=1.e-6; // choose your tolerance wisely!
JacobiSVDext::SingularValuesType singularValues_inv=m_singularValues;
for ( long i=0; i<m_workMatrix.cols(); ++i) {
if ( m_singularValues(i) > pinvtoler )
singularValues_inv(i)=1.0/m_singularValues(i);
else singularValues_inv(i)=0;
}
return m_matrixV*singularValues_inv.asDiagonal()*m_matrixU.transpose();
};
};
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
MatrixXf X = MatrixXf::Random(5, 5);
JacobiSVDext svd(X);
MatrixXf Y=svd.pinv();
cout << Y << endl;
cout << "hi" << endl;
}
預期結果是輸出隨機矩陣的偽逆以及“ hi”。 相反,它崩潰時沒有錯誤消息。
在構造Eigen::JacobiSVD
對象時,您無法請求應計算矩陣U和V。 默認情況下,不計算這些。 顯然,如果不計算這些矩陣,將導致分割違規。
請參閱構造函數的文檔 。 第二個輸入參數必須指定ComputeFullU | ComputeFullV
ComputeFullU | ComputeFullV
或ComputeThinU | ComputeThinV
ComputeThinU | ComputeThinV
。 計算偽逆時,最好使用細矩陣,因為不需要其余矩陣。
我不會從JacobiSVD
類派生而僅添加一個方法。 相反,我只是寫一個自由函數。 這既容易,又允許您僅使用Eigen API的文檔部分。
我編寫了以下MEX文件,該文件可以按預期工作(使用我已經在此計算中使用的代碼)。 它的作用相同,但略有不同,可避免編寫顯式循環。 不確定這種書寫方式是否很清楚,但是可以。
// Compile with:
// mex -v test.cpp -I/usr/local/include/eigen3
#include "mex.h"
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <cstdlib>
#include <cmath>
#include <iostream>
Eigen::MatrixXf PseudoInverse(Eigen::MatrixXf matrix) {
Eigen::JacobiSVD< Eigen::MatrixXf > svd( matrix, Eigen::ComputeThinU | Eigen::ComputeThinV );
float tolerance = 1.0e-6f * float(std::max(matrix.rows(), matrix.cols())) * svd.singularValues().array().abs()(0);
return svd.matrixV()
* (svd.singularValues().array().abs() > tolerance).select(svd.singularValues().array().inverse(), 0).matrix().asDiagonal()
* svd.matrixU().adjoint();
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
Eigen::MatrixXf X = Eigen::MatrixXf::Random(5, 5);
Eigen::MatrixXf Y = PseudoInverse(X);
std::cout << Y << '\n';
std::cout << "hi\n";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.