📄 lmdif.c
字号:
if (*nprint > 0)
if ((iter - 1) % *nprint == 0) {
iflag = 0;
(*fcn)(m, n, x, fvec, &iflag);
if (iflag < 0) {
goto L300;
}
}
/* compute the qr factorization of the jacobian. */
qrfac_(m, n, fjac, ldfjac, &c__1, ipvt, n, wa1, wa2, wa3);
/* on the first iteration and if mode is 1, scale according */
/* to the norms of the columns of the initial jacobian. */
if (iter != 1) {
goto L80;
}
if (*mode != 2)
for (j = 0; j < *n; ++j) {
diag[j] = wa2[j];
if (wa2[j] == 0.) {
diag[j] = 1.;
}
}
/* on the first iteration, calculate the norm of the scaled x */
/* and initialize the step bound delta. */
for (j = 0; j < *n; ++j) {
wa3[j] = diag[j] * x[j];
}
xnorm = enorm_(n, wa3);
delta = *factor * xnorm;
if (delta == 0.) {
delta = *factor;
}
L80:
/* form (q transpose)*fvec and store the first n components in */
/* qtf. */
for (i = 0; i < *m; ++i) {
wa4[i] = fvec[i];
}
for (j = 0; j < *n; ++j) {
if (fjac[j + j * *ldfjac] == 0.) {
goto L120;
}
sum = 0.;
for (i = j; i < *m; ++i) {
sum += fjac[i + j * *ldfjac] * wa4[i];
}
temp = -sum / fjac[j + j * *ldfjac];
for (i = j; i < *m; ++i) {
wa4[i] += fjac[i + j * *ldfjac] * temp;
}
L120:
fjac[j + j * *ldfjac] = wa1[j];
qtf[j] = wa4[j];
}
/* compute the norm of the scaled gradient. */
gnorm = 0.;
if (fnorm != 0.)
for (j = 0; j < *n; ++j) {
l = ipvt[j] - 1;
if (wa2[l] == 0.) {
continue;
}
sum = 0.;
for (i = 0; i <= j; ++i) {
sum += fjac[i + j * *ldfjac] * (qtf[i] / fnorm);
}
gnorm = max(gnorm,abs(sum / wa2[l]));
}
/* test for convergence of the gradient norm. */
if (gnorm <= *gtol) {
*info = 4;
}
if (*info != 0) {
goto L300;
}
/* rescale if necessary. */
if (*mode != 2)
for (j = 0; j < *n; ++j) {
diag[j] = max(diag[j],wa2[j]);
}
/* beginning of the inner loop. */
L200:
/* determine the levenberg-marquardt parameter. */
lmpar_(n, fjac, ldfjac, ipvt, diag, qtf, &delta, &par, wa1, wa2, wa3, wa4);
/* store the direction p and x + p. calculate the norm of p. */
for (j = 0; j < *n; ++j) {
wa1[j] = -wa1[j];
wa2[j] = x[j] + wa1[j];
wa3[j] = diag[j] * wa1[j];
}
pnorm = enorm_(n, wa3);
/* on the first iteration, adjust the initial step bound. */
if (iter == 1) {
delta = min(delta,pnorm);
}
/* evaluate the function at x + p and calculate its norm. */
iflag = 1;
(*fcn)(m, n, wa2, wa4, &iflag);
++(*nfev);
if (iflag < 0) {
goto L300;
}
fnorm1 = enorm_(m, wa4);
/* compute the scaled actual reduction. */
actred = -1.;
if (.1 * fnorm1 < fnorm) {
actred = fnorm1 / fnorm;
actred = 1. - actred * actred;
}
/* compute the scaled predicted reduction and */
/* the scaled directional derivative. */
for (j = 0; j < *n; ++j) {
wa3[j] = 0.;
l = ipvt[j] - 1;
temp = wa1[l];
for (i = 0; i <= j; ++i) {
wa3[i] += fjac[i + j * *ldfjac] * temp;
}
}
temp1 = enorm_(n, wa3) / fnorm;
temp2 = sqrt(par) * pnorm / fnorm;
prered = temp1 * temp1 + temp2 * temp2 / .5;
dirder = -(temp1 * temp1 + temp2 * temp2);
/* compute the ratio of the actual to the predicted */
/* reduction. */
ratio = 0.;
if (prered != 0.) {
ratio = actred / prered;
}
/* update the step bound. */
if (ratio > .25) {
if (par == 0. || ratio >= .75) {
delta = pnorm / .5;
par *= .5;
}
goto L240;
}
if (actred >= 0.) {
temp = .5;
}
if (actred < 0.) {
temp = .5 * dirder / (dirder + .5 * actred);
}
if (.1 * fnorm1 >= fnorm || temp < .1) {
temp = .1;
}
delta = temp * min(delta,pnorm/.1);
par /= temp;
L240:
/* test for successful iteration. */
if (ratio < .0001) {
goto L290;
}
/* successful iteration. update x, fvec, and their norms. */
for (j = 0; j < *n; ++j) {
x[j] = wa2[j];
wa2[j] = diag[j] * x[j];
}
for (i = 0; i < *m; ++i) {
fvec[i] = wa4[i];
}
xnorm = enorm_(n, wa2);
fnorm = fnorm1;
errors[1] = fnorm;
++iter;
L290:
/* tests for convergence. */
if (abs(actred) <= *ftol && prered <= *ftol && .5 * ratio <= 1.) {
*info = 1;
}
if (delta <= *xtol * xnorm) {
*info = 2;
}
if (abs(actred) <= *ftol && prered <= *ftol && .5 * ratio <= 1. && *info == 2) {
*info = 3;
}
if (*info != 0) {
goto L300;
}
/* tests for termination and stringent tolerances. */
if (*nfev >= *maxfev) {
*info = 5;
}
if (abs(actred) <= epsmch && prered <= epsmch && .5 * ratio <= 1.) {
*info = 6;
}
if (delta <= epsmch * xnorm) {
*info = 7;
}
if (gnorm <= epsmch) {
*info = 8;
}
if (*info != 0) {
goto L300;
}
/* end of the inner loop. repeat if iteration unsuccessful. */
if (ratio < .0001) {
goto L200;
}
/* end of the outer loop. */
goto L30;
L300:
/* termination, either normal or user imposed. */
if (iflag < 0) {
*info = iflag;
}
iflag = 0;
if (*nprint > 0) {
(*fcn)(m, n, x, fvec, &iflag);
}
return;
} /* lmdif_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -