/************************************************************************* Results of Armijo search OUTPUT PARAMETERS: INFO - on output it is set to one of the return codes: * 0 improper input params * 1 optimum step is found with at most FMAX evaluations * 3 FMAX evaluations were used, X contains optimum found so far * 4 step is at lower bound STPMIN * 5 step is at upper bound STP - step length (in case of failure it is still returned) F - function value (in case of failure it is still returned) -- ALGLIB -- Copyright 05.10.2010 by Bochkanov Sergey *************************************************************************/ public static void armijoresults(armijostate state, ref int info, ref double stp, ref double f) { info = state.info; stp = state.stplen; f = state.fcur; }
/************************************************************************* These functions perform Armijo line search using at most FMAX function evaluations. It doesn't enforce some kind of " sufficient decrease" criterion - it just tries different Armijo steps and returns optimum found so far. Optimization is done using F-rcomm interface: * ArmijoCreate initializes State structure (reusing previously allocated buffers) * ArmijoIteration is subsequently called * ArmijoResults returns results INPUT PARAMETERS: N - problem size X - array[N], starting point F - F(X+S*STP) S - step direction, S>0 STP - step length STPMAX - maximum value for STP or zero (if no limit is imposed) FMAX - maximum number of function evaluations State - optimization state -- ALGLIB -- Copyright 05.10.2010 by Bochkanov Sergey *************************************************************************/ public static void armijocreate(int n, double[] x, double f, double[] s, double stp, double stpmax, int fmax, armijostate state) { int i_ = 0; if( ap.len(state.x)<n ) { state.x = new double[n]; } if( ap.len(state.xbase)<n ) { state.xbase = new double[n]; } if( ap.len(state.s)<n ) { state.s = new double[n]; } state.stpmax = stpmax; state.fmax = fmax; state.stplen = stp; state.fcur = f; state.n = n; for(i_=0; i_<=n-1;i_++) { state.xbase[i_] = x[i_]; } for(i_=0; i_<=n-1;i_++) { state.s[i_] = s[i_]; } state.rstate.ia = new int[0+1]; state.rstate.ra = new double[0+1]; state.rstate.stage = -1; }
/************************************************************************* This is rcomm-based search function -- ALGLIB -- Copyright 05.10.2010 by Bochkanov Sergey *************************************************************************/ public static bool armijoiteration(armijostate state) { bool result = new bool(); double v = 0; int n = 0; int i_ = 0; // // Reverse communication preparations // I know it looks ugly, but it works the same way // anywhere from C++ to Python. // // This code initializes locals by: // * random values determined during code // generation - on first subroutine call // * values from previous call - on subsequent calls // if( state.rstate.stage>=0 ) { n = state.rstate.ia[0]; v = state.rstate.ra[0]; } else { n = -983; v = -989; } if( state.rstate.stage==0 ) { goto lbl_0; } if( state.rstate.stage==1 ) { goto lbl_1; } if( state.rstate.stage==2 ) { goto lbl_2; } if( state.rstate.stage==3 ) { goto lbl_3; } // // Routine body // if( ((double)(state.stplen)<=(double)(0) | (double)(state.stpmax)<(double)(0)) | state.fmax<2 ) { state.info = 0; result = false; return result; } if( (double)(state.stplen)<=(double)(stpmin) ) { state.info = 4; result = false; return result; } n = state.n; state.nfev = 0; // // We always need F // state.needf = true; // // Bound StpLen // if( (double)(state.stplen)>(double)(state.stpmax) & (double)(state.stpmax)!=(double)(0) ) { state.stplen = state.stpmax; } // // Increase length // v = state.stplen*armijofactor; if( (double)(v)>(double)(state.stpmax) & (double)(state.stpmax)!=(double)(0) ) { v = state.stpmax; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.xbase[i_]; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.x[i_] + v*state.s[i_]; } state.rstate.stage = 0; goto lbl_rcomm; lbl_0: state.nfev = state.nfev+1; if( (double)(state.f)>=(double)(state.fcur) ) { goto lbl_4; } state.stplen = v; state.fcur = state.f; lbl_6: if( false ) { goto lbl_7; } // // test stopping conditions // if( state.nfev>=state.fmax ) { state.info = 3; result = false; return result; } if( (double)(state.stplen)>=(double)(state.stpmax) ) { state.info = 5; result = false; return result; } // // evaluate F // v = state.stplen*armijofactor; if( (double)(v)>(double)(state.stpmax) & (double)(state.stpmax)!=(double)(0) ) { v = state.stpmax; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.xbase[i_]; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.x[i_] + v*state.s[i_]; } state.rstate.stage = 1; goto lbl_rcomm; lbl_1: state.nfev = state.nfev+1; // // make decision // if( (double)(state.f)<(double)(state.fcur) ) { state.stplen = v; state.fcur = state.f; } else { state.info = 1; result = false; return result; } goto lbl_6; lbl_7: lbl_4: // // Decrease length // v = state.stplen/armijofactor; for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.xbase[i_]; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.x[i_] + v*state.s[i_]; } state.rstate.stage = 2; goto lbl_rcomm; lbl_2: state.nfev = state.nfev+1; if( (double)(state.f)>=(double)(state.fcur) ) { goto lbl_8; } state.stplen = state.stplen/armijofactor; state.fcur = state.f; lbl_10: if( false ) { goto lbl_11; } // // test stopping conditions // if( state.nfev>=state.fmax ) { state.info = 3; result = false; return result; } if( (double)(state.stplen)<=(double)(stpmin) ) { state.info = 4; result = false; return result; } // // evaluate F // v = state.stplen/armijofactor; for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.xbase[i_]; } for(i_=0; i_<=n-1;i_++) { state.x[i_] = state.x[i_] + v*state.s[i_]; } state.rstate.stage = 3; goto lbl_rcomm; lbl_3: state.nfev = state.nfev+1; // // make decision // if( (double)(state.f)<(double)(state.fcur) ) { state.stplen = state.stplen/armijofactor; state.fcur = state.f; } else { state.info = 1; result = false; return result; } goto lbl_10; lbl_11: lbl_8: // // Nothing to be done // state.info = 1; result = false; return result; // // Saving state // lbl_rcomm: result = true; state.rstate.ia[0] = n; state.rstate.ra[0] = v; return result; }
public override alglib.apobject make_copy() { armijostate _result = new armijostate(); _result.needf = needf; _result.x = (double[])x.Clone(); _result.f = f; _result.n = n; _result.xbase = (double[])xbase.Clone(); _result.s = (double[])s.Clone(); _result.stplen = stplen; _result.fcur = fcur; _result.stpmax = stpmax; _result.fmax = fmax; _result.nfev = nfev; _result.info = info; _result.rstate = (rcommstate)rstate.make_copy(); return _result; }