MEX文件实现特征库伪内函数崩溃



我正在尝试在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 | ComputeFullVComputeThinU | ComputeThinV。计算伪内的薄矩阵时,由于其余的矩阵不需要。


我不会从 JacobiSVD类中得出来添加一种方法。相反,我只需写一个免费的功能。这既更容易,又允许您仅使用特征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 << "hin";
}

最新更新