lbfgs.c
来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 1,199 行 · 第 1/3 页
C
1,199 行
/* THE VARIABLES STX, FX, DGX CONTAIN THE VALUES OF THE STEP, */
/* FUNCTION, AND DIRECTIONAL DERIVATIVE AT THE BEST STEP. */
/* THE VARIABLES STY, FY, DGY CONTAIN THE VALUE OF THE STEP, */
/* FUNCTION, AND DERIVATIVE AT THE OTHER ENDPOINT OF */
/* THE INTERVAL OF UNCERTAINTY. */
/* THE VARIABLES STP, F, DG CONTAIN THE VALUES OF THE STEP, */
/* FUNCTION, AND DERIVATIVE AT THE CURRENT STEP. */
stx = 0.;
fx = finit;
dgx = dginit;
sty = 0.;
fy = finit;
dgy = dginit;
/* START OF ITERATION. */
L30:
/* SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND */
/* TO THE PRESENT INTERVAL OF UNCERTAINTY. */
if (brackt) {
stmin = min(stx,sty);
stmax = max(stx,sty);
} else {
stmin = stx;
stmax = *stp + xtrapf * (*stp - stx);
}
/* FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. */
*stp = max(*stp,lb3_1.stpmin);
*stp = min(*stp,lb3_1.stpmax);
/* IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET */
/* STP BE THE LOWEST POINT OBTAINED SO FAR. */
if ( (brackt && (*stp <= stmin || *stp >= stmax) ) || *nfev >= *maxfev - 1
|| infoc == 0 || ( brackt && stmax - stmin <= *xtol * stmax) ) {
*stp = stx;
}
/* EVALUATE THE FUNCTION AND GRADIENT AT STP */
/* AND COMPUTE THE DIRECTIONAL DERIVATIVE. */
/* We return to main program to obtain F and G. */
for (j = 0; j < *n; ++j) {
x[j] = wa[j] + *stp * s[j];
}
*info = -1;
return;
L45:
*info = 0;
++(*nfev);
dg = 0.;
for (j = 0; j < *n; ++j) {
dg += g[j] * s[j];
}
ftest1 = finit + *stp * dgtest;
/* TEST FOR CONVERGENCE. */
if ( (brackt && (*stp <= stmin || *stp >= stmax) ) || infoc == 0) {
*info = 6;
}
if (*stp == lb3_1.stpmax && *f <= ftest1 && dg <= dgtest) {
*info = 5;
}
if (*stp == lb3_1.stpmin && (*f > ftest1 || dg >= dgtest)) {
*info = 4;
}
if (*nfev >= *maxfev) {
*info = 3;
}
if (brackt && stmax - stmin <= *xtol * stmax) {
*info = 2;
}
if (*f <= ftest1 && abs(dg) <= lb3_1.gtol * (-dginit)) {
*info = 1;
}
/* CHECK FOR TERMINATION. */
if (*info != 0) {
return;
}
/* IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED */
/* FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. */
if (stage1 && *f <= ftest1 && dg >= min(*ftol,lb3_1.gtol) * dginit) {
stage1 = FALSE_;
}
/* A MODIFIED FUNCTION IS USED TO PREDICT THE STEP ONLY IF */
/* WE HAVE NOT OBTAINED A STEP FOR WHICH THE MODIFIED */
/* FUNCTION HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE */
/* DERIVATIVE, AND IF A LOWER FUNCTION VALUE HAS BEEN */
/* OBTAINED BUT THE DECREASE IS NOT SUFFICIENT. */
if (stage1 && *f <= fx && *f > ftest1) {
/* DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. */
fm = *f - *stp * dgtest;
fxm = fx - stx * dgtest;
fym = fy - sty * dgtest;
dgm = dg - dgtest;
dgxm = dgx - dgtest;
dgym = dgy - dgtest;
/* CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY */
/* AND TO COMPUTE THE NEW STEP. */
mcstep_(&stx, &fxm, &dgxm, &sty, &fym, &dgym, stp, &fm, &dgm, &brackt, &stmin, &stmax, &infoc);
/* RESET THE FUNCTION AND GRADIENT VALUES FOR F. */
fx = fxm + stx * dgtest;
fy = fym + sty * dgtest;
dgx = dgxm + dgtest;
dgy = dgym + dgtest;
} else {
/* CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY */
/* AND TO COMPUTE THE NEW STEP. */
mcstep_(&stx, &fx, &dgx, &sty, &fy, &dgy, stp, f, &dg, &brackt, &stmin, &stmax, &infoc);
}
/* FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE */
/* INTERVAL OF UNCERTAINTY. */
if (brackt) {
if (abs(sty - stx) >= .66 * width1) {
*stp = stx + .5 * (sty - stx);
}
width1 = width;
width = abs(sty - stx);
}
/* END OF ITERATION. */
goto L30;
/* LAST LINE OF SUBROUTINE MCSRCH. */
} /* mcsrch_ */
/* Subroutine */ void mcstep_(stx, fx, dx, sty, fy, dy, stp, fp, dp, brackt, stpmin, stpmax, info)
doublereal *stx, *fx, *dx, *sty, *fy, *dy, *stp, *fp, *dp;
logical *brackt;
doublereal *stpmin, *stpmax;
integer *info;
{
/* System generated locals */
doublereal d__1;
/* Local variables */
static doublereal sgnd, stpc, stpf, stpq, p, q, gamma, r, s, theta;
static logical bound;
/* SUBROUTINE MCSTEP */
/* THE PURPOSE OF MCSTEP IS TO COMPUTE A SAFEGUARDED STEP FOR */
/* A LINESEARCH AND TO UPDATE AN INTERVAL OF UNCERTAINTY FOR */
/* A MINIMIZER OF THE FUNCTION. */
/* THE PARAMETER STX CONTAINS THE STEP WITH THE LEAST FUNCTION */
/* VALUE. THE PARAMETER STP CONTAINS THE CURRENT STEP. IT IS */
/* ASSUMED THAT THE DERIVATIVE AT STX IS NEGATIVE IN THE */
/* DIRECTION OF THE STEP. IF BRACKT IS SET TRUE THEN A */
/* MINIMIZER HAS BEEN BRACKETED IN AN INTERVAL OF UNCERTAINTY */
/* WITH ENDPOINTS STX AND STY. */
/* THE SUBROUTINE STATEMENT IS */
/* SUBROUTINE MCSTEP(STX,FX,DX,STY,FY,DY,STP,FP,DP,BRACKT, */
/* STPMIN,STPMAX,INFO) */
/* WHERE */
/* STX, FX, AND DX ARE VARIABLES WHICH SPECIFY THE STEP, */
/* THE FUNCTION, AND THE DERIVATIVE AT THE BEST STEP OBTAINED */
/* SO FAR. THE DERIVATIVE MUST BE NEGATIVE IN THE DIRECTION */
/* OF THE STEP, THAT IS, DX AND STP-STX MUST HAVE OPPOSITE */
/* SIGNS. ON OUTPUT THESE PARAMETERS ARE UPDATED APPROPRIATELY. */
/* STY, FY, AND DY ARE VARIABLES WHICH SPECIFY THE STEP, */
/* THE FUNCTION, AND THE DERIVATIVE AT THE OTHER ENDPOINT OF */
/* THE INTERVAL OF UNCERTAINTY. ON OUTPUT THESE PARAMETERS ARE */
/* UPDATED APPROPRIATELY. */
/* STP, FP, AND DP ARE VARIABLES WHICH SPECIFY THE STEP, */
/* THE FUNCTION, AND THE DERIVATIVE AT THE CURRENT STEP. */
/* IF BRACKT IS SET TRUE THEN ON INPUT STP MUST BE */
/* BETWEEN STX AND STY. ON OUTPUT STP IS SET TO THE NEW STEP. */
/* BRACKT IS A LOGICAL VARIABLE WHICH SPECIFIES IF A MINIMIZER */
/* HAS BEEN BRACKETED. IF THE MINIMIZER HAS NOT BEEN BRACKETED */
/* THEN ON INPUT BRACKT MUST BE SET FALSE. IF THE MINIMIZER */
/* IS BRACKETED THEN ON OUTPUT BRACKT IS SET TRUE. */
/* STPMIN AND STPMAX ARE INPUT VARIABLES WHICH SPECIFY LOWER */
/* AND UPPER BOUNDS FOR THE STEP. */
/* INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: */
/* IF INFO = 1,2,3,4,5, THEN THE STEP HAS BEEN COMPUTED */
/* ACCORDING TO ONE OF THE FIVE CASES BELOW. OTHERWISE */
/* INFO = 0, AND THIS INDICATES IMPROPER INPUT PARAMETERS. */
/* SUBPROGRAMS CALLED */
/* FORTRAN-SUPPLIED ... ABS,MAX,MIN,SQRT */
/* ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 */
/* JORGE J. MORE', DAVID J. THUENTE */
*info = 0;
/* CHECK THE INPUT PARAMETERS FOR ERRORS. */
if ( ( *brackt && ( *stp <= min(*stx,*sty) || *stp >= max(*stx,*sty) ) )
|| *dx * (*stp - *stx) >= 0. || *stpmax < *stpmin) {
return;
}
/* DETERMINE IF THE DERIVATIVES HAVE OPPOSITE SIGN. */
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, */
/* ELSE THE AVERAGE OF THE CUBIC AND QUADRATIC STEPS IS TAKEN. */
if (*fp > *fx) {
*info = 1;
bound = TRUE_;
theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp;
s = max(max(abs(theta),abs(*dx)),abs(*dp));
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 (abs(stpc - *stx) < abs(stpq - *stx)) {
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 CLOSER TO STX THAN THE QUADRATIC (SECANT) STEP, */
/* THE CUBIC STEP IS TAKEN, ELSE THE QUADRATIC STEP IS TAKEN. */
} else if (sgnd < 0.) {
*info = 2;
bound = FALSE_;
theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp;
s = max(max(abs(theta),abs(*dx)),abs(*dp));
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 (abs(stpc - *stp) > abs(stpq - *stp)) {
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. */
/* THE CUBIC STEP IS ONLY USED 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 */
/* EITHER STPMIN OR STPMAX. THE QUADRATIC (SECANT) STEP IS ALSO */
/* COMPUTED AND IF THE MINIMUM IS BRACKETED THEN THE THE STEP */
/* CLOSEST TO STX IS TAKEN, ELSE THE STEP FARTHEST AWAY IS TAKEN. */
} else if (abs(*dp) < abs(*dx)) {
*info = 3;
bound = TRUE_;
theta = (*fx - *fp) * 3 / (*stp - *stx) + *dx + *dp;
s = max(max(abs(theta),abs(*dx)),abs(*dp));
/* THE CASE GAMMA = 0 ONLY ARISES IF THE CUBIC DOES NOT TEND */
/* TO INFINITY IN THE DIRECTION OF THE STEP. */
d__1 = theta / s;
d__1 = d__1 * d__1 - *dx / s * (*dp / s);
gamma = s * sqrt((max(0.,d__1)));
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) {
if (abs(*stp - stpc) < abs(*stp - stpq)) {
stpf = stpc;
} else {
stpf = stpq;
}
} else {
if (abs(*stp - stpc) > abs(*stp - stpq)) {
stpf = stpc;
} else {
stpf = stpq;
}
}
/* 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, ELSE THE CUBIC STEP IS TAKEN. */
} else {
*info = 4;
bound = FALSE_;
if (*brackt) {
theta = (*fp - *fy) * 3 / (*sty - *stp) + *dy + *dp;
s = max(max(abs(theta),abs(*dy)),abs(*dp));
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 OF UNCERTAINTY. THIS UPDATE DOES NOT */
/* DEPEND ON THE NEW STEP OR THE CASE ANALYSIS ABOVE. */
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 AND SAFEGUARD IT. */
stpf = min(*stpmax,stpf);
stpf = max(*stpmin,stpf);
*stp = stpf;
if (*brackt && bound) {
if (*sty > *stx) {
d__1 = *stx + (*sty - *stx) * .66f;
*stp = min(d__1,*stp);
} else {
d__1 = *stx + (*sty - *stx) * .66f;
*stp = max(d__1,*stp);
}
}
} /* mcstep_ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?