簡體   English   中英

實現本征庫偽逆函數的MEX文件崩潰

[英]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 | ComputeFullVComputeThinU | 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM