merge with default branch

This commit is contained in:
Gael Guennebaud
2014-09-14 17:34:54 +02:00
34 changed files with 426 additions and 111 deletions

View File

@@ -82,7 +82,9 @@ const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::cos() const
\param[in] M a square matrix.
\returns expression representing \f$ \cos(M) \f$.
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cos().
This function computes the matrix cosine. Use ArrayBase::cos() for computing the entry-wise cosine.
The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::cos().
\sa \ref matrixbase_sin "sin()" for an example.
@@ -123,6 +125,9 @@ differential equations: the solution of \f$ y' = My \f$ with the
initial condition \f$ y(0) = y_0 \f$ is given by
\f$ y(t) = \exp(M) y_0 \f$.
The matrix exponential is different from applying the exp function to all the entries in the matrix.
Use ArrayBase::exp() if you want to do the latter.
The cost of the computation is approximately \f$ 20 n^3 \f$ for
matrices of size \f$ n \f$. The number 20 depends weakly on the
norm of the matrix.
@@ -177,6 +182,9 @@ the scalar logarithm, the equation \f$ \exp(X) = M \f$ may have
multiple solutions; this function returns a matrix whose eigenvalues
have imaginary part in the interval \f$ (-\pi,\pi] \f$.
The matrix logarithm is different from applying the log function to all the entries in the matrix.
Use ArrayBase::log() if you want to do the latter.
In the real case, the matrix \f$ M \f$ should be invertible and
it should have no eigenvalues which are real and negative (pairs of
complex conjugate eigenvalues are allowed). In the complex case, it
@@ -232,7 +240,8 @@ const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(RealScalar p) con
The matrix power \f$ M^p \f$ is defined as \f$ \exp(p \log(M)) \f$,
where exp denotes the matrix exponential, and log denotes the matrix
logarithm.
logarithm. This is different from raising all the entries in the matrix
to the p-th power. Use ArrayBase::pow() if you want to do the latter.
If \p p is complex, the scalar type of \p M should be the type of \p
p . \f$ M^p \f$ simply evaluates into \f$ \exp(p \log(M)) \f$.
@@ -391,7 +400,9 @@ const MatrixFunctionReturnValue<Derived> MatrixBase<Derived>::sin() const
\param[in] M a square matrix.
\returns expression representing \f$ \sin(M) \f$.
This function calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sin().
This function computes the matrix sine. Use ArrayBase::sin() for computing the entry-wise sine.
The implementation calls \ref matrixbase_matrixfunction "matrixFunction()" with StdStemFunctions::sin().
Example: \include MatrixSine.cpp
Output: \verbinclude MatrixSine.out
@@ -428,7 +439,9 @@ const MatrixSquareRootReturnValue<Derived> MatrixBase<Derived>::sqrt() const
The matrix square root of \f$ M \f$ is the matrix \f$ M^{1/2} \f$
whose square is the original matrix; so if \f$ S = M^{1/2} \f$ then
\f$ S^2 = M \f$.
\f$ S^2 = M \f$. This is different from taking the square root of all
the entries in the matrix; use ArrayBase::sqrt() if you want to do the
latter.
In the <b>real case</b>, the matrix \f$ M \f$ should be invertible and
it should have no eigenvalues which are real and negative (pairs of

View File

@@ -45,18 +45,24 @@ namespace LevenbergMarquardtSpace {
template<typename FunctorType, typename Scalar=double>
class LevenbergMarquardt
{
static Scalar sqrt_epsilon()
{
using std::sqrt;
return sqrt(NumTraits<Scalar>::epsilon());
}
public:
LevenbergMarquardt(FunctorType &_functor)
: functor(_functor) { nfev = njev = iter = 0; fnorm = gnorm = 0.; useExternalScaling=false; }
typedef DenseIndex Index;
struct Parameters {
Parameters()
: factor(Scalar(100.))
, maxfev(400)
, ftol(sqrt_(NumTraits<Scalar>::epsilon()))
, xtol(sqrt_(NumTraits<Scalar>::epsilon()))
, ftol(sqrt_epsilon())
, xtol(sqrt_epsilon())
, gtol(Scalar(0.))
, epsfcn(Scalar(0.)) {}
Scalar factor;
@@ -72,7 +78,7 @@ public:
LevenbergMarquardtSpace::Status lmder1(
FVectorType &x,
const Scalar tol = sqrt_(NumTraits<Scalar>::epsilon())
const Scalar tol = sqrt_epsilon()
);
LevenbergMarquardtSpace::Status minimize(FVectorType &x);
@@ -83,12 +89,12 @@ public:
FunctorType &functor,
FVectorType &x,
Index *nfev,
const Scalar tol = sqrt_(NumTraits<Scalar>::epsilon())
const Scalar tol = sqrt_epsilon()
);
LevenbergMarquardtSpace::Status lmstr1(
FVectorType &x,
const Scalar tol = sqrt_(NumTraits<Scalar>::epsilon())
const Scalar tol = sqrt_epsilon()
);
LevenbergMarquardtSpace::Status minimizeOptimumStorage(FVectorType &x);
@@ -109,7 +115,6 @@ public:
Scalar lm_param(void) { return par; }
private:
static Scalar sqrt_(const Scalar& x) { using std::sqrt; return sqrt(x); }
FunctorType &functor;
Index n;

View File

@@ -1022,7 +1022,8 @@ void testNistLanczos1(void)
VERIFY_IS_EQUAL(lm.nfev, 79);
VERIFY_IS_EQUAL(lm.njev, 72);
// check norm^2
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.430899764097e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
std::cout.precision(30);
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.4290986055242372e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
// check x
VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
@@ -1043,7 +1044,7 @@ void testNistLanczos1(void)
VERIFY_IS_EQUAL(lm.nfev, 9);
VERIFY_IS_EQUAL(lm.njev, 8);
// check norm^2
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.428595533845e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.430571737783119393e-25); // should be 1.4307867721E-25, but nist results are on 128-bit floats
// check x
VERIFY_IS_APPROX(x[0], 9.5100000027E-02);
VERIFY_IS_APPROX(x[1], 1.0000000001E+00);
@@ -1262,8 +1263,8 @@ void testNistBoxBOD(void)
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev, 31);
VERIFY_IS_EQUAL(lm.njev, 25);
VERIFY(lm.nfev < 31); // 31
VERIFY(lm.njev < 25); // 25
// check norm^2
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 1.1680088766E+03);
// check x
@@ -1342,10 +1343,6 @@ void testNistMGH17(void)
lm.parameters.maxfev = 1000;
info = lm.minimize(x);
// check return value
VERIFY_IS_EQUAL(info, 2);
VERIFY_IS_EQUAL(lm.nfev, 602 );
VERIFY_IS_EQUAL(lm.njev, 545 );
// check norm^2
VERIFY_IS_APPROX(lm.fvec.squaredNorm(), 5.4648946975E-05);
// check x
@@ -1354,6 +1351,11 @@ void testNistMGH17(void)
VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
// check return value
VERIFY_IS_EQUAL(info, 2);
VERIFY(lm.nfev < 650); // 602
VERIFY(lm.njev < 600); // 545
/*
* Second try
@@ -1832,8 +1834,8 @@ void test_NonLinearOptimization()
// NIST tests, level of difficulty = "Average"
CALL_SUBTEST/*_5*/(testNistHahn1());
CALL_SUBTEST/*_6*/(testNistMisra1d());
// CALL_SUBTEST/*_7*/(testNistMGH17());
// CALL_SUBTEST/*_8*/(testNistLanczos1());
CALL_SUBTEST/*_7*/(testNistMGH17());
CALL_SUBTEST/*_8*/(testNistLanczos1());
// // NIST tests, level of difficulty = "Higher"
CALL_SUBTEST/*_9*/(testNistRat42());

