2017-12-27 801 views
0

問題:我並不總是知道我要上使用的Levenberg夸特的行列式或功能載體的確切大小。因此,我需要在編譯時設置它們的尺寸。如何設置使用的本徵DesnseFunctor輸入和值大小在本徵的Levenberg馬夸特

預計:我宣佈MyFunctorDense的一個實例後。我可以將「InputsAtCompileTime」設置爲我的輸入大小,並將「ValuesAtCompileTime」設置爲我的值大小。然後,我的雅可比,aFjac,應該有尺寸tValues X tInputs,和我的功能載體,啊,應該有尺寸tValues X 1.

觀察enter image description here

.h文件中

#pragma once 

#include "stdafx.h" 
#include <iostream> 

#include <unsupported/Eigen/LevenbergMarquardt> 
#include <unsupported/Eigen/NumericalDiff> 


//Generic functor 
template <typename _Scalar, typename _Index> 
struct MySparseFunctor 
{ 
    typedef _Scalar Scalar; 
    typedef _Index Index; 
    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> InputType; 
    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> ValueType; 
    typedef Eigen::SparseMatrix<Scalar, Eigen::ColMajor, Index> 
    JacobianType; 
    typedef Eigen::SparseQR<JacobianType, Eigen::COLAMDOrdering<int> > 
    QRSolver; 
    enum { 
     InputsAtCompileTime = Eigen::Dynamic, 
     ValuesAtCompileTime = Eigen::Dynamic 
    }; 

    MySparseFunctor(int inputs, int values) : m_inputs(inputs), 
m_values(values) {} 

    int inputs() const { return m_inputs; } 
    int values() const { return m_values; } 

    const int m_inputs, m_values; 


}; 

template <typename _Scalar, int NX=Eigen::Dynamic, int NY=Eigen::Dynamic> 
struct MyDenseFunctor 
{ 
    typedef _Scalar Scalar; 
    enum { 
    InputsAtCompileTime = NX, 
    ValuesAtCompileTime = NY 
    }; 
    typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType; 
    typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType; 
    typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> 
JacobianType; 
    typedef Eigen::ColPivHouseholderQR<JacobianType> QRSolver; 
    const int m_inputs, m_values; 

    MyDenseFunctor() : m_inputs(InputsAtCompileTime), 
m_values(ValuesAtCompileTime) {} 
    MyDenseFunctor(int inputs, int values) : m_inputs(inputs), 
m_values(values) {} 

    int inputs() const { return m_inputs; } 
    int values() const { return m_values; } 

}; 


struct MyFunctorSparse : MySparseFunctor<double, int> 
{ 
    MyFunctorSparse(void) : MySparseFunctor<double, int>(2 , 2) {} 

    int operator()(const Eigen::VectorXd &aX, //Input 
       Eigen::VectorXd &aF) const; //Output 
    int df(const InputType &aF, JacobianType& aFjac); 
}; 


struct MyFunctorDense : MyDenseFunctor<double> 
{ 
    MyFunctorDense(void) : MyDenseFunctor<double>(Eigen::Dynamic , 
Eigen::Dynamic) {} 

    int operator()(const InputType &aX, //Input 
       ValueType &aF) const; //Output 

    int df(const InputType &aX, JacobianType& aFjac); 
}; 

.cpp文件 的#pragma一次 的#include 「stdafx.h中」 #I nclude 「Main.h」

int MyFunctorSparse::operator()(const Eigen::VectorXd &aX,  //Input 
          Eigen::VectorXd &aF) const  //Output 
{ 
     //F = aX0^2 + aX1^2 
    aF(0) = aX(0)*aX(0) + aX(1)*aX(1); 
    aF(1) = 0; 

    return 0; 
} 

int MyFunctorDense::operator()(const InputType &aX,  //Input 
          ValueType &aF) const  //Output 
{ 
//F = aX0^2 + aX1^2 
for (int i = 0; i < aF.size(); i++) 
{ 
    aF(i) = i*aX(0)*aX(0) + i*(aX(1)-1)*(aX(1)-1); 
} 


    return 0; 
} 


int MyFunctorSparse::df(const InputType &aX, JacobianType& aFjac) 
{ 
    aFjac.coeffRef(0, 0) = 2*aX(0); 
    aFjac.coeffRef(0, 1) = 2*aX(1); 
    aFjac.coeffRef(1, 0) = 0.0; 
    aFjac.coeffRef(1, 1) = 0.0; 

    return 0; 
} 

int MyFunctorDense::df(const InputType &aX, JacobianType& aFjac) 
{ 
    for(int i = 0; i< aFjac.size(); i++) 
    { 
    aFjac(i, 0) = 2*i*aX(0); 
    aFjac(i, 1) = 2*i*(aX(1)-1); 
    } 
    return 0; 
} 

int main(int argc, char *argv[]) 
{ 
    int input; 
    std::cout << "Enter 1 to run LM with DenseFunctor, Enter 2 to run LM with 
SparseFunctor: " << std::endl; 
std::cin >> input; 

    Eigen::VectorXd tX(2); 
    tX(0) = 10; 
    tX(1) = 0.5; 
    int tInputs = tX.rows(); 
    int tValues = 60928; 

    std::cout << "tX: " << tX << std::endl; 

    if (input == 1) 
    { 
    MyFunctorDense myDenseFunctor; 
    tInputs = myDenseFunctor.inputs(); 
    tValues = myDenseFunctor.values(); 

    std::cout << "tInputs : " << tInputs << std::endl; 
    std::cout << "tValues : " << tValues << std::endl; 

    Eigen::LevenbergMarquardt<MyFunctorDense> lm(myDenseFunctor); 
    lm.setMaxfev(30); 
    lm.setXtol(1e-5); 
    lm.minimize(tX); 
    } 

    if (input == 2) 
    { 
    MyFunctorSparse myFunctorSparse; 
    //Eigen::NumericalDiff<MyFunctor> numDiff(myFunctor); 
    //Eigen::LevenbergMarquardt<Eigen::NumericalDiff<MyFunctor>,double> 
    lm(numDiff); 

    Eigen::LevenbergMarquardt<MyFunctorSparse> lm(myFunctorSparse); 
    lm.setMaxfev(2000); 
    lm.setXtol(1e-10); 

    lm.minimize(tX); 
    } 

    std::cout << "tX minimzed: " << tX << std::endl; 

    return 0; 
} 

回答

0

解決方案:我想通了,我的問題。我取代:

const int m_inputs, m_values; 

int m_inputs, m_values; 
在 「.H」 文件,這使得該結構MyFunctorDense的成員變量修改

。是這樣,那麼在線路

std::cout << "tX: " << tX << std::endl; 

低於 「的.cpp」 我補充:

Eigen::VectorXd tF(60928); 

,因爲這是尺寸60928x1的測試功能向量。因此,我可以放入任意nx1維度。

然後下面一行:

MyFunctorDense myDenseFunctor; 

我說:

myDenseFunctor.m_inputs = tX.rows(); 
    myDenseFunctor.m_values = tF.rows(); 

現在我得到的結果是:

enter image description here

相關問題