Ejemplo n.º 1
0
        /*************************************************************************
        *  L-BFGS algorithm results
        *
        *  Called after MinLBFGSIteration returned False.
        *
        *  Input parameters:
        *   State   -   algorithm state (used by MinLBFGSIteration).
        *
        *  Output parameters:
        *   X       -   array[0..N-1], solution
        *   Rep     -   optimization report:
        * Rep.TerminationType completetion code:
        * -2    rounding errors prevent further improvement.
        *                           X contains best point found.
        * -1    incorrect parameters were specified
        *  1    relative function improvement is no more than
        *                           EpsF.
        *  2    relative step is no more than EpsX.
        *  4    gradient norm is no more than EpsG
        *  5    MaxIts steps was taken
        * Rep.IterationsCount contains iterations count
        * NFEV countains number of function calculations
        *
        *  -- ALGLIB --
        *    Copyright 14.11.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void minlbfgsresults(ref lbfgsstate state,
                                           ref double[] x,
                                           ref lbfgsreport rep)
        {
            int i_ = 0;

            x = new double[state.n - 1 + 1];
            for (i_ = 0; i_ <= state.n - 1; i_++)
            {
                x[i_] = state.x[i_];
            }
            rep.iterationscount = state.repiterationscount;
            rep.nfev            = state.repnfev;
            rep.terminationtype = state.repterminationtype;
        }
Ejemplo n.º 2
0
        /*************************************************************************
        *  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
        *************************************************************************/
        private static void mcsrch(int n,
                                   ref double[] x,
                                   ref double f,
                                   ref double[] g,
                                   ref double[] s,
                                   ref double stp,
                                   ref int info,
                                   ref int nfev,
                                   ref double[] wa,
                                   ref lbfgsstate 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;

            //
            // 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 | stp <= 0 | ftol < 0 | gtol < zero | xtol < zero | stpmin < zero | stpmax < 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 (state.dginit >= 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 (state.stx < 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 (stp > stpmax)
                    {
                        stp = stpmax;
                    }
                    if (stp < stpmin)
                    {
                        stp = stpmin;
                    }

                    //
                    //        IF AN UNUSUAL TERMINATION IS TO OCCUR THEN LET
                    //        STP BE THE LOWEST POINT OBTAINED SO FAR.
                    //
                    if (state.brackt & (stp <= state.stmin | stp >= state.stmax) | nfev >= maxfev - 1 | state.infoc == 0 | state.brackt & state.stmax - state.stmin <= 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 & (stp <= state.stmin | stp >= state.stmax) | state.infoc == 0)
                    {
                        info = 6;
                    }
                    if (stp == stpmax & f <= state.ftest1 & state.dg <= state.dgtest)
                    {
                        info = 5;
                    }
                    if (stp == stpmin & (f > state.ftest1 | state.dg >= state.dgtest))
                    {
                        info = 4;
                    }
                    if (nfev >= maxfev)
                    {
                        info = 3;
                    }
                    if (state.brackt & state.stmax - state.stmin <= xtol * state.stmax)
                    {
                        info = 2;
                    }
                    if (f <= state.ftest1 & Math.Abs(state.dg) <= -(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 & f <= state.ftest1 & state.dg >= 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 & f <= state.fx & f > 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 (Math.Abs(state.sty - state.stx) >= 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;
                }
            }
        }
Ejemplo n.º 3
0
        /*************************************************************************
        *  One L-BFGS iteration
        *
        *  Called after initialization with MinLBFGS.
        *  See HTML documentation for examples.
        *
        *  Input parameters:
        *   State   -   structure which stores algorithm state between calls and
        *               which is used for reverse communication. Must be initialized
        *               with MinLBFGS.
        *
        *  If suborutine returned False, iterative proces has converged.
        *
        *  If subroutine returned True, caller should calculate function value
        *  State.F an gradient State.G[0..N-1] at State.X[0..N-1] and call
        *  MinLBFGSIteration again.
        *
        *  -- ALGLIB --
        *    Copyright 20.04.2009 by Bochkanov Sergey
        *************************************************************************/
        public static bool minlbfgsiteration(ref lbfgsstate state)
        {
            bool   result = new bool();
            int    n      = 0;
            int    m      = 0;
            int    maxits = 0;
            double epsf   = 0;
            double epsg   = 0;
            double epsx   = 0;
            int    i      = 0;
            int    j      = 0;
            int    ic     = 0;
            int    mcinfo = 0;
            double v      = 0;
            double vv     = 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];
                m      = state.rstate.ia[1];
                maxits = state.rstate.ia[2];
                i      = state.rstate.ia[3];
                j      = state.rstate.ia[4];
                ic     = state.rstate.ia[5];
                mcinfo = state.rstate.ia[6];
                epsf   = state.rstate.ra[0];
                epsg   = state.rstate.ra[1];
                epsx   = state.rstate.ra[2];
                v      = state.rstate.ra[3];
                vv     = state.rstate.ra[4];
            }
            else
            {
                n      = -983;
                m      = -989;
                maxits = -834;
                i      = 900;
                j      = -287;
                ic     = 364;
                mcinfo = 214;
                epsf   = -338;
                epsg   = -686;
                epsx   = 912;
                v      = 585;
                vv     = 497;
            }
            if (state.rstate.stage == 0)
            {
                goto lbl_0;
            }
            if (state.rstate.stage == 1)
            {
                goto lbl_1;
            }

            //
            // Routine body
            //

            //
            // Unload frequently used variables from State structure
            // (just for typing convinience)
            //
            n      = state.n;
            m      = state.m;
            epsg   = state.epsg;
            epsf   = state.epsf;
            epsx   = state.epsx;
            maxits = state.maxits;
            state.repterminationtype = 0;
            state.repiterationscount = 0;
            state.repnfev            = 0;

            //
            // Update info
            //
            state.xupdated = false;

            //
            // Calculate F/G
            //
            state.rstate.stage = 0;
            goto lbl_rcomm;
lbl_0:
            state.repnfev = 1;

            //
            // Preparations
            //
            state.fold = state.f;
            v          = 0.0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                v += state.g[i_] * state.g[i_];
            }
            v = Math.Sqrt(v);
            if (v == 0)
            {
                state.repterminationtype = 4;
                result = false;
                return(result);
            }
            state.stp = 1.0 / v;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.d[i_] = -state.g[i_];
            }

            //
            // Main cycle
            //
lbl_2:
            if (false)
            {
                goto lbl_3;
            }

            //
            // Main cycle: prepare to 1-D line search
            //
            state.p = state.k % m;
            state.q = Math.Min(state.k, m - 1);

            //
            // Store X[k], G[k]
            //
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.s[state.p, i_] = -state.x[i_];
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.y[state.p, i_] = -state.g[i_];
            }

            //
            // Minimize F(x+alpha*d)
            //
            state.mcstage = 0;
            if (state.k != 0)
            {
                state.stp = 1.0;
            }
            mcsrch(n, ref state.x, ref state.f, ref state.g, ref state.d, ref state.stp, ref mcinfo, ref state.nfev, ref state.work, ref state, ref state.mcstage);
lbl_4:
            if (state.mcstage == 0)
            {
                goto lbl_5;
            }
            state.rstate.stage = 1;
            goto lbl_rcomm;
lbl_1:
            mcsrch(n, ref state.x, ref state.f, ref state.g, ref state.d, ref state.stp, ref mcinfo, ref state.nfev, ref state.work, ref state, ref state.mcstage);
            goto lbl_4;
lbl_5:

            //
            // Main cycle: update information and Hessian.
            // Check stopping conditions.
            //
            state.repnfev            = state.repnfev + state.nfev;
            state.repiterationscount = state.repiterationscount + 1;

            //
            // Calculate S[k], Y[k], Rho[k], GammaK
            //
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.s[state.p, i_] = state.s[state.p, i_] + state.x[i_];
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.y[state.p, i_] = state.y[state.p, i_] + state.g[i_];
            }

            //
            // Stopping conditions
            //
            if (state.repiterationscount >= maxits & maxits > 0)
            {
                //
                // Too many iterations
                //
                state.repterminationtype = 5;
                result = false;
                return(result);
            }
            v = 0.0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                v += state.g[i_] * state.g[i_];
            }
            if (Math.Sqrt(v) <= epsg)
            {
                //
                // Gradient is small enough
                //
                state.repterminationtype = 4;
                result = false;
                return(result);
            }
            if (state.fold - state.f <= epsf * Math.Max(Math.Abs(state.fold), Math.Max(Math.Abs(state.f), 1.0)))
            {
                //
                // F(k+1)-F(k) is small enough
                //
                state.repterminationtype = 1;
                result = false;
                return(result);
            }
            v = 0.0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                v += state.s[state.p, i_] * state.s[state.p, i_];
            }
            if (Math.Sqrt(v) <= epsx)
            {
                //
                // X(k+1)-X(k) is small enough
                //
                state.repterminationtype = 2;
                result = false;
                return(result);
            }

            //
            // Calculate Rho[k], GammaK
            //
            v = 0.0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                v += state.y[state.p, i_] * state.s[state.p, i_];
            }
            vv = 0.0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                vv += state.y[state.p, i_] * state.y[state.p, i_];
            }
            if (v == 0 | vv == 0)
            {
                //
                // Rounding errors make further iterations impossible.
                //
                state.repterminationtype = -2;
                result = false;
                return(result);
            }
            state.rho[state.p] = 1 / v;
            state.gammak       = v / vv;

            //
            //  Calculate d(k+1) = H(k+1)*g(k+1)
            //
            //  for I:=K downto K-Q do
            //      V = s(i)^T * work(iteration:I)
            //      theta(i) = V
            //      work(iteration:I+1) = work(iteration:I) - V*Rho(i)*y(i)
            //  work(last iteration) = H0*work(last iteration)
            //  for I:=K-Q to K do
            //      V = y(i)^T*work(iteration:I)
            //      work(iteration:I+1) = work(iteration:I) +(-V+theta(i))*Rho(i)*s(i)
            //
            //  NOW WORK CONTAINS d(k+1)
            //
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.work[i_] = state.g[i_];
            }
            for (i = state.k; i >= state.k - state.q; i--)
            {
                ic = i % m;
                v  = 0.0;
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    v += state.s[ic, i_] * state.work[i_];
                }
                state.theta[ic] = v;
                vv = v * state.rho[ic];
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    state.work[i_] = state.work[i_] - vv * state.y[ic, i_];
                }
            }
            v = state.gammak;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.work[i_] = v * state.work[i_];
            }
            for (i = state.k - state.q; i <= state.k; i++)
            {
                ic = i % m;
                v  = 0.0;
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    v += state.y[ic, i_] * state.work[i_];
                }
                vv = state.rho[ic] * (-v + state.theta[ic]);
                for (i_ = 0; i_ <= n - 1; i_++)
                {
                    state.work[i_] = state.work[i_] + vv * state.s[ic, i_];
                }
            }
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.d[i_] = -state.work[i_];
            }

            //
            // Next step
            //
            state.fold     = state.f;
            state.k        = state.k + 1;
            state.xupdated = true;
            goto lbl_2;
lbl_3:
            result = false;
            return(result);

            //
            // Saving state
            //
lbl_rcomm:
            result             = true;
            state.rstate.ia[0] = n;
            state.rstate.ia[1] = m;
            state.rstate.ia[2] = maxits;
            state.rstate.ia[3] = i;
            state.rstate.ia[4] = j;
            state.rstate.ia[5] = ic;
            state.rstate.ia[6] = mcinfo;
            state.rstate.ra[0] = epsf;
            state.rstate.ra[1] = epsg;
            state.rstate.ra[2] = epsx;
            state.rstate.ra[3] = v;
            state.rstate.ra[4] = vv;
            return(result);
        }
