diff options
author | Thomas Capricelli <orzel@freehackers.org> | 2010-01-25 07:22:28 +0100 |
---|---|---|
committer | Thomas Capricelli <orzel@freehackers.org> | 2010-01-25 07:22:28 +0100 |
commit | ee0e39284c8ddd94ae82604e8bb51a846e3dc644 (patch) | |
tree | 992ab8a5e58449b776bac1850c61af65a4145db8 /unsupported/Eigen | |
parent | 1cb0be05b0f287172dbbfb14a576d89600ffbebe (diff) |
Replace the qr factorization from (c)minpack (qrfac) by Eigen's own stuff.
Results as checked by unit tests are very slightly worse, but not much.
Diffstat (limited to 'unsupported/Eigen')
4 files changed, 48 insertions, 115 deletions
diff --git a/unsupported/Eigen/NonLinearOptimization b/unsupported/Eigen/NonLinearOptimization index f15e09386..a239018b0 100644 --- a/unsupported/Eigen/NonLinearOptimization +++ b/unsupported/Eigen/NonLinearOptimization @@ -129,7 +129,6 @@ namespace Eigen { #include "src/NonLinearOptimization/r1updt.h" #include "src/NonLinearOptimization/r1mpyq.h" #include "src/NonLinearOptimization/rwupdt.h" -#include "src/NonLinearOptimization/qrfac.h" #include "src/NonLinearOptimization/fdjac1.h" #include "src/NonLinearOptimization/qform.h" #include "src/NonLinearOptimization/lmpar.h" diff --git a/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h b/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h index 3bf3d12ea..91efdac68 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h +++ b/unsupported/Eigen/src/NonLinearOptimization/HybridNonLinearSolver.h @@ -218,7 +218,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep( const int mode ) { - int i, j, l, iwa[1]; + int i, j, l; jeval = true; /* calculate the jacobian matrix. */ @@ -249,7 +249,13 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep( } /* compute the qr factorization of the jacobian. */ - ei_qrfac<Scalar>(n, n, fjac.data(), fjac.rows(), false, iwa, wa1.data()); + wa2 = fjac.colwise().blueNorm(); + HouseholderQR<JacobianType> qrfac(fjac); // no pivoting: + fjac = qrfac.matrixQR(); + wa1 = fjac.diagonal(); + fjac.diagonal() = qrfac.hCoeffs(); + // TODO : avoid this: + for(int ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii); // rescale vectors /* form (q transpose)*fvec and store in qtf. */ @@ -280,6 +286,11 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveOneStep( /* accumulate the orthogonal factor in fjac. */ ei_qform<Scalar>(n, n, fjac.data(), fjac.rows(), wa1.data()); +#if 0 + std::cout << "ei_qform<Scalar>: " << fjac << std::endl; + fjac = qrfac.matrixQ(); + std::cout << "qrfac.matrixQ():" << fjac << std::endl; +#endif /* rescale if necessary. */ @@ -530,7 +541,7 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep( const int mode ) { - int i, j, l, iwa[1]; + int i, j, l; jeval = true; if (parameters.nb_of_subdiagonals<0) parameters.nb_of_subdiagonals= n-1; if (parameters.nb_of_superdiagonals<0) parameters.nb_of_superdiagonals= n-1; @@ -563,7 +574,13 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep( } /* compute the qr factorization of the jacobian. */ - ei_qrfac<Scalar>(n, n, fjac.data(), fjac.rows(), false, iwa, wa1.data()); + wa2 = fjac.colwise().blueNorm(); + HouseholderQR<JacobianType> qrfac(fjac); // no pivoting: + fjac = qrfac.matrixQR(); + wa1 = fjac.diagonal(); + fjac.diagonal() = qrfac.hCoeffs(); + // TODO : avoid this: + for(int ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii); // rescale vectors /* form (q transpose)*fvec and store in qtf. */ @@ -594,6 +611,11 @@ HybridNonLinearSolver<FunctorType,Scalar>::solveNumericalDiffOneStep( /* accumulate the orthogonal factor in fjac. */ ei_qform<Scalar>(n, n, fjac.data(), fjac.rows(), wa1.data()); +#if 0 + std::cout << "ei_qform<Scalar>: " << fjac << std::endl; + fjac = qrfac.matrixQ(); + std::cout << "qrfac.matrixQ():" << fjac << std::endl; +#endif /* rescale if necessary. */ diff --git a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h index 8df48d2ab..9f3707952 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h +++ b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h @@ -254,8 +254,13 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep( /* compute the qr factorization of the jacobian. */ wa2 = fjac.colwise().blueNorm(); - ei_qrfac<Scalar>(m, n, fjac.data(), fjac.rows(), true, ipvt.data(), wa1.data()); - ipvt.array() -= 1; // qrfac() creates ipvt with fortran convention (1->n), convert it to c (0->n-1) + ColPivHouseholderQR<JacobianType> qrfac(fjac); + fjac = qrfac.matrixQR(); + wa1 = fjac.diagonal(); + fjac.diagonal() = qrfac.hCoeffs(); + ipvt = qrfac.colsPermutation().indices(); + // TODO : avoid this: + for(int i=0; i< fjac.cols(); i++) fjac.col(i).segment(i+1, fjac.rows()-i-1) *= fjac(i,i); // rescale vectors /* on the first iteration and if mode is 1, scale according */ /* to the norms of the columns of the initial jacobian. */ @@ -295,6 +300,12 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOneStep( qtf[j] = wa4[j]; } +#if 0 + std::cout << "qtf: " << qtf << std::endl; + FVectorType monqtf = qrfac.matrixQ().transpose() * fvec; + std::cout << "mon qtf :" << monqtf << std::endl; +#endif + /* compute the norm of the scaled gradient. */ gnorm = 0.; @@ -540,10 +551,16 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep( wa2[j] = fjac.col(j).head(j).stableNorm(); } if (sing) { - ipvt.array() += 1; wa2 = fjac.colwise().blueNorm(); - ei_qrfac<Scalar>(n, n, fjac.data(), fjac.rows(), true, ipvt.data(), wa1.data()); - ipvt.array() -= 1; // qrfac() creates ipvt with fortran convention (1->n), convert it to c (0->n-1) + // TODO We have no unit test covering this branch.. untested + ColPivHouseholderQR<JacobianType> qrfac(fjac); + fjac = qrfac.matrixQR(); + wa1 = fjac.diagonal(); + fjac.diagonal() = qrfac.hCoeffs(); + ipvt = qrfac.colsPermutation().indices(); + // TODO : avoid this: + for(int ii=0; ii< fjac.cols(); ii++) fjac.col(ii).segment(ii+1, fjac.rows()-ii-1) *= fjac(ii,ii); // rescale vectors + for (j = 0; j < n; ++j) { if (fjac(j,j) != 0.) { sum = 0.; diff --git a/unsupported/Eigen/src/NonLinearOptimization/qrfac.h b/unsupported/Eigen/src/NonLinearOptimization/qrfac.h deleted file mode 100644 index ff297293d..000000000 --- a/unsupported/Eigen/src/NonLinearOptimization/qrfac.h +++ /dev/null @@ -1,105 +0,0 @@ - -template <typename Scalar> -void ei_qrfac(int m, int n, Scalar *a, int - lda, int pivot, int *ipvt, Scalar *rdiag) -{ - /* System generated locals */ - int a_dim1, a_offset; - - /* Local variables */ - int i, j, k, jp1; - Scalar sum; - int kmax; - Scalar temp; - int minmn; - Scalar ajnorm; - - Matrix< Scalar, Dynamic, 1 > wa(n+1); - - /* Parameter adjustments */ - --rdiag; - a_dim1 = lda; - a_offset = 1 + a_dim1 * 1; - a -= a_offset; - --ipvt; - - /* Function Body */ - const Scalar epsmch = epsilon<Scalar>(); - - /* compute the initial column norms and initialize several arrays. */ - - for (j = 1; j <= n; ++j) { - rdiag[j] = Map< Matrix< Scalar, Dynamic, 1 > >(&a[j * a_dim1 + 1],m).blueNorm(); - wa[j] = rdiag[j]; - if (pivot) - ipvt[j] = j; - } - - /* reduce a to r with householder transformations. */ - - minmn = std::min(m,n); - for (j = 1; j <= minmn; ++j) { - if (! (pivot)) - goto L40; - - /* bring the column of largest norm into the pivot position. */ - - kmax = j; - for (k = j; k <= n; ++k) - if (rdiag[k] > rdiag[kmax]) - kmax = k; - if (kmax == j) - goto L40; - for (i = 1; i <= m; ++i) { - temp = a[i + j * a_dim1]; - a[i + j * a_dim1] = a[i + kmax * a_dim1]; - a[i + kmax * a_dim1] = temp; - /* L30: */ - } - rdiag[kmax] = rdiag[j]; - wa[kmax] = wa[j]; - k = ipvt[j]; - ipvt[j] = ipvt[kmax]; - ipvt[kmax] = k; -L40: - - /* compute the householder transformation to reduce the */ - /* j-th column of a to a multiple of the j-th unit vector. */ - - ajnorm = Map< Matrix< Scalar, Dynamic, 1 > >(&a[j + j * a_dim1],m-j+1).blueNorm(); - if (ajnorm == 0.) - goto L100; - if (a[j + j * a_dim1] < 0.) - ajnorm = -ajnorm; - for (i = j; i <= m; ++i) - a[i + j * a_dim1] /= ajnorm; - a[j + j * a_dim1] += 1.; - - /* apply the transformation to the remaining columns */ - /* and update the norms. */ - - jp1 = j + 1; - for (k = jp1; k <= n; ++k) { - sum = 0.; - for (i = j; i <= m; ++i) - sum += a[i + j * a_dim1] * a[i + k * a_dim1]; - temp = sum / a[j + j * a_dim1]; - for (i = j; i <= m; ++i) - a[i + k * a_dim1] -= temp * a[i + j * a_dim1]; - if (! (pivot) || rdiag[k] == 0.) - continue; - temp = a[j + k * a_dim1] / rdiag[k]; - /* Computing MAX */ - /* Computing 2nd power */ - rdiag[k] *= ei_sqrt((std::max(Scalar(0.), Scalar(1.)-ei_abs2(temp)))); - /* Computing 2nd power */ - if (Scalar(.05) * ei_abs2(rdiag[k] / wa[k]) > epsmch) - continue; - rdiag[k] = Map< Matrix< Scalar, Dynamic, 1 > >(&a[jp1 + k * a_dim1],m-j).blueNorm(); - wa[k] = rdiag[k]; - } -L100: - rdiag[j] = -ajnorm; - } -} - |