📄 minpack.cpp
字号:
goto L190; } i__1 = *n; for (j = 1; j <= i__1; ++j) {/* Computing MAX */ d__1 = diag[j], d__2 = wa2[j]; diag[j] = max(d__1,d__2);/* L180: */ }L190:/* beginning of the inner loop. */L200:/* determine the levenberg-marquardt parameter. */ lmpar_(n, &fjac[fjac_offset], ldfjac, &ipvt[1], &diag[1], &qtf[1], &delta, &par, &wa1[1], &wa2[1], &wa3[1], &wa4[1]);/* store the direction p and x + p. calculate the norm of p. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = -wa1[j]; wa2[j] = x[j] + wa1[j]; wa3[j] = diag[j] * wa1[j];/* L210: */ } pnorm = enorm_(n, &wa3[1]);/* 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[1], &wa4[1], &iflag); (*fcn)(m, n, &wa2[1], &wa4[1]); ++(*nfev); if (iflag < 0) { goto L300; } fnorm1 = enorm_(m, &wa4[1]);/* compute the scaled actual reduction. */ actred = -one; if (p1 * fnorm1 < fnorm) {/* Computing 2nd power */ d__1 = fnorm1 / fnorm; actred = one - d__1 * d__1; }/* compute the scaled predicted reduction and *//* the scaled directional derivative. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { wa3[j] = zero; l = ipvt[j]; temp = wa1[l]; i__2 = j; for (i = 1; i <= i__2; ++i) { wa3[i] += fjac[i + j * fjac_dim1] * temp;/* L220: */ }/* L230: */ } temp1 = enorm_(n, &wa3[1]) / fnorm; temp2 = sqrt(par) * pnorm / fnorm;/* Computing 2nd power */ d__1 = temp1;/* Computing 2nd power */ d__2 = temp2; prered = d__1 * d__1 + d__2 * d__2 / p5;/* Computing 2nd power */ d__1 = temp1;/* Computing 2nd power */ d__2 = temp2; dirder = -(d__1 * d__1 + d__2 * d__2);/* compute the ratio of the actual to the predicted *//* reduction. */ ratio = zero; if (prered != zero) { ratio = actred / prered; }/* update the step bound. */ if (ratio > p25) { goto L240; } if (actred >= zero) { temp = p5; } if (actred < zero) { temp = p5 * dirder / (dirder + p5 * actred); } if (p1 * fnorm1 >= fnorm || temp < p1) { temp = p1; }/* Computing MIN */ d__1 = delta, d__2 = pnorm / p1; delta = temp * min(d__1,d__2); par /= temp; goto L260;L240: if (par != zero && ratio < p75) { goto L250; } delta = pnorm / p5; par = p5 * par;L250:L260:/* test for successful iteration. */ if (ratio < p0001) { goto L290; }/* successful iteration. update x, fvec, and their norms. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { x[j] = wa2[j]; wa2[j] = diag[j] * x[j];/* L270: */ } i__1 = *m; for (i = 1; i <= i__1; ++i) { fvec[i] = wa4[i];/* L280: */ } xnorm = enorm_(n, &wa2[1]); fnorm = fnorm1; ++iter;L290:/* tests for convergence. */ if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one) { *info = 1; } if (delta <= *xtol * xnorm) { *info = 2; } if (abs(actred) <= *ftol && prered <= *ftol && p5 * ratio <= one && *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 && p5 * ratio <= one) { *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 < p0001) { 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[1], &fvec[1], &iflag); (*fcn)(m, n, &x[1], &fvec[1]); } return 0;} int lmpar_(long *n,double *r,long *ldr,long *ipvt,double *diag,double *qtb, double *delta,double * par,double *x,double *sdiag,double *wa1, double *wa2){ static double p1 = .1; static double p001 = .001; static double zero = 0.; /* System generated locals */ long r_dim1, r_offset, i__1, i__2; double d__1, d__2; /* Builtin functions */ /* Local variables */ static double parc, parl; static long iter; static double temp, paru; static long i, j, k, l; static double dwarf; static long nsing; static double gnorm, fp; static double dxnorm; static long jm1, jp1; static double sum; /* Parameter adjustments */ --wa2; --wa1; --sdiag; --x; --qtb; --diag; --ipvt; r_dim1 = *ldr; r_offset = r_dim1 + 1; r -= r_offset; /* Function Body *//* dwarf is the smallest positive magnitude. */ dwarf = dpmpar_(&c__3);/* compute and store in x the gauss-newton direction. if the *//* jacobian is rank-deficient, obtain a least squares solution. */ nsing = *n; i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = qtb[j]; if (r[j + j * r_dim1] == zero && nsing == *n) { nsing = j - 1; } if (nsing < *n) { wa1[j] = zero; }/* L10: */ } if (nsing < 1) { goto L50; } i__1 = nsing; for (k = 1; k <= i__1; ++k) { j = nsing - k + 1; wa1[j] /= r[j + j * r_dim1]; temp = wa1[j]; jm1 = j - 1; if (jm1 < 1) { goto L30; } i__2 = jm1; for (i = 1; i <= i__2; ++i) { wa1[i] -= r[i + j * r_dim1] * temp;/* L20: */ }L30:/* L40: */ ; }L50: i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; x[l] = wa1[j];/* L60: */ }/* initialize the iteration counter. *//* evaluate the function at the origin, and test *//* for acceptance of the gauss-newton direction. */ iter = 0; i__1 = *n; for (j = 1; j <= i__1; ++j) { wa2[j] = diag[j] * x[j];/* L70: */ } dxnorm = enorm_(n, &wa2[1]); fp = dxnorm - *delta; if (fp <= p1 * *delta) { goto L220; }/* if the jacobian is not rank deficient, the newton *//* step provides a lower bound, parl, for the zero of *//* the function. otherwise set this bound to zero. */ parl = zero; if (nsing < *n) { goto L120; } i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; wa1[j] = diag[l] * (wa2[l] / dxnorm);/* L80: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; jm1 = j - 1; if (jm1 < 1) { goto L100; } i__2 = jm1; for (i = 1; i <= i__2; ++i) { sum += r[i + j * r_dim1] * wa1[i];/* L90: */ }L100: wa1[j] = (wa1[j] - sum) / r[j + j * r_dim1];/* L110: */ } temp = enorm_(n, &wa1[1]); parl = fp / *delta / temp / temp;L120:/* calculate an upper bound, paru, for the zero of the function. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { sum = zero; i__2 = j; for (i = 1; i <= i__2; ++i) { sum += r[i + j * r_dim1] * qtb[i];/* L130: */ } l = ipvt[j]; wa1[j] = sum / diag[l];/* L140: */ } gnorm = enorm_(n, &wa1[1]); paru = gnorm / *delta; if (paru == zero) { paru = dwarf / min(*delta,p1); }/* if the input par lies outside of the interval (parl,paru), *//* set par to the closer endpoint. */ *par = max(*par,parl); *par = min(*par,paru); if (*par == zero) { *par = gnorm / dxnorm; }/* beginning of an iteration. */L150: ++iter;/* evaluate the function at the current value of par. */ if (*par == zero) {/* Computing MAX */ d__1 = dwarf, d__2 = p001 * paru; *par = max(d__1,d__2); } temp = sqrt(*par); i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] = temp * diag[j];/* L160: */ } qrsolv_(n, &r[r_offset], ldr, &ipvt[1], &wa1[1], &qtb[1], &x[1], &sdiag[1] , &wa2[1]); i__1 = *n; for (j = 1; j <= i__1; ++j) { wa2[j] = diag[j] * x[j];/* L170: */ } dxnorm = enorm_(n, &wa2[1]); temp = fp; fp = dxnorm - *delta;/* if the function is small enough, accept the current value *//* of par. also test for the exceptional cases where parl *//* is zero or the number of iterations has reached 10. */ if (abs(fp) <= p1 * *delta || parl == zero && fp <= temp && temp < zero || iter == 10) { goto L220; }/* compute the newton correction. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { l = ipvt[j]; wa1[j] = diag[l] * (wa2[l] / dxnorm);/* L180: */ } i__1 = *n; for (j = 1; j <= i__1; ++j) { wa1[j] /= sdiag[j]; temp = wa1[j]; jp1 = j + 1; if (*n < jp1) { goto L200; } i__2 = *n; for (i = jp1; i <= i__2; ++i) { wa1[i] -= r[i + j * r_dim1] * temp;/* L190: */ }L200:/* L210: */ ; } temp = enorm_(n, &wa1[1]); parc = fp / *delta / temp / temp;/* depending on the sign of the function, update parl or paru. */ if (fp > zero) { parl = max(parl,*par); } if (fp < zero) { paru = min(paru,*par); }/* compute an improved estimate for par. *//* Computing MAX */ d__1 = parl, d__2 = *par + parc; *par = max(d__1,d__2);/* end of an iteration. */ goto L150;L220:/* termination. */ if (iter == 0) { *par = zero; } return 0;} int qrfac_(long *m, long *n, double *a, long *lda, long *pivot, long *ipvt, long *lipvt, double *rdiag, double *acnorm, double *wa){ static double one = 1.; static double p05 = .05; static double zero = 0.; /* System generated locals */ long a_dim1, a_offset, i__1, i__2, i__3; double d__1, d__2, d__3; /* Builtin functions */ /* Local variables */ static long kmax; static double temp; static long i, j, k, minmn; static double epsmch; static double ajnorm; static long jp1; static double sum; /* Parameter adjustments */ --wa; --acnorm; --rdiag; --ipvt; a_dim1 = *lda; a_offset = a_dim1 + 1; a -= a_offset; /* Function Body *//* epsmch is the machine precision. */ epsmch = dpmpar_(&c__4);/* compute the initial column norms and initialize several arrays. */ i__1 = *n; for (j = 1; j <= i__1; ++j) { acnorm[j] = enorm_(m, &a[j * a_dim1 + 1]); rdiag[j] = acnorm[j]; wa[j] = rdiag[j]; if (*pivot) { ipvt[j] = j; }/* L10: */ }/* reduce a to r with householder transformations. */ minmn = min(*m,*n); i__1 = minmn; for (j = 1; j <= i__1; ++j) { if (! (*pivot)) { goto L40; }/* bring the column of largest norm into the pivot position. */ kmax = j; i__2 = *n; for (k = j; k <= i__2; ++k) { if (rdiag[k] > rdiag[kmax]) { kmax = k; }/* L20: */ } if (kmax == j) { goto L40; } i__2 = *m; for (i = 1; i <= i__2; ++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. */ i__2 = *m - j + 1; ajnorm = enorm_(&i__2, &a[j + j * a_dim1]); if (ajnorm == zero) { goto L100; } if (a[j + j * a_dim1] < zero) { ajnorm = -ajnorm; } i__2 = *m; for (i = j; i <= i__2; ++i) { a[i + j * a_dim1] /= ajnorm;/* L50: */ } a[j + j * a_dim1] += one;/* apply the transformation to the remaining columns *//* and update the norms. */ jp1 = j + 1; if (*n < jp1) { goto L100; } i__2 = *n; for (k = jp1; k <= i__2; ++k) { sum = zero; i__3 = *m; for (i = j; i <= i__3; ++i) { sum += a[i + j * a_dim1] * a[i + k * a_dim1];/* L60: */ } temp = sum / a[j + j * a_dim1]; i__3 = *m; for (i = j; i <= i__3; ++i) { a[i + k * a_dim1] -= temp * a[i + j * a_dim1];/* L70: */ } if (! (*pivot) || rdiag[k] == zero) { goto L80; } temp = a[j + k * a_dim1] / rdiag[k];/* Computing MAX *//* Computing 2nd power */ d__3 = temp; d__1 = zero, d__2 = one - d__3 * d__3; rdiag[k] *= sqrt((max(d__1,d__2)));/* Computing 2nd power */ d__1 = rdiag[k] / wa[k]; if (p05 * (d__1 * d__1) > epsmch) { goto L80; } i__3 = *m - j; rdiag[k] = enorm_(&i__3, &a[jp1 + k * a_dim1]); wa[k] = rdiag[k];L80:/* L90: */ ; }L100: rdiag[j] = -ajnorm;/* L110: */ } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -