2017-12-27 16 views
0

Problem: Ich weiß nicht immer die genaue Größe des Jacobi- oder Funktionsvektors, auf dem ich Levenberg Marquardt verwenden werde. Daher muss ich die Dimensionen von ihnen zur Kompilierungszeit festlegen.Wie man Eigen DesnseFunctor Eingabe- und Wertgrößen für Eigen Levenberg Marquardt setzt

Erwartet: Nachdem ich eine Instanz von MyFunctorDense erkläre. Ich könnte die "InputsAtCompileTime" auf meine Eingabegröße setzen und "ValuesAtCompileTime" auf meine Wertegröße setzen. Dann ist mein Jacobi, aFjac sollte die Dimensionen tValues ​​x tInputs haben, und meine Funktion Vektor, aH, sollten die Abmessungen haben tValues ​​x 1.

Beobachtet: enter image description here

.h-Datei

#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-Datei #pragma once #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; 
} 

Antwort

0

Lösung: dachte ich, mein Problem heraus. I ersetzt:

const int m_inputs, m_values; 

mit

int m_inputs, m_values; 

in der ".h" Datei dies die Membervariable der Struktur MyFunctorDense modifizierbar macht. Also, dann in dem "CPP" unter der Leitung

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

ich hinzugefügt:

Eigen::VectorXd tF(60928); 

weil dies eine Testfunktion Vektor der Dimension 60928x1 ist. Daher könnte ich jede beliebige nx1-Dimension eingeben.

Dann unterhalb der Linie:

MyFunctorDense myDenseFunctor; 

ich hinzugefügt:

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

Jetzt bekomme ich das Ergebnis:

enter image description here