1 // This file is part of Eigen, a lightweight C++ template library
4 // Copyright (C) 2012 Desire Nuentsa <desire.nuentsa_wakam@inria.fr>
5 // Copyright (C) 2012 Gael Guennebaud <gael.guennebaud@inria.fr>
7 // This Source Code Form is subject to the terms of the Mozilla
8 // Public License v. 2.0. If a copy of the MPL was not distributed
9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
16 #include <Eigen/LevenbergMarquardt>
18 using namespace Eigen
;
20 template<typename Scalar
>
21 struct DenseLM
: DenseFunctor
<Scalar
>
23 typedef DenseFunctor
<Scalar
> Base
;
24 typedef typename
Base::JacobianType JacobianType
;
25 typedef Matrix
<Scalar
,Dynamic
,1> VectorType
;
27 DenseLM(int n
, int m
) : DenseFunctor
<Scalar
>(n
,m
)
30 VectorType
model(const VectorType
& uv
, VectorType
& x
)
32 VectorType y
; // Should change to use expression template
33 int m
= Base::values();
34 int n
= Base::inputs();
35 eigen_assert(uv
.size()%2 == 0);
36 eigen_assert(uv
.size() == n
);
37 eigen_assert(x
.size() == m
);
40 VectorBlock
<const VectorType
> u(uv
, 0, half
);
41 VectorBlock
<const VectorType
> v(uv
, half
, half
);
42 for (int j
= 0; j
< m
; j
++)
44 for (int i
= 0; i
< half
; i
++)
45 y(j
) += u(i
)*std::exp(-(x(j
)-i
)*(x(j
)-i
)/(v(i
)*v(i
)));
50 void initPoints(VectorType
& uv_ref
, VectorType
& x
)
53 m_y
= this->model(uv_ref
, x
);
56 int operator()(const VectorType
& uv
, VectorType
& fvec
)
59 int m
= Base::values();
60 int n
= Base::inputs();
61 eigen_assert(uv
.size()%2 == 0);
62 eigen_assert(uv
.size() == n
);
63 eigen_assert(fvec
.size() == m
);
65 VectorBlock
<const VectorType
> u(uv
, 0, half
);
66 VectorBlock
<const VectorType
> v(uv
, half
, half
);
67 for (int j
= 0; j
< m
; j
++)
70 for (int i
= 0; i
< half
; i
++)
72 fvec(j
) -= u(i
) *std::exp(-(m_x(j
)-i
)*(m_x(j
)-i
)/(v(i
)*v(i
)));
78 int df(const VectorType
& uv
, JacobianType
& fjac
)
80 int m
= Base::values();
81 int n
= Base::inputs();
82 eigen_assert(n
== uv
.size());
83 eigen_assert(fjac
.rows() == m
);
84 eigen_assert(fjac
.cols() == n
);
86 VectorBlock
<const VectorType
> u(uv
, 0, half
);
87 VectorBlock
<const VectorType
> v(uv
, half
, half
);
88 for (int j
= 0; j
< m
; j
++)
90 for (int i
= 0; i
< half
; i
++)
92 fjac
.coeffRef(j
,i
) = -std::exp(-(m_x(j
)-i
)*(m_x(j
)-i
)/(v(i
)*v(i
)));
93 fjac
.coeffRef(j
,i
+half
) = -2.*u(i
)*(m_x(j
)-i
)*(m_x(j
)-i
)/(std::pow(v(i
),3)) * std::exp(-(m_x(j
)-i
)*(m_x(j
)-i
)/(v(i
)*v(i
)));
98 VectorType m_x
, m_y
; //Data Points
101 template<typename FunctorType
, typename VectorType
>
102 int test_minimizeLM(FunctorType
& functor
, VectorType
& uv
)
104 LevenbergMarquardt
<FunctorType
> lm(functor
);
105 LevenbergMarquardtSpace::Status info
;
107 info
= lm
.minimize(uv
);
109 VERIFY_IS_EQUAL(info
, 1);
110 //FIXME Check other parameters
114 template<typename FunctorType
, typename VectorType
>
115 int test_lmder(FunctorType
& functor
, VectorType
& uv
)
117 typedef typename
VectorType::Scalar Scalar
;
118 LevenbergMarquardtSpace::Status info
;
119 LevenbergMarquardt
<FunctorType
> lm(functor
);
120 info
= lm
.lmder1(uv
);
122 VERIFY_IS_EQUAL(info
, 1);
123 //FIXME Check other parameters
127 template<typename FunctorType
, typename VectorType
>
128 int test_minimizeSteps(FunctorType
& functor
, VectorType
& uv
)
130 LevenbergMarquardtSpace::Status info
;
131 LevenbergMarquardt
<FunctorType
> lm(functor
);
132 info
= lm
.minimizeInit(uv
);
133 if (info
==LevenbergMarquardtSpace::ImproperInputParameters
)
137 info
= lm
.minimizeOneStep(uv
);
138 } while (info
==LevenbergMarquardtSpace::Running
);
140 VERIFY_IS_EQUAL(info
, 1);
141 //FIXME Check other parameters
146 void test_denseLM_T()
148 typedef Matrix
<T
,Dynamic
,1> VectorType
;
152 DenseLM
<T
> dense_gaussian(inputs
, values
);
153 VectorType
uv(inputs
),uv_ref(inputs
);
154 VectorType
x(values
);
156 // Generate the reference solution
157 uv_ref
<< -2, 1, 4 ,8, 6, 1.8, 1.2, 1.1, 1.9 , 3;
159 //Generate the reference data points
163 dense_gaussian
.initPoints(uv_ref
, x
);
165 // Generate the initial parameters
166 VectorBlock
<VectorType
> u(uv
, 0, inputs
/2);
167 VectorBlock
<VectorType
> v(uv
, inputs
/2, inputs
/2);
169 // Solve the optimization problem
172 u
.setOnes(); v
.setOnes();
173 test_minimizeLM(dense_gaussian
, uv
);
175 //Solve until the machine precision
176 u
.setOnes(); v
.setOnes();
177 test_lmder(dense_gaussian
, uv
);
179 // Solve step by step
180 v
.setOnes(); u
.setOnes();
181 test_minimizeSteps(dense_gaussian
, uv
);
187 CALL_SUBTEST_2(test_denseLM_T
<double>());
189 // CALL_SUBTEST_2(test_sparseLM_T<std::complex<double>());