diff --git a/unsupported/Eigen/NonLinear b/unsupported/Eigen/NonLinear new file mode 100644 index 000000000..85b958f97 --- /dev/null +++ b/unsupported/Eigen/NonLinear @@ -0,0 +1,17 @@ +#ifndef EIGEN_NONLINEAR_MODULE_H +#define EIGEN_NONLINEAR_MODULE_H + +#include + +namespace Eigen { + +/** \ingroup Unsupported_modules + * \defgroup Support for non linear optimization and non linear least + * square using minpack routines. + */ + +#include "src/NonLinear/MathFunctions.h" + +} + +#endif // EIGEN_NONLINEAR_MODULE_H diff --git a/unsupported/Eigen/src/NonLinear/CMakeLists.txt b/unsupported/Eigen/src/NonLinear/CMakeLists.txt new file mode 100644 index 000000000..3fbab502c --- /dev/null +++ b/unsupported/Eigen/src/NonLinear/CMakeLists.txt @@ -0,0 +1,6 @@ +FILE(GLOB Eigen_NonLinear_SRCS "*.h") + +INSTALL(FILES + ${Eigen_NonLinear_SRCS} + DESTINATION ${INCLUDE_INSTALL_DIR}/unsupported/Eigen/src/NonLinear COMPONENT Devel + ) diff --git a/unsupported/Eigen/src/NonLinear/MathFunctions.h b/unsupported/Eigen/src/NonLinear/MathFunctions.h new file mode 100644 index 000000000..f4688cc7d --- /dev/null +++ b/unsupported/Eigen/src/NonLinear/MathFunctions.h @@ -0,0 +1,30 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Thomas Capricelli +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_NONLINEAR_MATHFUNCTIONS_H +#define EIGEN_NONLINEAR_MATHFUNCTIONS_H + +#include + +#endif // EIGEN_NONLINEAR_MATHFUNCTIONS_H diff --git a/unsupported/test/CMakeLists.txt b/unsupported/test/CMakeLists.txt index abfbb0185..c264249ec 100644 --- a/unsupported/test/CMakeLists.txt +++ b/unsupported/test/CMakeLists.txt @@ -15,6 +15,11 @@ else(ADOLC_FOUND) ei_add_property(EIGEN_MISSING_BACKENDS "Adolc") endif(ADOLC_FOUND) +# temporary : +include_directories(/home/orzel/tmp/cminpack-1.0.2/) +LINK_LIBRARIES(/home/orzel/tmp/cminpack-1.0.2/libminpack.a) + +ei_add_test(NonLinear) ei_add_test(autodiff) ei_add_test(BVH) ei_add_test(matrixExponential) diff --git a/unsupported/test/NonLinear.cpp b/unsupported/test/NonLinear.cpp new file mode 100644 index 000000000..74ea2dedb --- /dev/null +++ b/unsupported/test/NonLinear.cpp @@ -0,0 +1,126 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Thomas Capricelli + + +#include "main.h" + +#include +#include +#include + + +int fcn(int m, int n, const double *x, double *fvec, double *fjac, int ldfjac, int iflag); + +void testChkder() +{ + int i, m, n, ldfjac; + double x[3], fvec[15], fjac[15*3], xp[3], fvecp[15], + err[15]; + + m = 15; + n = 3; + + /* the following values should be suitable for */ + /* checking the jacobian matrix. */ + + x[1-1] = 9.2e-1; + x[2-1] = 1.3e-1; + x[3-1] = 5.4e-1; + + ldfjac = 15; + + chkder(m, n, x, fvec, fjac, ldfjac, xp, fvecp, 1, err); + fcn(m, n, x, fvec, fjac, ldfjac, 1); + fcn(m, n, x, fvec, fjac, ldfjac, 2); + fcn(m, n, xp, fvecp, fjac, ldfjac, 1); + chkder(m, n, x, fvec, fjac, ldfjac, xp, fvecp, 2, err); + + for (i=1; i<=m; i++) + { + fvecp[i-1] = fvecp[i-1] - fvec[i-1]; + } + + + double fvec_ref[] = { + -1.181606, -1.429655, -1.606344, + -1.745269, -1.840654, -1.921586, + -1.984141, -2.022537, -2.468977, + -2.827562, -3.473582, -4.437612, + -6.047662, -9.267761, -18.91806 + }; + double fvecp_ref[] = { + -7.724666e-09, -3.432406e-09, -2.034843e-10, + 2.313685e-09, 4.331078e-09, 5.984096e-09, + 7.363281e-09, 8.53147e-09, 1.488591e-08, + 2.33585e-08, 3.522012e-08, 5.301255e-08, + 8.26666e-08, 1.419747e-07, 3.19899e-07 + }; + double err_ref[] = { + 0.1141397, 0.09943516, 0.09674474, + 0.09980447, 0.1073116, 0.1220445, + 0.1526814, 1, 1, + 1, 1, 1, + 1, 1, 1 + }; + + for (i=1; i<=m; i++) VERIFY_IS_APPROX(fvec[i-1], fvec_ref[i-1]); + for (i=1; i<=m; i++) VERIFY_IS_APPROX(fvecp[i-1], fvecp_ref[i-1]); + for (i=1; i<=m; i++) VERIFY_IS_APPROX(err[i-1], err_ref[i-1]); + return; +} + +int fcn(int /*m*/, int /*n*/, const double *x, double *fvec, + double *fjac, int ldfjac, int iflag) +{ + /* subroutine fcn for chkder example. */ + + int i; + double tmp1, tmp2, tmp3, tmp4; + double y[15]={1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 2.9e-1, 3.2e-1, 3.5e-1, + 3.9e-1, 3.7e-1, 5.8e-1, 7.3e-1, 9.6e-1, 1.34, 2.1, 4.39}; + + + if (iflag == 0) + { + /* insert print statements here when nprint is positive. */ + return 0; + } + + if (iflag != 2) + + for (i=1; i<=15; i++) + { + tmp1 = i; + tmp2 = 16 - i; + tmp3 = tmp1; + if (i > 8) tmp3 = tmp2; + fvec[i-1] = y[i-1] - (x[1-1] + tmp1/(x[2-1]*tmp2 + x[3-1]*tmp3)); + } + else + { + for (i = 1; i <= 15; i++) + { + tmp1 = i; + tmp2 = 16 - i; + + /* error introduced into next statement for illustration. */ + /* corrected statement should read tmp3 = tmp1 . */ + + tmp3 = tmp2; + if (i > 8) tmp3 = tmp2; + tmp4 = (x[2-1]*tmp2 + x[3-1]*tmp3); tmp4=tmp4*tmp4; + fjac[i-1+ ldfjac*(1-1)] = -1.; + fjac[i-1+ ldfjac*(2-1)] = tmp1*tmp2/tmp4; + fjac[i-1+ ldfjac*(3-1)] = tmp1*tmp3/tmp4; + } + } + return 0; +} + + +void test_NonLinear() +{ + CALL_SUBTEST(testChkder()); +}