/************************************************************************* 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. :::::::::::::IMPORTANT NOTES::::::::::::: NOTE 1: This routine guarantees that it will stop at the last point where function value was calculated. It won't make several additional function evaluations after finding good point. So if you store function evaluations requested by this routine, you can be sure that last one is the point where we've stopped. NOTE 2: when 0<StpMax<StpMin, algorithm will terminate with INFO=5 and Stp=0.0 ::::::::::::::::::::::::::::::::::::::::: PARAMETERS DESCRIPRION STAGE IS ZERO ON FIRST CALL, ZERO ON FINAL EXIT 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. 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. 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 THE SUFFICIENT DECREASE CONDITION AND THE DIRECTIONAL DERIVATIVE CONDITION HOLD. INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY IS AT MOST XTOL. INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. THERE MAY NOT BE A STEP WHICH SATISFIES THE SUFFICIENT DECREASE AND CURVATURE CONDITIONS. TOLERANCES MAY BE TOO SMALL. NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN. WA IS A WORK ARRAY OF LENGTH N. ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 JORGE J. MORE', DAVID J. THUENTE *************************************************************************/ public static void mcsrch(int n, ref double[] x, ref double f, ref double[] g, double[] s, ref double stp, double stpmax, double gtol, ref int info, ref int nfev, ref double[] wa, linminstate state, ref int stage) { double v = 0; double p5 = 0; double p66 = 0; double zero = 0; int i_ = 0; // // init // p5 = 0.5; p66 = 0.66; state.xtrapf = 4.0; zero = 0; if( (double)(stpmax)==(double)(0) ) { stpmax = defstpmax; } if( (double)(stp)<(double)(stpmin) ) { stp = stpmin; } if( (double)(stp)>(double)(stpmax) ) { stp = stpmax; } // // Main cycle // while( true ) { if( stage==0 ) { // // NEXT // stage = 2; continue; } if( stage==2 ) { state.infoc = 1; info = 0; // // CHECK THE INPUT PARAMETERS FOR ERRORS. // if( (double)(stpmax)<(double)(stpmin) & (double)(stpmax)>(double)(0) ) { info = 5; stp = 0.0; return; } if( ((((((n<=0 | (double)(stp)<=(double)(0)) | (double)(ftol)<(double)(0)) | (double)(gtol)<(double)(zero)) | (double)(xtol)<(double)(zero)) | (double)(stpmin)<(double)(zero)) | (double)(stpmax)<(double)(stpmin)) | maxfev<=0 ) { stage = 0; return; } // // COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION // AND CHECK THAT S IS A DESCENT DIRECTION. // v = 0.0; for(i_=0; i_<=n-1;i_++) { v += g[i_]*s[i_]; } state.dginit = v; if( (double)(state.dginit)>=(double)(0) ) { stage = 0; return; } // // INITIALIZE LOCAL VARIABLES. // state.brackt = false; state.stage1 = true; nfev = 0; state.finit = f; state.dgtest = ftol*state.dginit; state.width = stpmax-stpmin; state.width1 = state.width/p5; for(i_=0; i_<=n-1;i_++) { wa[i_] = x[i_]; } // // 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. // state.stx = 0; state.fx = state.finit; state.dgx = state.dginit; state.sty = 0; state.fy = state.finit; state.dgy = state.dginit; // // NEXT // stage = 3; continue; } if( stage==3 ) { // // START OF ITERATION. // // SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND // TO THE PRESENT INTERVAL OF UNCERTAINTY. // if( state.brackt ) { if( (double)(state.stx)<(double)(state.sty) ) { state.stmin = state.stx; state.stmax = state.sty; } else { state.stmin = state.sty; state.stmax = state.stx; } } else { state.stmin = state.stx; state.stmax = stp+state.xtrapf*(stp-state.stx); } // // FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. // if( (double)(stp)>(double)(stpmax) ) { stp = stpmax; } if( (double)(stp)<(double)(stpmin) ) { stp = stpmin; } // // IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET // STP BE THE LOWEST POINT OBTAINED SO FAR. // if( (((state.brackt & ((double)(stp)<=(double)(state.stmin) | (double)(stp)>=(double)(state.stmax))) | nfev>=maxfev-1) | state.infoc==0) | (state.brackt & (double)(state.stmax-state.stmin)<=(double)(xtol*state.stmax)) ) { stp = state.stx; } // // EVALUATE THE FUNCTION AND GRADIENT AT STP // AND COMPUTE THE DIRECTIONAL DERIVATIVE. // for(i_=0; i_<=n-1;i_++) { x[i_] = wa[i_]; } for(i_=0; i_<=n-1;i_++) { x[i_] = x[i_] + stp*s[i_]; } // // NEXT // stage = 4; return; } if( stage==4 ) { info = 0; nfev = nfev+1; v = 0.0; for(i_=0; i_<=n-1;i_++) { v += g[i_]*s[i_]; } state.dg = v; state.ftest1 = state.finit+stp*state.dgtest; // // TEST FOR CONVERGENCE. // if( (state.brackt & ((double)(stp)<=(double)(state.stmin) | (double)(stp)>=(double)(state.stmax))) | state.infoc==0 ) { info = 6; } if( ((double)(stp)==(double)(stpmax) & (double)(f)<=(double)(state.ftest1)) & (double)(state.dg)<=(double)(state.dgtest) ) { info = 5; } if( (double)(stp)==(double)(stpmin) & ((double)(f)>(double)(state.ftest1) | (double)(state.dg)>=(double)(state.dgtest)) ) { info = 4; } if( nfev>=maxfev ) { info = 3; } if( state.brackt & (double)(state.stmax-state.stmin)<=(double)(xtol*state.stmax) ) { info = 2; } if( (double)(f)<=(double)(state.ftest1) & (double)(Math.Abs(state.dg))<=(double)(-(gtol*state.dginit)) ) { info = 1; } // // CHECK FOR TERMINATION. // if( info!=0 ) { stage = 0; return; } // // IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED // FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. // if( (state.stage1 & (double)(f)<=(double)(state.ftest1)) & (double)(state.dg)>=(double)(Math.Min(ftol, gtol)*state.dginit) ) { state.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( (state.stage1 & (double)(f)<=(double)(state.fx)) & (double)(f)>(double)(state.ftest1) ) { // // DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. // state.fm = f-stp*state.dgtest; state.fxm = state.fx-state.stx*state.dgtest; state.fym = state.fy-state.sty*state.dgtest; state.dgm = state.dg-state.dgtest; state.dgxm = state.dgx-state.dgtest; state.dgym = state.dgy-state.dgtest; // // CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. // mcstep(ref state.stx, ref state.fxm, ref state.dgxm, ref state.sty, ref state.fym, ref state.dgym, ref stp, state.fm, state.dgm, ref state.brackt, state.stmin, state.stmax, ref state.infoc); // // RESET THE FUNCTION AND GRADIENT VALUES FOR F. // state.fx = state.fxm+state.stx*state.dgtest; state.fy = state.fym+state.sty*state.dgtest; state.dgx = state.dgxm+state.dgtest; state.dgy = state.dgym+state.dgtest; } else { // // CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. // mcstep(ref state.stx, ref state.fx, ref state.dgx, ref state.sty, ref state.fy, ref state.dgy, ref stp, f, state.dg, ref state.brackt, state.stmin, state.stmax, ref state.infoc); } // // FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE // INTERVAL OF UNCERTAINTY. // if( state.brackt ) { if( (double)(Math.Abs(state.sty-state.stx))>=(double)(p66*state.width1) ) { stp = state.stx+p5*(state.sty-state.stx); } state.width1 = state.width; state.width = Math.Abs(state.sty-state.stx); } // // NEXT. // stage = 3; continue; } } }
/************************************************************************* * 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. * * PARAMETERS DESCRIPRION * * 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. 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. * * 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 THE SUFFICIENT DECREASE CONDITION AND THE * DIRECTIONAL DERIVATIVE CONDITION HOLD. * * INFO = 2 RELATIVE WIDTH OF THE INTERVAL OF UNCERTAINTY * IS AT MOST XTOL. * * INFO = 3 NUMBER OF CALLS TO FCN HAS REACHED MAXFEV. * * INFO = 4 THE STEP IS AT THE LOWER BOUND STPMIN. * * INFO = 5 THE STEP IS AT THE UPPER BOUND STPMAX. * * INFO = 6 ROUNDING ERRORS PREVENT FURTHER PROGRESS. * THERE MAY NOT BE A STEP WHICH SATISFIES THE * SUFFICIENT DECREASE AND CURVATURE CONDITIONS. * TOLERANCES MAY BE TOO SMALL. * * NFEV IS AN INTEGER OUTPUT VARIABLE SET TO THE NUMBER OF CALLS TO FCN. * * WA IS A WORK ARRAY OF LENGTH N. * * ARGONNE NATIONAL LABORATORY. MINPACK PROJECT. JUNE 1983 * JORGE J. MORE', DAVID J. THUENTE *************************************************************************/ public static void mcsrch(int n, ref double[] x, ref double f, ref double[] g, ref double[] s, ref double stp, double stpmax, ref int info, ref int nfev, ref double[] wa, ref linminstate state, ref int stage) { double v = 0; double p5 = 0; double p66 = 0; double zero = 0; int i_ = 0; // // init // p5 = 0.5; p66 = 0.66; state.xtrapf = 4.0; zero = 0; if ((double)(stpmax) == (double)(0)) { stpmax = defstpmax; } if ((double)(stp) < (double)(stpmin)) { stp = stpmin; } if ((double)(stp) > (double)(stpmax)) { stp = stpmax; } // // Main cycle // while (true) { if (stage == 0) { // // NEXT // stage = 2; continue; } if (stage == 2) { state.infoc = 1; info = 0; // // CHECK THE INPUT PARAMETERS FOR ERRORS. // if (n <= 0 | (double)(stp) <= (double)(0) | (double)(ftol) < (double)(0) | (double)(gtol) < (double)(zero) | (double)(xtol) < (double)(zero) | (double)(stpmin) < (double)(zero) | (double)(stpmax) < (double)(stpmin) | maxfev <= 0) { stage = 0; return; } // // COMPUTE THE INITIAL GRADIENT IN THE SEARCH DIRECTION // AND CHECK THAT S IS A DESCENT DIRECTION. // v = 0.0; for (i_ = 0; i_ <= n - 1; i_++) { v += g[i_] * s[i_]; } state.dginit = v; if ((double)(state.dginit) >= (double)(0)) { stage = 0; return; } // // INITIALIZE LOCAL VARIABLES. // state.brackt = false; state.stage1 = true; nfev = 0; state.finit = f; state.dgtest = ftol * state.dginit; state.width = stpmax - stpmin; state.width1 = state.width / p5; for (i_ = 0; i_ <= n - 1; i_++) { wa[i_] = x[i_]; } // // 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. // state.stx = 0; state.fx = state.finit; state.dgx = state.dginit; state.sty = 0; state.fy = state.finit; state.dgy = state.dginit; // // NEXT // stage = 3; continue; } if (stage == 3) { // // START OF ITERATION. // // SET THE MINIMUM AND MAXIMUM STEPS TO CORRESPOND // TO THE PRESENT INTERVAL OF UNCERTAINTY. // if (state.brackt) { if ((double)(state.stx) < (double)(state.sty)) { state.stmin = state.stx; state.stmax = state.sty; } else { state.stmin = state.sty; state.stmax = state.stx; } } else { state.stmin = state.stx; state.stmax = stp + state.xtrapf * (stp - state.stx); } // // FORCE THE STEP TO BE WITHIN THE BOUNDS STPMAX AND STPMIN. // if ((double)(stp) > (double)(stpmax)) { stp = stpmax; } if ((double)(stp) < (double)(stpmin)) { stp = stpmin; } // // IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET // STP BE THE LOWEST POINT OBTAINED SO FAR. // if (state.brackt & ((double)(stp) <= (double)(state.stmin) | (double)(stp) >= (double)(state.stmax)) | nfev >= maxfev - 1 | state.infoc == 0 | state.brackt & (double)(state.stmax - state.stmin) <= (double)(xtol * state.stmax)) { stp = state.stx; } // // EVALUATE THE FUNCTION AND GRADIENT AT STP // AND COMPUTE THE DIRECTIONAL DERIVATIVE. // for (i_ = 0; i_ <= n - 1; i_++) { x[i_] = wa[i_]; } for (i_ = 0; i_ <= n - 1; i_++) { x[i_] = x[i_] + stp * s[i_]; } // // NEXT // stage = 4; return; } if (stage == 4) { info = 0; nfev = nfev + 1; v = 0.0; for (i_ = 0; i_ <= n - 1; i_++) { v += g[i_] * s[i_]; } state.dg = v; state.ftest1 = state.finit + stp * state.dgtest; // // TEST FOR CONVERGENCE. // if (state.brackt & ((double)(stp) <= (double)(state.stmin) | (double)(stp) >= (double)(state.stmax)) | state.infoc == 0) { info = 6; } if ((double)(stp) == (double)(stpmax) & (double)(f) <= (double)(state.ftest1) & (double)(state.dg) <= (double)(state.dgtest)) { info = 5; } if ((double)(stp) == (double)(stpmin) & ((double)(f) > (double)(state.ftest1) | (double)(state.dg) >= (double)(state.dgtest))) { info = 4; } if (nfev >= maxfev) { info = 3; } if (state.brackt & (double)(state.stmax - state.stmin) <= (double)(xtol * state.stmax)) { info = 2; } if ((double)(f) <= (double)(state.ftest1) & (double)(Math.Abs(state.dg)) <= (double)(-(gtol * state.dginit))) { info = 1; } // // CHECK FOR TERMINATION. // if (info != 0) { stage = 0; return; } // // IN THE FIRST STAGE WE SEEK A STEP FOR WHICH THE MODIFIED // FUNCTION HAS A NONPOSITIVE VALUE AND NONNEGATIVE DERIVATIVE. // if (state.stage1 & (double)(f) <= (double)(state.ftest1) & (double)(state.dg) >= (double)(Math.Min(ftol, gtol) * state.dginit)) { state.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 (state.stage1 & (double)(f) <= (double)(state.fx) & (double)(f) > (double)(state.ftest1)) { // // DEFINE THE MODIFIED FUNCTION AND DERIVATIVE VALUES. // state.fm = f - stp * state.dgtest; state.fxm = state.fx - state.stx * state.dgtest; state.fym = state.fy - state.sty * state.dgtest; state.dgm = state.dg - state.dgtest; state.dgxm = state.dgx - state.dgtest; state.dgym = state.dgy - state.dgtest; // // CALL CSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. // mcstep(ref state.stx, ref state.fxm, ref state.dgxm, ref state.sty, ref state.fym, ref state.dgym, ref stp, state.fm, state.dgm, ref state.brackt, state.stmin, state.stmax, ref state.infoc); // // RESET THE FUNCTION AND GRADIENT VALUES FOR F. // state.fx = state.fxm + state.stx * state.dgtest; state.fy = state.fym + state.sty * state.dgtest; state.dgx = state.dgxm + state.dgtest; state.dgy = state.dgym + state.dgtest; } else { // // CALL MCSTEP TO UPDATE THE INTERVAL OF UNCERTAINTY // AND TO COMPUTE THE NEW STEP. // mcstep(ref state.stx, ref state.fx, ref state.dgx, ref state.sty, ref state.fy, ref state.dgy, ref stp, f, state.dg, ref state.brackt, state.stmin, state.stmax, ref state.infoc); } // // FORCE A SUFFICIENT DECREASE IN THE SIZE OF THE // INTERVAL OF UNCERTAINTY. // if (state.brackt) { if ((double)(Math.Abs(state.sty - state.stx)) >= (double)(p66 * state.width1)) { stp = state.stx + p5 * (state.sty - state.stx); } state.width1 = state.width; state.width = Math.Abs(state.sty - state.stx); } // // NEXT. // stage = 3; continue; } } }
public override alglib.apobject make_copy() { linminstate _result = new linminstate(); _result.brackt = brackt; _result.stage1 = stage1; _result.infoc = infoc; _result.dg = dg; _result.dgm = dgm; _result.dginit = dginit; _result.dgtest = dgtest; _result.dgx = dgx; _result.dgxm = dgxm; _result.dgy = dgy; _result.dgym = dgym; _result.finit = finit; _result.ftest1 = ftest1; _result.fm = fm; _result.fx = fx; _result.fxm = fxm; _result.fy = fy; _result.fym = fym; _result.stx = stx; _result.sty = sty; _result.stmin = stmin; _result.stmax = stmax; _result.width = width; _result.width1 = width1; _result.xtrapf = xtrapf; return _result; }