View File

@@ -787,16 +787,17 @@ void testNistMGH10(void)
LevenbergMarquardt<MGH10_functor> lm(functor);
info = lm.minimize(x);
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 284 );
VERIFY_IS_EQUAL(lm.njev(), 249 );
// check norm^2
VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
// check x
VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
// check return value
//VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 284 );
VERIFY_IS_EQUAL(lm.njev(), 249 );
/*
* Second try
@@ -805,16 +806,17 @@ void testNistMGH10(void)
// do the computation
info = lm.minimize(x);
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 126);
VERIFY_IS_EQUAL(lm.njev(), 116);
// check norm^2
VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 8.7945855171E+01);
// check x
VERIFY_IS_APPROX(x[0], 5.6096364710E-03);
VERIFY_IS_APPROX(x[1], 6.1813463463E+03);
VERIFY_IS_APPROX(x[2], 3.4522363462E+02);
// check return value
//VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 126);
VERIFY_IS_EQUAL(lm.njev(), 116);
}
@@ -866,15 +868,16 @@ void testNistBoxBOD(void)
lm.setFactor(10);
info = lm.minimize(x);
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 31);
VERIFY_IS_EQUAL(lm.njev(), 25);
// check norm^2
VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 1.1680088766E+03);
// check x
VERIFY_IS_APPROX(x[0], 2.1380940889E+02);
VERIFY_IS_APPROX(x[1], 5.4723748542E-01);
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY(lm.nfev() < 31); // 31
VERIFY(lm.njev() < 25); // 25
/*
* Second try
@@ -948,10 +951,6 @@ void testNistMGH17(void)
lm.setMaxfev(1000);
info = lm.minimize(x);
// check return value
// VERIFY_IS_EQUAL(info, 2); //FIXME Use (lm.info() == Success)
// VERIFY_IS_EQUAL(lm.nfev(), 602 );
VERIFY_IS_EQUAL(lm.njev(), 545 );
// check norm^2
VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 5.4648946975E-05);
// check x
@@ -960,6 +959,11 @@ void testNistMGH17(void)
VERIFY_IS_APPROX(x[2], -1.4646871366E+00);
VERIFY_IS_APPROX(x[3], 1.2867534640E-02);
VERIFY_IS_APPROX(x[4], 2.2122699662E-02);
// check return value
// VERIFY_IS_EQUAL(info, 2); //FIXME Use (lm.info() == Success)
VERIFY(lm.nfev() < 700 ); // 602
VERIFY(lm.njev() < 600 ); // 545
/*
* Second try
@@ -1035,10 +1039,6 @@ void testNistMGH09(void)
lm.setMaxfev(1000);
info = lm.minimize(x);
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY_IS_EQUAL(lm.nfev(), 490 );
VERIFY_IS_EQUAL(lm.njev(), 376 );
// check norm^2
VERIFY_IS_APPROX(lm.fvec().squaredNorm(), 3.0750560385E-04);
// check x
@@ -1046,6 +1046,10 @@ void testNistMGH09(void)
VERIFY_IS_APPROX(x[1], 0.19126423573); // should be 1.9128232873E-01
VERIFY_IS_APPROX(x[2], 0.12305309914); // should be 1.2305650693E-01
VERIFY_IS_APPROX(x[3], 0.13605395375); // should be 1.3606233068E-01
// check return value
VERIFY_IS_EQUAL(info, 1);
VERIFY(lm.nfev() < 510 ); // 490
VERIFY(lm.njev() < 400 ); // 376
/*
* Second try