Ejemplo n.º 4
0
        /*************************************************************************
        *       LIMITED MEMORY BFGS METHOD FOR LARGE SCALE OPTIMIZATION
        *
        *  The subroutine minimizes function F(x) of N arguments by  using  a  quasi-
        *  Newton method (LBFGS scheme) which is optimized to use  a  minimum  amount
        *  of memory.
        *
        *  The subroutine generates the approximation of an inverse Hessian matrix by
        *  using information about the last M steps of the algorithm  (instead of N).
        *  It lessens a required amount of memory from a value  of  order  N^2  to  a
        *  value of order 2*N*M.
        *
        *  Input parameters:
        *   N   -   problem dimension. N>0
        *   M   -   number of corrections in the BFGS scheme of Hessian
        *           approximation update. Recommended value:  3<=M<=7. The smaller
        *           value causes worse convergence, the bigger will  not  cause  a
        *           considerably better convergence, but will cause a fall in  the
        *           performance. M<=N.
        *   X   -   initial solution approximation, array[0..N-1].
        *   EpsG -  positive number which  defines  a  precision  of  search.  The
        *           subroutine finishes its work if the condition ||G|| < EpsG  is
        *           satisfied, where ||.|| means Euclidian norm, G - gradient, X -
        *           current approximation.
        *   EpsF -  positive number which  defines  a  precision  of  search.  The
        *           subroutine finishes its work if on iteration  number  k+1  the
        *           condition |F(k+1)-F(k)| <= EpsF*max{|F(k)|, |F(k+1)|, 1}    is
        *           satisfied.
        *   EpsX -  positive number which  defines  a  precision  of  search.  The
        *           subroutine finishes its work if on iteration number k+1    the
        *           condition |X(k+1)-X(k)| <= EpsX is fulfilled.
        *   MaxIts- maximum number of iterations. If MaxIts=0, the number of
        *           iterations is unlimited.
        *   Flags - additional settings:
        * Flags = 0     means no additional settings
        * Flags = 1     "do not allocate memory". used when solving
        *                           a many subsequent tasks with  same N/M  values.
        *                           First  call MUST  be without this flag bit set,
        *                           subsequent calls of MinLBFGS with same LBFGSState
        *                           structure can set Flags to 1.
        *
        *  Output parameters:
        *   State - structure used for reverse communication.
        *
        *  See also MinLBFGSIteration, MinLBFGSResults
        *
        *  -- ALGLIB --
        *    Copyright 14.11.2007 by Bochkanov Sergey
        *************************************************************************/
        public static void minlbfgs(int n,
                                    int m,
                                    ref double[] x,
                                    double epsg,
                                    double epsf,
                                    double epsx,
                                    int maxits,
                                    int flags,
                                    ref lbfgsstate state)
        {
            bool allocatemem = new bool();
            int  i_          = 0;

            System.Diagnostics.Debug.Assert(n >= 1, "MinLBFGS: N too small!");
            System.Diagnostics.Debug.Assert(m >= 1, "MinLBFGS: M too small!");
            System.Diagnostics.Debug.Assert(m <= n, "MinLBFGS: M too large!");
            System.Diagnostics.Debug.Assert(epsg >= 0, "MinLBFGS: negative EpsG!");
            System.Diagnostics.Debug.Assert(epsf >= 0, "MinLBFGS: negative EpsF!");
            System.Diagnostics.Debug.Assert(epsx >= 0, "MinLBFGS: negative EpsX!");
            System.Diagnostics.Debug.Assert(maxits >= 0, "MinLBFGS: negative MaxIts!");

            //
            // Initialize
            //
            state.n      = n;
            state.m      = m;
            state.epsg   = epsg;
            state.epsf   = epsf;
            state.epsx   = epsx;
            state.maxits = maxits;
            state.flags  = flags;
            allocatemem  = flags % 2 == 0;
            flags        = flags / 2;
            if (allocatemem)
            {
                state.rho   = new double[m - 1 + 1];
                state.theta = new double[m - 1 + 1];
                state.y     = new double[m - 1 + 1, n - 1 + 1];
                state.s     = new double[m - 1 + 1, n - 1 + 1];
                state.d     = new double[n - 1 + 1];
                state.x     = new double[n - 1 + 1];
                state.g     = new double[n - 1 + 1];
                state.work  = new double[n - 1 + 1];
            }

            //
            // Initialize Rep structure
            //
            state.xupdated = false;

            //
            // Prepare first run
            //
            state.k = 0;
            for (i_ = 0; i_ <= n - 1; i_++)
            {
                state.x[i_] = x[i_];
            }
            state.rstate.ia    = new int[6 + 1];
            state.rstate.ra    = new double[4 + 1];
            state.rstate.stage = -1;
        }