⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lmdif.cpp

📁 L-M法的函数库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*       minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac *//*       fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod *//*     argonne national laboratory. minpack project. march 1980. *//*     burton s. garbow, kenneth e. hillstrom, jorge j. more *//*     ********** */    /* Parameter adjustments */    --wa4;    --wa3;    --wa2;    --wa1;    --qtf;    --ipvt;    fjac_dim1 = *ldfjac;    fjac_offset = fjac_dim1 + 1;    fjac -= fjac_offset;    --diag;    --fvec;    --x;    /* Function Body *//*     epsmch is the machine precision. */    epsmch = ::dpmpar_(&c__1);    *info = 0;    iflag = 0;    *nfev = 0;/*     check the input parameters for errors. */    if (*n <= 0 || *m < *n || *ldfjac < *m || *ftol < zero || *xtol < zero || 	    *gtol < zero || *maxfev <= 0 || *factor <= zero) {	goto L300;    }    if (*mode != 2) {	goto L20;    }    i__1 = *n;    for (j = 1; j <= i__1; ++j) {	if (diag[j] <= zero) {	    goto L300;	}/* L10: */    }L20:/*     evaluate the function at the starting point *//*     and calculate its norm. */    iflag = 1;    (*fcn)(m, n, &x[1], &fvec[1], &iflag);    *nfev = 1;    if (iflag < 0) {	goto L300;    }    fnorm = ::enorm_(m, &fvec[1]);/*     initialize levenberg-marquardt parameter and iteration counter. */    par = zero;    iter = 1;/*     beginning of the outer loop. */L30:/*        calculate the jacobian matrix. */    iflag = 2;    ::fdjac2_(fcn, m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag, 	    epsfcn, &wa4[1]);    *nfev += *n;    if (iflag < 0) {	goto L300;    }/*        if requested, call fcn to enable printing of iterates. */    if (*nprint <= 0) {	goto L40;    }    iflag = 0;    if ((iter - 1) % *nprint == 0) {	(fcn)(m, n, &x[1], &fvec[1], &iflag);    }    if (iflag < 0) {	goto L300;    }L40:/*        compute the qr factorization of the jacobian. */    ::qrfac_(m, n, &fjac[fjac_offset], ldfjac, &c__1, &ipvt[1], n, &wa1[1], &	    wa2[1], &wa3[1]);/*        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) {	goto L60;    }    i__1 = *n;    for (j = 1; j <= i__1; ++j) {	diag[j] = wa2[j];	if (wa2[j] == zero) {	    diag[j] = one;	}/* L50: */    }L60:/*        on the first iteration, calculate the norm of the scaled x *//*        and initialize the step bound delta. */    i__1 = *n;    for (j = 1; j <= i__1; ++j) {	wa3[j] = diag[j] * x[j];/* L70: */    }    xnorm = ::enorm_(n, &wa3[1]);    delta = *factor * xnorm;    if (delta == zero) {	delta = *factor;    }L80:/*        form (q transpose)*fvec and store the first n components in *//*        qtf. */    i__1 = *m;    for (i = 1; i <= i__1; ++i) {	wa4[i] = fvec[i];/* L90: */    }    i__1 = *n;    for (j = 1; j <= i__1; ++j) {	if (fjac[j + j * fjac_dim1] == zero) {	    goto L120;	}	sum = zero;	i__2 = *m;	for (i = j; i <= i__2; ++i) {	    sum += fjac[i + j * fjac_dim1] * wa4[i];/* L100: */	}	temp = -sum / fjac[j + j * fjac_dim1];	i__2 = *m;	for (i = j; i <= i__2; ++i) {	    wa4[i] += fjac[i + j * fjac_dim1] * temp;/* L110: */	}L120:	fjac[j + j * fjac_dim1] = wa1[j];	qtf[j] = wa4[j];/* L130: */    }/*        compute the norm of the scaled gradient. */    gnorm = zero;    if (fnorm == zero) {	goto L170;    }    i__1 = *n;    for (j = 1; j <= i__1; ++j) {	l = ipvt[j];	if (wa2[l] == zero) {	    goto L150;	}	sum = zero;	i__2 = j;	for (i = 1; i <= i__2; ++i) {	    sum += fjac[i + j * fjac_dim1] * (qtf[i] / fnorm);/* L140: */	}/* Computing MAX */	d__2 = gnorm, d__3 = (d__1 = sum / wa2[l], abs(d__1));	gnorm = xmax(d__2,d__3);L150:/* L160: */	;    }L170:/*        test for convergence of the gradient norm. */    if (gnorm <= *gtol) {	*info = 4;    }    if (*info != 0) {	goto L300;    }/*        rescale if necessary. */    if (*mode == 2) {	goto L190;    }    i__1 = *n;    for (j = 1; j <= i__1; ++j) {/* Computing MAX */	d__1 = diag[j], d__2 = wa2[j];	diag[j] = xmax(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 = xmin(delta,pnorm);    }/*           evaluate the function at x + p and calculate its norm. */    iflag = 1;    (*fcn)(m, n, &wa2[1], &wa4[1], &iflag);    ++(*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 * xmin(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);    }    return 0;/*     last card of subroutine lmdif. */} /* lmdif_ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -