2017-12-27 31 views
0

문제 : Levenberg Marquardt를 사용할 Jacobian 또는 Function 벡터의 정확한 크기를 항상 알 수는 없습니다. 따라서 컴파일 시간에 이들의 크기를 설정해야합니다.Eigen Levenberg Marquardt에서 사용하기 위해 Eigen DesnseFunctor 입력 및 값 크기를 설정하는 방법

예상 : MyFunctorDense 인스턴스를 선언 한 후. "InputsAtCompileTime"을 입력 크기로 설정하고 "ValuesAtCompileTime"을 값 크기로 설정할 수 있습니다. 그런 다음 내 코비, aFjac는 치수를 tValues의 X의 tInputs을해야하고, 내 기능 벡터, 아, 치수를해야 1.

을 관찰 X tValues ​​: 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 "Main.h"를 nclude

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; 

이 구조체 MyFunctorDense의 멤버 변수를 수정하게 ".H"파일에

int m_inputs, m_values; 

와 함께. 그래서, 해, 행

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

아래의 "통화 당"내가 추가 :

Eigen::VectorXd tF(60928); 

를이 치수 60928x1의 테스트 기능 벡터이기 때문이다. 따라서 임의의 nx1 차원을 넣을 수 있습니다.

MyFunctorDense myDenseFunctor; 

내가 추가 :

enter image description here

:

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

지금 내가 결과를 얻을, 행 아래