📄 minpack2-linmin.c
字号:
if (*stp == *stpmin && (*f > ftest || *g >= gtest)) { s_copy(task, "WARNING: STP = STPMIN", task_len, (ftnlen)21); }/* Test for convergence. */ if (*f <= ftest && ABS(*g) <= *gtol * (-ginit)) { s_copy(task, "CONVERGENCE", task_len, (ftnlen)11); }/* Test for termination. */ if (s_cmp(task, "WARN", (ftnlen)4, (ftnlen)4) == 0 || s_cmp(task, "CONV", (ftnlen)4, (ftnlen)4) == 0) { goto L10; }/* A modified function is used to predict the step during the *//* first stage if a lower function value has been obtained but *//* the decrease is not sufficient. */ if (stage == 1 && *f <= fx && *f > ftest) {/* Define the modified function and derivative values. */ fm = *f - *stp * gtest; fxm = fx - stx * gtest; fym = fy - sty * gtest; gm = *g - gtest; gxm = gx - gtest; gym = gy - gtest;/* Call dcstep to update stx, sty, and to compute the new step. */ dcstep(&stx, &fxm, &gxm, &sty, &fym, &gym, stp, &fm, &gm, &brackt, & stmin, &stmax);/* Reset the function and derivative values for f. */ fx = fxm + stx * gtest; fy = fym + sty * gtest; gx = gxm + gtest; gy = gym + gtest; } else {/* Call dcstep to update stx, sty, and to compute the new step. */ dcstep(&stx, &fx, &gx, &sty, &fy, &gy, stp, f, g, &brackt, &stmin, & stmax); }/* Decide if a bisection step is needed. */ if (brackt) { if ((d__1 = sty - stx, ABS(d__1)) >= width1 * .66) { *stp = stx + (sty - stx) * .5; } width1 = width; width = (d__1 = sty - stx, ABS(d__1)); }/* Set the minimum and maximum steps allowed for stp. */ if (brackt) { stmin = MIN(stx,sty); stmax = MAX(stx,sty); } else { stmin = *stp + (*stp - stx) * 1.1; stmax = *stp + (*stp - stx) * 4.; }/* Force the step to be within the bounds stpmax and stpmin. */ *stp = MAX(*stp,*stpmin); *stp = MIN(*stp,*stpmax);/* If further progress is not possible, let stp be the best *//* point obtained during the search. */ if ((brackt && (*stp <= stmin || *stp >= stmax)) || (brackt && stmax - stmin <= *xtol * stmax)) { *stp = stx; }/* Obtain another function and derivative. */ s_copy(task, "FG", task_len, (ftnlen)2);L10:/* Save local variables. */ if (brackt) { isave[1] = 1; } else { isave[1] = 0; } isave[2] = stage; dsave[1] = ginit; dsave[2] = gtest; dsave[3] = gx; dsave[4] = gy; dsave[5] = finit; dsave[6] = fx; dsave[7] = fy; dsave[8] = stx; dsave[9] = sty; dsave[10] = stmin; dsave[11] = stmax; dsave[12] = width; dsave[13] = width1; return 0;} /* dcsrch *//* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc *//* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc *//* Subroutine */ int dcstep(doublereal *stx, doublereal *fx, doublereal *dx, doublereal *sty, doublereal *fy, doublereal *dy, doublereal *stp, doublereal *fp, doublereal *dp, logical *brackt, doublereal *stpmin, doublereal *stpmax){ /* System generated locals */ doublereal d__1, d__2, d__3; /* Local variables */ doublereal sgnd, stpc, stpf, stpq, p, q, gamma, r__, s, theta;/* ********** *//* Subroutine dcstep *//* This subroutine computes a safeguarded step for a search *//* procedure and updates an interval that contains a step that *//* satisfies a sufficient decrease and a curvature condition. *//* The parameter stx contains the step with the least function *//* value. If brackt is set to .true. then a minimizer has *//* been bracketed in an interval with endpoints stx and sty. *//* The parameter stp contains the current step. *//* The subroutine assumes that if brackt is set to .true. then *//* MIN(stx,sty) < stp < MAX(stx,sty), *//* and that the derivative at stx is negative in the direction *//* of the step. *//* The subroutine statement is *//* subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, *//* stpmin,stpmax) *//* where *//* stx is a double precision variable. *//* On entry stx is the best step obtained so far and is an *//* endpoint of the interval that contains the minimizer. *//* On exit stx is the updated best step. *//* fx is a double precision variable. *//* On entry fx is the function at stx. *//* On exit fx is the function at stx. *//* dx is a double precision variable. *//* On entry dx is the derivative of the function at *//* stx. The derivative must be negative in the direction of *//* the step, that is, dx and stp - stx must have opposite *//* signs. *//* On exit dx is the derivative of the function at stx. *//* sty is a double precision variable. *//* On entry sty is the second endpoint of the interval that *//* contains the minimizer. *//* On exit sty is the updated endpoint of the interval that *//* contains the minimizer. *//* fy is a double precision variable. *//* On entry fy is the function at sty. *//* On exit fy is the function at sty. *//* dy is a double precision variable. *//* On entry dy is the derivative of the function at sty. *//* On exit dy is the derivative of the function at the exit sty. *//* stp is a double precision variable. *//* On entry stp is the current step. If brackt is set to .true. *//* then on input stp must be between stx and sty. *//* On exit stp is a new trial step. *//* fp is a double precision variable. *//* On entry fp is the function at stp *//* On exit fp is unchanged. *//* dp is a double precision variable. *//* On entry dp is the the derivative of the function at stp. *//* On exit dp is unchanged. *//* brackt is an logical variable. *//* On entry brackt specifies if a minimizer has been bracketed. *//* Initially brackt must be set to .false. *//* On exit brackt specifies if a minimizer has been bracketed. *//* When a minimizer is bracketed brackt is set to .true. *//* stpmin is a double precision variable. *//* On entry stpmin is a lower bound for the step. *//* On exit stpmin is unchanged. *//* stpmax is a double precision variable. *//* On entry stpmax is an upper bound for the step. *//* On exit stpmax is unchanged. *//* MINPACK-1 Project. June 1983 *//* Argonne National Laboratory. *//* Jorge J. More' and David J. Thuente. *//* MINPACK-2 Project. November 1993. *//* Argonne National Laboratory and University of Minnesota. *//* Brett M. Averick and Jorge J. More'. *//* ********** */ sgnd = *dp * (*dx / ABS(*dx));/* First case: A higher function value. The minimum is bracketed. *//* If the cubic step is closer to stx than the quadratic step, the *//* cubic step is taken, otherwise the average of the cubic and *//* quadratic steps is taken. */ if (*fp > *fx) { theta = (*fx - *fp) * 3. / (*stp - *stx) + *dx + *dp;/* Computing MAX */ d__1 = ABS(theta), d__2 = ABS(*dx), d__1 = MAX(d__1,d__2), d__2 = ABS( *dp); s = MAX(d__1,d__2);/* Computing 2nd power */ d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dx / s * (*dp / s)); if (*stp < *stx) { gamma = -gamma; } p = gamma - *dx + theta; q = gamma - *dx + gamma + *dp; r__ = p / q; stpc = *stx + r__ * (*stp - *stx); stpq = *stx + *dx / ((*fx - *fp) / (*stp - *stx) + *dx) / 2. * (*stp - *stx); if ((d__1 = stpc - *stx, ABS(d__1)) < (d__2 = stpq - *stx, ABS(d__2))) { stpf = stpc; } else { stpf = stpc + (stpq - stpc) / 2.; } *brackt = TRUE_;/* Second case: A lower function value and derivatives of opposite *//* sign. The minimum is bracketed. If the cubic step is farther from *//* stp than the secant step, the cubic step is taken, otherwise the *//* secant step is taken. */ } else if (sgnd < 0.) { theta = (*fx - *fp) * 3. / (*stp - *stx) + *dx + *dp;/* Computing MAX */ d__1 = ABS(theta), d__2 = ABS(*dx), d__1 = MAX(d__1,d__2), d__2 = ABS( *dp); s = MAX(d__1,d__2);/* Computing 2nd power */ d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dx / s * (*dp / s)); if (*stp > *stx) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma - *dp + gamma + *dx; r__ = p / q; stpc = *stp + r__ * (*stx - *stp); stpq = *stp + *dp / (*dp - *dx) * (*stx - *stp); if ((d__1 = stpc - *stp, ABS(d__1)) > (d__2 = stpq - *stp, ABS(d__2))) { stpf = stpc; } else { stpf = stpq; } *brackt = TRUE_;/* Third case: A lower function value, derivatives of the same sign, *//* and the magnitude of the derivative decreases. */ } else if (ABS(*dp) < ABS(*dx)) {/* The cubic step is computed only if the cubic tends to infinity *//* in the direction of the step or if the minimum of the cubic *//* is beyond stp. Otherwise the cubic step is defined to be the *//* secant step. */ theta = (*fx - *fp) * 3. / (*stp - *stx) + *dx + *dp;/* Computing MAX */ d__1 = ABS(theta), d__2 = ABS(*dx), d__1 = MAX(d__1,d__2), d__2 = ABS( *dp); s = MAX(d__1,d__2);/* The case gamma = 0 only arises if the cubic does not tend *//* to infinity in the direction of the step. *//* Computing MAX *//* Computing 2nd power */ d__3 = theta / s; d__1 = 0., d__2 = d__3 * d__3 - *dx / s * (*dp / s); gamma = s * sqrt((MAX(d__1,d__2))); if (*stp > *stx) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma + (*dx - *dp) + gamma; r__ = p / q; if (r__ < 0. && gamma != 0.) { stpc = *stp + r__ * (*stx - *stp); } else if (*stp > *stx) { stpc = *stpmax; } else { stpc = *stpmin; } stpq = *stp + *dp / (*dp - *dx) * (*stx - *stp); if (*brackt) {/* A minimizer has been bracketed. If the cubic step is *//* closer to stp than the secant step, the cubic step is *//* taken, otherwise the secant step is taken. */ if ((d__1 = stpc - *stp, ABS(d__1)) < (d__2 = stpq - *stp, ABS( d__2))) { stpf = stpc; } else { stpf = stpq; } if (*stp > *stx) {/* Computing MIN */ d__1 = *stp + (*sty - *stp) * .66; stpf = MIN(d__1,stpf); } else {/* Computing MAX */ d__1 = *stp + (*sty - *stp) * .66; stpf = MAX(d__1,stpf); } } else {/* A minimizer has not been bracketed. If the cubic step is *//* farther from stp than the secant step, the cubic step is *//* taken, otherwise the secant step is taken. */ if ((d__1 = stpc - *stp, ABS(d__1)) > (d__2 = stpq - *stp, ABS( d__2))) { stpf = stpc; } else { stpf = stpq; } stpf = MIN(*stpmax,stpf); stpf = MAX(*stpmin,stpf); }/* Fourth case: A lower function value, derivatives of the same sign, *//* and the magnitude of the derivative does not decrease. If the *//* minimum is not bracketed, the step is either stpmin or stpmax, *//* otherwise the cubic step is taken. */ } else { if (*brackt) { theta = (*fp - *fy) * 3. / (*sty - *stp) + *dy + *dp;/* Computing MAX */ d__1 = ABS(theta), d__2 = ABS(*dy), d__1 = MAX(d__1,d__2), d__2 = ABS(*dp); s = MAX(d__1,d__2);/* Computing 2nd power */ d__1 = theta / s; gamma = s * sqrt(d__1 * d__1 - *dy / s * (*dp / s)); if (*stp > *sty) { gamma = -gamma; } p = gamma - *dp + theta; q = gamma - *dp + gamma + *dy; r__ = p / q; stpc = *stp + r__ * (*sty - *stp); stpf = stpc; } else if (*stp > *stx) { stpf = *stpmax; } else { stpf = *stpmin; } }/* Update the interval which contains a minimizer. */ if (*fp > *fx) { *sty = *stp; *fy = *fp; *dy = *dp; } else { if (sgnd < 0.) { *sty = *stx; *fy = *fx; *dy = *dx; } *stx = *stp; *fx = *fp; *dx = *dp; }/* Compute the new step. */ *stp = stpf; return 0;} /* dcstep */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -