Как установить входные и выходные значения Eigen DesnseFunctor для использования в Eigen Levenberg Marquardt

проблемаЯ не всегда знаю точный размер вектора Якобиана или Функции, на котором я собираюсь использовать Левенберга Марквардта. Поэтому мне нужно установить их размеры во время компиляции.

ожидаемый: После того, как я объявил экземпляр MyFunctorDense. Я мог бы установить «InputsAtCompileTime» в мой размер ввода и установить «ValuesAtCompileTime» в мой размер значений. Тогда мой якобиан, aFjac, должен иметь размеры tValues ​​x tInputs, а вектор моей функции, aH, должен иметь размеры tValues ​​x 1.

Наблюдаемый:
введите описание изображения здесь

.ч файл

 #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» #include «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» это делает переменную-член struct MyFunctorDense модифицируемой. Итак, тогда в «.cpp» ниже строки

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

Я добавил:

 Eigen::VectorXd tF(60928);

потому что это вектор тестовой функции измерения 60928×1. Поэтому я мог бы положить в любое произвольное измерение nx1.

Затем под чертой:

MyFunctorDense myDenseFunctor;

Я добавил:

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

Теперь я получаю результат:

введите описание изображения здесь

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]