5#ifndef EIGEN_NONLINEAROPTIMIZATION_LMPAR_H
6#define EIGEN_NONLINEAROPTIMIZATION_LMPAR_H
8#include "./InternalHeaderCheck.h"
14template <
typename Scalar>
15void lmpar(Matrix<Scalar, Dynamic, Dynamic> &r,
const VectorXi &ipvt,
const Matrix<Scalar, Dynamic, 1> &diag,
16 const Matrix<Scalar, Dynamic, 1> &qtb, Scalar delta, Scalar &par, Matrix<Scalar, Dynamic, 1> &x) {
19 typedef DenseIndex Index;
31 const Scalar dwarf = (std::numeric_limits<Scalar>::min)();
32 const Index n = r.cols();
33 eigen_assert(n == diag.size());
34 eigen_assert(n == qtb.size());
35 eigen_assert(n == x.size());
37 Matrix<Scalar, Dynamic, 1> wa1, wa2;
43 for (j = 0; j < n; ++j) {
44 if (r(j, j) == 0. && nsing == n - 1) nsing = j - 1;
45 if (nsing < n - 1) wa1[j] = 0.;
47 for (j = nsing; j >= 0; --j) {
50 for (i = 0; i < j; ++i) wa1[i] -= r(i, j) * temp;
53 for (j = 0; j < n; ++j) x[ipvt[j]] = wa1[j];
59 wa2 = diag.cwiseProduct(x);
60 dxnorm = wa2.blueNorm();
62 if (fp <= Scalar(0.1) * delta) {
72 for (j = 0; j < n; ++j) {
74 wa1[j] = diag[l] * (wa2[l] / dxnorm);
77 for (j = 0; j < n; ++j) {
79 for (i = 0; i < j; ++i) sum += r(i, j) * wa1[i];
80 wa1[j] = (wa1[j] - sum) / r(j, j);
82 temp = wa1.blueNorm();
83 parl = fp / delta / temp / temp;
87 for (j = 0; j < n; ++j) wa1[j] = r.col(j).head(j + 1).dot(qtb.head(j + 1)) / diag[ipvt[j]];
89 gnorm = wa1.stableNorm();
91 if (paru == 0.) paru = dwarf / (std::min)(delta, Scalar(0.1));
95 par = (std::max)(par, parl);
96 par = (std::min)(par, paru);
97 if (par == 0.) par = gnorm / dxnorm;
104 if (par == 0.) par = (std::max)(dwarf, Scalar(.001) * paru);
105 wa1 = sqrt(par) * diag;
107 Matrix<Scalar, Dynamic, 1> sdiag(n);
108 qrsolv<Scalar>(r, ipvt, wa1, qtb, x, sdiag);
110 wa2 = diag.cwiseProduct(x);
111 dxnorm = wa2.blueNorm();
118 if (abs(fp) <= Scalar(0.1) * delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10)
break;
121 for (j = 0; j < n; ++j) {
123 wa1[j] = diag[l] * (wa2[l] / dxnorm);
125 for (j = 0; j < n; ++j) {
128 for (i = j + 1; i < n; ++i) wa1[i] -= r(i, j) * temp;
130 temp = wa1.blueNorm();
131 parc = fp / delta / temp / temp;
134 if (fp > 0.) parl = (std::max)(parl, par);
135 if (fp < 0.) paru = (std::min)(paru, par);
139 par = (std::max)(parl, par + parc);
145 if (iter == 0) par = 0.;
149template <
typename Scalar>
150void lmpar2(
const ColPivHouseholderQR<Matrix<Scalar, Dynamic, Dynamic> > &qr,
const Matrix<Scalar, Dynamic, 1> &diag,
151 const Matrix<Scalar, Dynamic, 1> &qtb, Scalar delta, Scalar &par, Matrix<Scalar, Dynamic, 1> &x)
156 typedef DenseIndex Index;
168 const Scalar dwarf = (std::numeric_limits<Scalar>::min)();
169 const Index n = qr.matrixQR().cols();
170 eigen_assert(n == diag.size());
171 eigen_assert(n == qtb.size());
173 Matrix<Scalar, Dynamic, 1> wa1, wa2;
178 const Index rank = qr.rank();
180 wa1.tail(n - rank).setZero();
181 qr.matrixQR().topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(wa1.head(rank));
183 x = qr.colsPermutation() * wa1;
189 wa2 = diag.cwiseProduct(x);
190 dxnorm = wa2.blueNorm();
192 if (fp <= Scalar(0.1) * delta) {
202 wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2) / dxnorm;
203 qr.matrixQR().topLeftCorner(n, n).transpose().template triangularView<Lower>().solveInPlace(wa1);
204 temp = wa1.blueNorm();
205 parl = fp / delta / temp / temp;
209 for (j = 0; j < n; ++j)
210 wa1[j] = qr.matrixQR().col(j).head(j + 1).dot(qtb.head(j + 1)) / diag[qr.colsPermutation().indices()(j)];
212 gnorm = wa1.stableNorm();
213 paru = gnorm / delta;
214 if (paru == 0.) paru = dwarf / (std::min)(delta, Scalar(0.1));
218 par = (std::max)(par, parl);
219 par = (std::min)(par, paru);
220 if (par == 0.) par = gnorm / dxnorm;
223 Matrix<Scalar, Dynamic, Dynamic> s = qr.matrixQR();
228 if (par == 0.) par = (std::max)(dwarf, Scalar(.001) * paru);
229 wa1 = sqrt(par) * diag;
231 Matrix<Scalar, Dynamic, 1> sdiag(n);
232 qrsolv<Scalar>(s, qr.colsPermutation().indices(), wa1, qtb, x, sdiag);
234 wa2 = diag.cwiseProduct(x);
235 dxnorm = wa2.blueNorm();
242 if (abs(fp) <= Scalar(0.1) * delta || (parl == 0. && fp <= temp && temp < 0.) || iter == 10)
break;
245 wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2 / dxnorm);
248 for (j = 0; j < n; ++j) {
251 for (Index i = j + 1; i < n; ++i) wa1[i] -= s(i, j) * temp;
253 temp = wa1.blueNorm();
254 parc = fp / delta / temp / temp;
257 if (fp > 0.) parl = (std::max)(parl, par);
258 if (fp < 0.) paru = (std::min)(paru, par);
261 par = (std::max)(parl, par + parc);
263 if (iter == 0) par = 0.;
Matrix< int, Dynamic, 1 > VectorXi
Namespace containing all symbols from the Eigen library.