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

📄 lmdif.c

📁 InsightToolkit-1.4.0(有大量的优化算法程序)
💻 C
📖 第 1 页 / 共 2 页
字号:

    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 + -