lbfgs.c
来自「InsightToolkit-1.4.0(有大量的优化算法程序)」· C语言 代码 · 共 1,199 行 · 第 1/3 页
C
1,199 行
if (cp == -1) {
cp = *m - 1;
}
sq = ddot_(n, &w[ispt + cp * *n], &c__1, w, &c__1);
inmc = *n + *m + cp;
iycn = iypt + cp * *n;
w[inmc] = w[*n + cp] * sq;
d__1 = -w[inmc];
daxpy_(n, &d__1, &w[iycn], &c__1, w, &c__1);
}
for (i = 0; i < *n; ++i) {
w[i] *= diag[i];
}
for (i = 0; i < bound; ++i) {
yr = ddot_(n, &w[iypt + cp * *n], &c__1, w, &c__1);
beta = w[*n + cp] * yr;
inmc = *n + *m + cp;
beta = w[inmc] - beta;
iscn = ispt + cp * *n;
daxpy_(n, &beta, &w[iscn], &c__1, w, &c__1);
++cp;
if (cp == *m) {
cp = 0;
}
}
/* STORE THE NEW SEARCH DIRECTION */
/* ------------------------------ */
for (i = 0; i < *n; ++i) {
w[ispt + point * *n + i] = w[i];
}
/* OBTAIN THE ONE-DIMENSIONAL MINIMIZER OF THE FUNCTION */
/* BY USING THE LINE SEARCH ROUTINE MCSRCH */
/* ---------------------------------------------------- */
L165:
nfev = 0;
/* awf changed initial step from ONE to be parametrized. */
stp = lb3_1.stpawf;
if (iter == 1) {
stp = stp1;
}
for (i = 0; i < *n; ++i) {
w[i] = g[i];
}
L172:
mcsrch_(n, x, f, g, &w[ispt + point * *n], &stp, &ftol, xtol, &maxfev, &info, &nfev, diag);
if (info == -1) {
*iflag = 1;
/* Return, in order to get another sample of F and G. */
/* Next call comes right back here. */
return;
}
if (info != 1) {
goto L190;
}
nfun += nfev;
/* COMPUTE THE NEW STEP AND GRADIENT CHANGE */
/* ----------------------------------------- */
npt = point * *n;
for (i = 0; i < *n; ++i) {
w[ispt + npt + i] *= stp;
w[iypt + npt + i] = g[i] - w[i];
}
++point;
if (point == *m) {
point = 0;
}
/* TERMINATION TEST */
/* ---------------- */
gnorm = sqrt(ddot_(n, g, &c__1, g, &c__1));
xnorm = sqrt(ddot_(n, x, &c__1, x, &c__1));
xnorm = max(1.,xnorm);
if (gnorm / xnorm <= *eps) {
finish = TRUE_;
}
if (iprint[0] >= 0) {
lb1_(iprint, &iter, &nfun, &gnorm, n, m, x, f, g, &stp, &finish);
}
if (finish) {
*iflag = 0;
return;
}
goto L80;
/* ------------------------------------------------------------ */
/* END OF MAIN ITERATION LOOP. ERROR EXITS. */
/* ------------------------------------------------------------ */
L190:
*iflag = -1;
if (lb3_1.lp > 0) {
lbptf_("IFLAG= -1. LINE SEARCH FAILED.");
lbptf_(" SEE DOCUMENTATION OF ROUTINE MCSRCH");
lbp1d_(" ERROR RETURN OF LINE SEARCH: INFO=%d", &info);
lbptf_(" POSSIBLE CAUSES: FUNCTION OR GRADIENT ARE ");
lbptf_(" INCORRECT OR INCORRECT TOLERANCES");
}
return;
L195:
*iflag = -2;
if (lb3_1.lp > 0) {
lbp1d_("IFLAG=-2, THE %d-TH DIAGONAL ELEMENT OF THE", &i);
lbptf_("INVERSE HESSIAN APPROXIMATION IS NOT POSITIVE");
}
return;
L196:
*iflag = -3;
if (lb3_1.lp > 0) {
lbptf_("IFLAG= -3, IMPROPER INPUT PARAMETERS.");
lbptf_(" (N OR M ARE NOT POSITIVE)");
}
return;
} /* lbfgs_ */
/* LAST LINE OF SUBROUTINE LBFGS */
/* SUBROUTINE LB1(IPRINT,ITER,NFUN,GNORM,N,M,X,F,G,STP,FINISH) */
/* ** moved to c file */
/* ---------------------------------------------------------- */
/* These routines removed for insertion into TargetJr netlib */
/* awf subroutine daxpy(n,da,dx,incx,dy,incy) */
/* awf c */
/* awf c constant times a vector plus a vector. */
/* awf c uses unrolled loops for increments equal to one. */
/* awf c jack dongarra, linpack, 3/11/78. */
/* awf c */
/* awf double precision dx(1),dy(1),da */
/* awf integer i,incx,incy,ix,iy,m,mp1,n */
/* awf c */
/* awf if(n.le.0)return */
/* awf if (da .eq. 0.0d0) return */
/* awf if(incx.eq.1.and.incy.eq.1)go to 20 */
/* awf c */
/* awf c code for unequal increments or equal increments */
/* awf c not equal to 1 */
/* awf c */
/* awf ix = 1 */
/* awf iy = 1 */
/* awf if(incx.lt.0)ix = (-n+1)*incx + 1 */
/* awf if(incy.lt.0)iy = (-n+1)*incy + 1 */
/* awf do 10 i = 1,n */
/* awf dy(iy) = dy(iy) + da*dx(ix) */
/* awf ix = ix + incx */
/* awf iy = iy + incy */
/* awf 10 continue */
/* awf return */
/* awf c */
/* awf c code for both increments equal to 1 */
/* awf c */
/* awf c */
/* awf c clean-up loop */
/* awf c */
/* awf 20 m = mod(n,4) */
/* awf if( m .eq. 0 ) go to 40 */
/* awf do 30 i = 1,m */
/* awf dy(i) = dy(i) + da*dx(i) */
/* awf 30 continue */
/* awf if( n .lt. 4 ) return */
/* awf 40 mp1 = m + 1 */
/* awf do 50 i = mp1,n,4 */
/* awf dy(i) = dy(i) + da*dx(i) */
/* awf dy(i + 1) = dy(i + 1) + da*dx(i + 1) */
/* awf dy(i + 2) = dy(i + 2) + da*dx(i + 2) */
/* awf dy(i + 3) = dy(i + 3) + da*dx(i + 3) */
/* awf 50 continue */
/* awf return */
/* awf end */
/* awf C */
/* awf C */
/* awf C ---------------------------------------------------------- */
/* awf C */
/* awf double precision function ddot(n,dx,incx,dy,incy) */
/* awf c */
/* awf c forms the dot product of two vectors. */
/* awf c uses unrolled loops for increments equal to one. */
/* awf c jack dongarra, linpack, 3/11/78. */
/* awf c */
/* awf double precision dx(1),dy(1),dtemp */
/* awf integer i,incx,incy,ix,iy,m,mp1,n */
/* awf c */
/* awf ddot = 0.0d0 */
/* awf dtemp = 0.0d0 */
/* awf if(n.le.0)return */
/* awf if(incx.eq.1.and.incy.eq.1)go to 20 */
/* awf c */
/* awf c code for unequal increments or equal increments */
/* awf c not equal to 1 */
/* awf c */
/* awf ix = 1 */
/* awf iy = 1 */
/* awf if(incx.lt.0)ix = (-n+1)*incx + 1 */
/* awf if(incy.lt.0)iy = (-n+1)*incy + 1 */
/* awf do 10 i = 1,n */
/* awf dtemp = dtemp + dx(ix)*dy(iy) */
/* awf ix = ix + incx */
/* awf iy = iy + incy */
/* awf 10 continue */
/* awf ddot = dtemp */
/* awf return */
/* awf c */
/* awf c code for both increments equal to 1 */
/* awf c */
/* awf c */
/* awf c clean-up loop */
/* awf c */
/* awf 20 m = mod(n,5) */
/* awf if( m .eq. 0 ) go to 40 */
/* awf do 30 i = 1,m */
/* awf dtemp = dtemp + dx(i)*dy(i) */
/* awf 30 continue */
/* awf if( n .lt. 5 ) go to 60 */
/* awf 40 mp1 = m + 1 */
/* awf do 50 i = mp1,n,5 */
/* awf dtemp = dtemp + dx(i)*dy(i) + dx(i + 1)*dy(i + 1) + */
/* awf * dx(i + 2)*dy(i + 2) + dx(i + 3)*dy(i + 3) + dx(i + 4)*dy(i + 4) */
/* awf 50 continue */
/* awf 60 ddot = dtemp */
/* awf return */
/* awf end */
/* ------------------------------------------------------------------ */
/* ************************** */
/* LINE SEARCH ROUTINE MCSRCH */
/* ************************** */
/* Subroutine */ void mcsrch_(n, x, f, g, s, stp, ftol, xtol, maxfev, info, nfev, wa)
integer *n;
doublereal *x, *f, *g, *s, *stp, *ftol, *xtol;
integer *maxfev, *info, *nfev;
doublereal *wa;
{
/* Initialized data */
static doublereal xtrapf = 4.;
/* Local variables */
static doublereal dgxm, dgym;
static integer j, infoc;
static doublereal finit, width, stmin, stmax;
static logical stage1;
static doublereal width1, ftest1, dg, fm, fx, fy;
static logical brackt;
static doublereal dginit, dgtest;
static doublereal dgm, dgx, dgy, fxm, fym, stx, sty;
/* SUBROUTINE MCSRCH */
/* A slight modification of the subroutine CSRCH of More' and Thuente. */
/* The changes are to allow reverse communication, and do not affect */
/* the performance of the routine. */
/* THE PURPOSE OF MCSRCH IS TO FIND A STEP WHICH SATISFIES */
/* A SUFFICIENT DECREASE CONDITION AND A CURVATURE CONDITION. */
/* AT EACH STAGE THE SUBROUTINE UPDATES AN INTERVAL OF */
/* UNCERTAINTY WITH ENDPOINTS STX AND STY. THE INTERVAL OF */
/* UNCERTAINTY IS INITIALLY CHOSEN SO THAT IT CONTAINS A */
/* MINIMIZER OF THE MODIFIED FUNCTION */
/* F(X+STP*S) - F(X) - FTOL*STP*(GRADF(X)'S). */
/* IF A STEP IS OBTAINED FOR WHICH THE MODIFIED FUNCTION */
/* HAS A NONPOSITIVE FUNCTION VALUE AND NONNEGATIVE DERIVATIVE, */
/* THEN THE INTERVAL OF UNCERTAINTY IS CHOSEN SO THAT IT */
/* CONTAINS A MINIMIZER OF F(X+STP*S). */
/* THE ALGORITHM IS DESIGNED TO FIND A STEP WHICH SATISFIES */
/* THE SUFFICIENT DECREASE CONDITION */
/* F(X+STP*S) .LE. F(X) + FTOL*STP*(GRADF(X)'S), */
/* AND THE CURVATURE CONDITION */
/* ABS(GRADF(X+STP*S)'S)) .LE. GTOL*ABS(GRADF(X)'S). */
/* IF FTOL IS LESS THAN GTOL AND IF, FOR EXAMPLE, THE FUNCTION */
/* IS BOUNDED BELOW, THEN THERE IS ALWAYS A STEP WHICH SATISFIES */
/* BOTH CONDITIONS. IF NO STEP CAN BE FOUND WHICH SATISFIES BOTH */
/* CONDITIONS, THEN THE ALGORITHM USUALLY STOPS WHEN ROUNDING */
/* ERRORS PREVENT FURTHER PROGRESS. IN THIS CASE STP ONLY */
/* SATISFIES THE SUFFICIENT DECREASE CONDITION. */
/* THE SUBROUTINE STATEMENT IS */
/* SUBROUTINE MCSRCH(N,X,F,G,S,STP,FTOL,XTOL, MAXFEV,INFO,NFEV,WA) */
/* WHERE */
/* N IS A POSITIVE INTEGER INPUT VARIABLE SET TO THE NUMBER */
/* OF VARIABLES. */
/* X IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE */
/* BASE POINT FOR THE LINE SEARCH. ON OUTPUT IT CONTAINS */
/* X + STP*S. */
/* F IS A VARIABLE. ON INPUT IT MUST CONTAIN THE VALUE OF F */
/* AT X. ON OUTPUT IT CONTAINS THE VALUE OF F AT X + STP*S. */
/* G IS AN ARRAY OF LENGTH N. ON INPUT IT MUST CONTAIN THE */
/* GRADIENT OF F AT X. ON OUTPUT IT CONTAINS THE GRADIENT */
/* OF F AT X + STP*S. */
/* S IS AN INPUT ARRAY OF LENGTH N WHICH SPECIFIES THE */
/* SEARCH DIRECTION. */
/* STP IS A NONNEGATIVE VARIABLE. ON INPUT STP CONTAINS AN */
/* INITIAL ESTIMATE OF A SATISFACTORY STEP. ON OUTPUT */
/* STP CONTAINS THE FINAL ESTIMATE. */
/* FTOL AND GTOL ARE NONNEGATIVE INPUT VARIABLES. (In this reverse */
/* communication implementation GTOL is defined in a COMMON */
/* statement.) TERMINATION OCCURS WHEN THE SUFFICIENT DECREASE */
/* CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION ARE */
/* SATISFIED. */
/* XTOL IS A NONNEGATIVE INPUT VARIABLE. TERMINATION OCCURS */
/* WHEN THE RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY */
/* IS AT MOST XTOL. */
/* STPMIN AND STPMAX ARE NONNEGATIVE INPUT VARIABLES WHICH */
/* SPECIFY LOWER AND UPPER BOUNDS FOR THE STEP. (In this reverse */
/* communication implementatin they are defined in a COMMON */
/* statement). */
/* MAXFEV IS A POSITIVE INTEGER INPUT VARIABLE. TERMINATION */
/* OCCURS WHEN THE NUMBER OF CALLS TO FCN IS AT LEAST */
/* MAXFEV BY THE END OF AN ITERATION. */
/* INFO IS AN INTEGER OUTPUT VARIABLE SET AS FOLLOWS: */
/* INFO = 0 IMPROPER INPUT PARAMETERS. */
/* INFO =-1 A RETURN IS MADE TO COMPUTE THE FUNCTION AND GRADIENT. */
/* NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF */
/* CALLS TO FCN. */
/* WA IS A WORK ARRAY OF LENGTH N. */
/* SUBPROGRAMS CALLED */
/* MCSTEP */
/* FORTRAN-SUPPLIED...ABS,MAX,MIN */
/* ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 */
/* JORGE J. MORE', DAVID J. THUENTE */
/* ********** */
if (*info == -1) {
goto L45;
}
infoc = 1;
/* CHECK THE INPUT PARAMETERS FOR ERRORS. */
if (*n <= 0 || *stp <= 0. || *ftol < 0. || lb3_1.gtol < 0. || *xtol < 0. ||
lb3_1.stpmin < 0. || lb3_1.stpmax < lb3_1.stpmin || *maxfev <= 0) {
return;
}
/* COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION */
/* AND CHECK THAT S IS A DESCENT DIRECTION. */
dginit = 0.;
for (j = 0; j < *n; ++j) {
dginit += g[j] * s[j];
}
if (dginit >= 0.) {
lbptf_("THE SEARCH DIRECTION IS NOT A DESCENT DIRECTION");
return;
}
/* INITIALIZE LOCAL VARIABLES. */
brackt = FALSE_;
stage1 = TRUE_;
*nfev = 0;
finit = *f;
dgtest = *ftol * dginit;
width = lb3_1.stpmax - lb3_1.stpmin;
width1 = width / .5;
for (j = 0; j < *n; ++j) {
wa[j] = x[j];
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?