Example #1
0
        private double[] Compute(OptMultivariateFunction function, OptMultivariateGradient gradient, double tolerance, double factr, ref int nMax)
        {
            double f = 0;

            BFGSTask TASK   = BFGSTask.START;
            BFGSTask Csave  = BFGSTask.START;
            int      iprint = 0;

            bool Continue = true;

            int funcEvaluations = 0;

            while (Continue)
            {
                this._SETULB.Run(this._NumFreeVariables, this.M, ref this._FreeVariables, 0, this._LowerBounds, 0, this._UpperBounds, 0,
                                 this._NBD, 0, ref f, ref this._GradientArray, 0, factr, tolerance, ref WA, 0, ref IWA, 0, ref TASK, iprint, ref Csave,
                                 ref LSAVE, 0, ref this.ISAVE, 0, ref DSAVE, 0);

                if (funcEvaluations <= nMax)
                {
                    if (TASK == BFGSTask.FG || TASK == BFGSTask.FG_LNSRCH || TASK == BFGSTask.FG_ST || TASK == BFGSTask.FG_START)
                    {
                        // c        the minimization routine has returned to request the
                        // c        function f and gradient g values at the current x.

                        // c        Compute function value f for the sample problem.

                        this.UpdateExternalVariables();

                        funcEvaluations++;
                        f = function(this._ExternalVariables);

                        this._ExternalGradientArray = gradient(this._ExternalVariables);

                        this.UpdateInternalGradient();

                        // c          go back to the minimization routine.
                        Continue = true;
                    }
                    else if (TASK == BFGSTask.NEW_X)
                    {
                        Continue = true;
                    }
                    else
                    {
                        Continue = false;
                    }
                }
                else
                {
                    Continue = false;
                }
            }

            this.UpdateExternalVariables();

            nMax = funcEvaluations;

            return(this._ExternalVariables);
        }
Example #2
0
        public void Run(int N, int M, double FACTR, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
            , ref BFGSTask TASK, ref int INFO, ref int K)
        {
            #region Variables

            int I = 0;

            #endregion

            #region Array Index Correction

             int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;

            #endregion

            #region Prolog

            // c     ************
            // c
            // c     Subroutine errclb
            // c
            // c     This subroutine checks the validity of the input data.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************

            // c     Check the input arguments for errors.

            #endregion

            #region Body

             if (N <= 0) TASK = BFGSTask.ERROR;
             if (M <= 0) TASK = BFGSTask.ERROR;
             if (FACTR < ZERO) TASK = BFGSTask.ERROR;

            // c     Check the validity of the arrays nbd(i), u(i), and l(i).

            for (I = 1; I <= N; I++)
            {
                if (NBD[I + o_nbd] < 0 || NBD[I + o_nbd] > 3)
                {
                    // c                                                   return
                    //"ERROR: INVALID NBD";
                    TASK = BFGSTask.ERROR;
                    INFO =  - 6;
                    K = I;
                }
                if (NBD[I + o_nbd] == 2)
                {
                    if (L[I + o_l] > U[I + o_u])
                    {
                        // c                                    return
                        //"ERROR: NO FEASIBLE SOLUTION"
                        TASK = BFGSTask.ERROR;
                        INFO =  - 7;
                        K = I;
                    }
                }
            }

            return;

            #endregion
        }
Example #3
0
        /// <param name="F">
        /// is a double precision variable.
        /// On initial entry f is the value of the function at 0.
        /// On subsequent entries f is the value of the 
        /// function at stp.
        /// On exit f is the value of the function at stp.
        ///</param>
        /// <param name="G">
        /// is a double precision variable.
        /// On initial entry g is the derivative of the function at 0.
        /// On subsequent entries g is the derivative of the 
        /// function at stp.
        /// On exit g is the derivative of the function at stp.
        /// 
        /// stp is a double precision variable. 
        /// On entry stp is the current estimate of a satisfactory 
        /// step. On initial entry, a positive initial estimate 
        /// must be provided. 
        /// On exit stp is the current estimate of a satisfactory step
        /// if task = 'FG'. If task = 'CONV' then stp satisfies
        /// the sufficient decrease and curvature condition.
        /// 
        /// ftol is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the 
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        /// 
        /// gtol is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the 
        /// curvature condition. 
        /// On exit gtol is unchanged.
        /// 
        /// xtol is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        /// 
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        /// 
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        /// 
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        /// 
        /// If task(1:2) = 'FG' then evaluate the function and 
        /// derivative at stp and call dcsrch again.
        /// 
        /// If task(1:4) = 'CONV' then the search is successful.
        /// 
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        /// 
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        /// 
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        /// 
        /// isave is an integer work array of dimension 2.
        /// 
        /// dsave is a double precision work array of dimension 13.
        /// 
        /// Subprograms called
        /// 
        /// MINPACK-2 ... dcstep
        /// 
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory. 
        /// Jorge J. More' and David J. Thuente.
        /// 
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota. 
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
        /// 
        /// **********
        /// 
        /// 
        /// 
        /// 
        /// Initialization block.
        ///</param>
        /// <param name="STP">
        /// is a double precision variable. 
        /// On entry stp is the current estimate of a satisfactory 
        /// step. On initial entry, a positive initial estimate 
        /// must be provided. 
        /// On exit stp is the current estimate of a satisfactory step
        /// if task = 'FG'. If task = 'CONV' then stp satisfies
        /// the sufficient decrease and curvature condition.
        /// 
        /// ftol is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the 
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        /// 
        /// gtol is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the 
        /// curvature condition. 
        /// On exit gtol is unchanged.
        /// 
        /// xtol is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        /// 
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        /// 
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        /// 
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        /// 
        /// If task(1:2) = 'FG' then evaluate the function and 
        /// derivative at stp and call dcsrch again.
        /// 
        /// If task(1:4) = 'CONV' then the search is successful.
        /// 
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        /// 
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        /// 
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        /// 
        /// isave is an integer work array of dimension 2.
        /// 
        /// dsave is a double precision work array of dimension 13.
        /// 
        /// Subprograms called
        /// 
        /// MINPACK-2 ... dcstep
        /// 
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory. 
        /// Jorge J. More' and David J. Thuente.
        /// 
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota. 
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
        /// 
        /// **********
        /// 
        /// 
        /// 
        /// 
        /// Initialization block.
        ///</param>
        /// <param name="FTOL">
        /// is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the 
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        ///</param>
        /// <param name="GTOL">
        /// is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the 
        /// curvature condition. 
        /// On exit gtol is unchanged.
        ///</param>
        /// <param name="XTOL">
        /// is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        /// 
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        /// 
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        /// 
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        /// 
        /// If task(1:2) = 'FG' then evaluate the function and 
        /// derivative at stp and call dcsrch again.
        /// 
        /// If task(1:4) = 'CONV' then the search is successful.
        /// 
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        /// 
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        /// 
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        /// 
        /// isave is an integer work array of dimension 2.
        /// 
        /// dsave is a double precision work array of dimension 13.
        /// 
        /// Subprograms called
        /// 
        /// MINPACK-2 ... dcstep
        /// 
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory. 
        /// Jorge J. More' and David J. Thuente.
        /// 
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota. 
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
        /// 
        /// **********
        /// 
        /// 
        /// 
        /// 
        /// Initialization block.
        ///</param>
        /// <param name="STPMIN">
        /// is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        /// 
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        /// 
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        /// 
        /// If task(1:2) = 'FG' then evaluate the function and 
        /// derivative at stp and call dcsrch again.
        /// 
        /// If task(1:4) = 'CONV' then the search is successful.
        /// 
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        /// 
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        /// 
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        /// 
        /// isave is an integer work array of dimension 2.
        /// 
        /// dsave is a double precision work array of dimension 13.
        /// 
        /// Subprograms called
        /// 
        /// MINPACK-2 ... dcstep
        /// 
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory. 
        /// Jorge J. More' and David J. Thuente.
        /// 
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota. 
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
        /// 
        /// **********
        /// 
        /// 
        /// 
        /// 
        /// Initialization block.
        ///</param>
        /// <param name="STPMAX">
        /// is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        /// 
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        /// 
        /// If task(1:2) = 'FG' then evaluate the function and 
        /// derivative at stp and call dcsrch again.
        /// 
        /// If task(1:4) = 'CONV' then the search is successful.
        /// 
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        /// 
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        /// 
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        /// 
        /// isave is an integer work array of dimension 2.
        /// 
        /// dsave is a double precision work array of dimension 13.
        /// 
        /// Subprograms called
        /// 
        /// MINPACK-2 ... dcstep
        /// 
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory. 
        /// Jorge J. More' and David J. Thuente.
        /// 
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota. 
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'. 
        /// 
        /// **********
        /// 
        /// 
        /// 
        /// 
        /// Initialization block.
        ///</param>
        /// <param name="TASK">
        /// = 'START'
        ///</param>
        /// <param name="ISAVE">
        /// is an integer work array of dimension 2.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision work array of dimension 13.
        ///</param>
        public void Run(double F, double G, ref double STP, double FTOL, double GTOL, double XTOL
            , double STPMIN, double STPMAX, ref BFGSTask TASK, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            bool BRACKT = false; int STAGE = 0; double FINIT = 0; double FTEST = 0; double FM = 0; double FX = 0; double FXM = 0;
            double FY = 0;double FYM = 0; double GINIT = 0; double GTEST = 0; double GM = 0; double GX = 0; double GXM = 0;
            double GY = 0;double GYM = 0; double STX = 0; double STY = 0; double STMIN = 0; double STMAX = 0; double WIDTH = 0;
            double WIDTH1 = 0;

            #endregion

            #region Array Index Correction

             int o_isave = -1 + offset_isave;  int o_dsave = -1 + offset_dsave;

            #endregion

            #region Prolog

            // c     **********
            // c
            // c     Subroutine dcsrch
            // c
            // c     This subroutine finds a step that satisfies a sufficient
            // c     decrease condition and a curvature condition.
            // c
            // c     Each call of the subroutine updates an interval with
            // c     endpoints stx and sty. The interval is initially chosen
            // c     so that it contains a minimizer of the modified function
            // c
            // c           psi(stp) = f(stp) - f(0) - ftol*stp*f'(0).
            // c
            // c     If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
            // c     interval is chosen so that it contains a minimizer of f.
            // c
            // c     The algorithm is designed to find a step that satisfies
            // c     the sufficient decrease condition
            // c
            // c           f(stp) <= f(0) + ftol*stp*f'(0),
            // c
            // c     and the curvature condition
            // c
            // c           abs(f'(stp)) <= gtol*abs(f'(0)).
            // c
            // c     If ftol is less than gtol and if, for example, the function
            // c     is bounded below, then there is always a step which satisfies
            // c     both conditions.
            // c
            // c     If no step can be found that satisfies both conditions, then
            // c     the algorithm stops with a warning. In this case stp only
            // c     satisfies the sufficient decrease condition.
            // c
            // c     A typical invocation of dcsrch has the following outline:
            // c
            // c     task = 'START'
            // c  10 continue
            // c        call dcsrch( ... )
            // c        if (task .eq. 'FG') then
            // c           Evaluate the function and the gradient at stp
            // c           goto 10
            // c           end if
            // c
            // c     NOTE: The user must no alter work arrays between calls.
            // c
            // c     The subroutine statement is
            // c
            // c        subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax,
            // c                          task,isave,dsave)
            // c     where
            // c
            // c       f is a double precision variable.
            // c         On initial entry f is the value of the function at 0.
            // c            On subsequent entries f is the value of the
            // c            function at stp.
            // c         On exit f is the value of the function at stp.
            // c
            // c	g is a double precision variable.
            // c         On initial entry g is the derivative of the function at 0.
            // c            On subsequent entries g is the derivative of the
            // c            function at stp.
            // c         On exit g is the derivative of the function at stp.
            // c
            // c	stp is a double precision variable.
            // c         On entry stp is the current estimate of a satisfactory
            // c            step. On initial entry, a positive initial estimate
            // c            must be provided.
            // c         On exit stp is the current estimate of a satisfactory step
            // c            if task = 'FG'. If task = 'CONV' then stp satisfies
            // c            the sufficient decrease and curvature condition.
            // c
            // c       ftol is a double precision variable.
            // c         On entry ftol specifies a nonnegative tolerance for the
            // c            sufficient decrease condition.
            // c         On exit ftol is unchanged.
            // c
            // c       gtol is a double precision variable.
            // c         On entry gtol specifies a nonnegative tolerance for the
            // c            curvature condition.
            // c         On exit gtol is unchanged.
            // c
            // c	xtol is a double precision variable.
            // c         On entry xtol specifies a nonnegative relative tolerance
            // c            for an acceptable step. The subroutine exits with a
            // c            warning if the relative difference between sty and stx
            // c            is less than xtol.
            // c         On exit xtol is unchanged.
            // c
            // c	stpmin is a double precision variable.
            // c         On entry stpmin is a nonnegative lower bound for the step.
            // c         On exit stpmin is unchanged.
            // c
            // c	stpmax is a double precision variable.
            // c         On entry stpmax is a nonnegative upper bound for the step.
            // c         On exit stpmax is unchanged.
            // c
            // c       task is a character variable of length at least 60.
            // c         On initial entry task must be set to 'START'.
            // c         On exit task indicates the required action:
            // c
            // c            If task(1:2) = 'FG' then evaluate the function and
            // c            derivative at stp and call dcsrch again.
            // c
            // c            If task(1:4) = 'CONV' then the search is successful.
            // c
            // c            If task(1:4) = 'WARN' then the subroutine is not able
            // c            to satisfy the convergence conditions. The exit value of
            // c            stp contains the best point found during the search.
            // c
            // c            If task(1:5) = 'ERROR' then there is an error in the
            // c            input arguments.
            // c
            // c         On exit with convergence, a warning or an error, the
            // c            variable task contains additional information.
            // c
            // c       isave is an integer work array of dimension 2.
            // c
            // c       dsave is a double precision work array of dimension 13.
            // c
            // c     Subprograms called
            // c
            // c	MINPACK-2 ... dcstep
            // c
            // c     MINPACK-1 Project. June 1983.
            // c     Argonne National Laboratory.
            // c     Jorge J. More' and David J. Thuente.
            // c
            // c     MINPACK-2 Project. October 1993.
            // c     Argonne National Laboratory and University of Minnesota.
            // c     Brett M. Averick, Richard G. Carter, and Jorge J. More'.
            // c
            // c     **********

            // c     Initialization block.

            #endregion

            #region Body

             if (TASK == BFGSTask.START)
            {

                // c        Check the input arguments for errors.

                //if (STP < STPMIN) FortranLib.Copy(ref TASK , "ERROR: STP .LT. STPMIN");
                //if (STP > STPMAX) FortranLib.Copy(ref TASK , "ERROR: STP .GT. STPMAX");
                //if (G >= ZERO) FortranLib.Copy(ref TASK , "ERROR: INITIAL G .GE. ZERO");
                //if (FTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: FTOL .LT. ZERO");
                //if (GTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: GTOL .LT. ZERO");
                //if (XTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: XTOL .LT. ZERO");
                //if (STPMIN < ZERO) FortranLib.Copy(ref TASK , "ERROR: STPMIN .LT. ZERO");
                //if (STPMAX < STPMIN) FortranLib.Copy(ref TASK , "ERROR: STPMAX .LT. STPMIN");
                if (STP < STPMIN)
                {
                    TASK = BFGSTask.ERROR;;
                }
                if (STP > STPMAX)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (G >= ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (FTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (GTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (XTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (STPMIN < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (STPMAX < STPMIN)
                {
                    TASK = BFGSTask.ERROR;
                }

                // c        Exit if there are errors on input.

                if (TASK == BFGSTask.ERROR) return;

                // c        Initialize local variables.

                BRACKT = false;
                STAGE = 1;
                FINIT = F;
                GINIT = G;
                GTEST = FTOL * GINIT;
                WIDTH = STPMAX - STPMIN;
                WIDTH1 = WIDTH / P5;

                // c        The variables stx, fx, gx contain the values of the step,
                // c        function, and derivative at the best step.
                // c        The variables sty, fy, gy contain the value of the step,
                // c        function, and derivative at sty.
                // c        The variables stp, f, g contain the values of the step,
                // c        function, and derivative at stp.

                STX = ZERO;
                FX = FINIT;
                GX = GINIT;
                STY = ZERO;
                FY = FINIT;
                GY = GINIT;
                STMIN = ZERO;
                STMAX = STP + XTRAPU * STP;
                TASK = BFGSTask.FG;

                goto LABEL1000;

            }
            else
            {

                // c        Restore local variables.

                if (ISAVE[1 + o_isave] == 1)
                {
                    BRACKT = true;
                }
                else
                {
                    BRACKT = false;
                }
                STAGE = ISAVE[2 + o_isave];
                GINIT = DSAVE[1 + o_dsave];
                GTEST = DSAVE[2 + o_dsave];
                GX = DSAVE[3 + o_dsave];
                GY = DSAVE[4 + o_dsave];
                FINIT = DSAVE[5 + o_dsave];
                FX = DSAVE[6 + o_dsave];
                FY = DSAVE[7 + o_dsave];
                STX = DSAVE[8 + o_dsave];
                STY = DSAVE[9 + o_dsave];
                STMIN = DSAVE[10 + o_dsave];
                STMAX = DSAVE[11 + o_dsave];
                WIDTH = DSAVE[12 + o_dsave];
                WIDTH1 = DSAVE[13 + o_dsave];

            }

            // c     If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
            // c     algorithm enters the second stage.

            FTEST = FINIT + STP * GTEST;
            if (STAGE == 1 && F <= FTEST && G >= ZERO) STAGE = 2;

            // c     Test for warnings.

            //if (BRACKT && (STP <= STMIN || STP >= STMAX)) FortranLib.Copy(ref TASK , "WARNING: ROUNDING ERRORS PREVENT PROGRESS");
            //if (BRACKT && STMAX - STMIN <= XTOL * STMAX) FortranLib.Copy(ref TASK , "WARNING: XTOL TEST SATISFIED");
            //if (STP == STPMAX && F <= FTEST && G <= GTEST) FortranLib.Copy(ref TASK , "WARNING: STP = STPMAX");
            //if (STP == STPMIN && (F > FTEST || G >= GTEST)) FortranLib.Copy(ref TASK , "WARNING: STP = STPMIN");
            if (BRACKT && (STP <= STMIN || STP >= STMAX))
            {
                TASK = BFGSTask.WARNING;
            }
            if (BRACKT && STMAX - STMIN <= XTOL * STMAX)
            {
                TASK = BFGSTask.WARNING;
            }
            if (STP == STPMAX && F <= FTEST && G <= GTEST)
            {
                TASK = BFGSTask.WARNING;
            }
            if (STP == STPMIN && (F > FTEST || G >= GTEST))
            {
                TASK = BFGSTask.WARNING;
            }
            // c     Test for convergence.

            if (F <= FTEST && Math.Abs(G) <= GTOL * (-GINIT)) TASK = BFGSTask.CONV;

            // c     Test for termination.

            if (TASK == BFGSTask.WARNING || TASK == BFGSTask.CONV) goto LABEL1000;

            // c     A modified function is used to predict the step during the
            // c     first stage if a lower function value has been obtained but
            // c     the decrease is not sufficient.

            if (STAGE == 1 && F <= FX && F > FTEST)
            {

                // c        Define the modified function and derivative values.

                FM = F - STP * GTEST;
                FXM = FX - STX * GTEST;
                FYM = FY - STY * GTEST;
                GM = G - GTEST;
                GXM = GX - GTEST;
                GYM = GY - GTEST;

                // c        Call dcstep to update stx, sty, and to compute the new step.

                this._dcstep.Run(ref STX, ref FXM, ref GXM, ref STY, ref FYM, ref GYM
                                 , ref STP, FM, GM, ref BRACKT, STMIN, STMAX);

                // c        Reset the function and derivative values for f.

                FX = FXM + STX * GTEST;
                FY = FYM + STY * GTEST;
                GX = GXM + GTEST;
                GY = GYM + GTEST;

            }
            else
            {

                // c       Call dcstep to update stx, sty, and to compute the new step.

                this._dcstep.Run(ref STX, ref FX, ref GX, ref STY, ref FY, ref GY
                                 , ref STP, F, G, ref BRACKT, STMIN, STMAX);

            }

            // c     Decide if a bisection step is needed.

            if (BRACKT)
            {
                if (Math.Abs(STY - STX) >= P66 * WIDTH1) STP = STX + P5 * (STY - STX);
                WIDTH1 = WIDTH;
                WIDTH = Math.Abs(STY - STX);
            }

            // c     Set the minimum and maximum steps allowed for stp.

            if (BRACKT)
            {
                STMIN = Math.Min(STX, STY);
                STMAX = Math.Max(STX, STY);
            }
            else
            {
                STMIN = STP + XTRAPL * (STP - STX);
                STMAX = STP + XTRAPU * (STP - STX);
            }

            // c     Force the step to be within the bounds stpmax and stpmin.

            STP = Math.Max(STP, STPMIN);
            STP = Math.Min(STP, STPMAX);

            // c     If further progress is not possible, let stp be the best
            // c     point obtained during the search.

            if (BRACKT && (STP <= STMIN || STP >= STMAX) || (BRACKT && STMAX - STMIN <= XTOL * STMAX)) STP = STX;

            // c     Obtain another function and derivative.

            TASK = BFGSTask.FG;

            LABEL1000:;

            // c     Save local variables.

            if (BRACKT)
            {
                ISAVE[1 + o_isave] = 1;
            }
            else
            {
                ISAVE[1 + o_isave] = 0;
            }
            ISAVE[2 + o_isave] = STAGE;
            DSAVE[1 + o_dsave] = GINIT;
            DSAVE[2 + o_dsave] = GTEST;
            DSAVE[3 + o_dsave] = GX;
            DSAVE[4 + o_dsave] = GY;
            DSAVE[5 + o_dsave] = FINIT;
            DSAVE[6 + o_dsave] = FX;
            DSAVE[7 + o_dsave] = FY;
            DSAVE[8 + o_dsave] = STX;
            DSAVE[9 + o_dsave] = STY;
            DSAVE[10 + o_dsave] = STMIN;
            DSAVE[11 + o_dsave] = STMAX;
            DSAVE[12 + o_dsave] = WIDTH;
            DSAVE[13 + o_dsave] = WIDTH1;

            #endregion
        }
Example #4
0
        public void Run(int N, int M, double FACTR, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
                        , ref BFGSTask TASK, ref int INFO, ref int K)
        {
            #region Variables

            int I = 0;

            #endregion


            #region Array Index Correction

            int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine errclb
            // c
            // c     This subroutine checks the validity of the input data.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************


            // c     Check the input arguments for errors.


            #endregion


            #region Body

            if (N <= 0)
            {
                TASK = BFGSTask.ERROR;
            }
            if (M <= 0)
            {
                TASK = BFGSTask.ERROR;
            }
            if (FACTR < ZERO)
            {
                TASK = BFGSTask.ERROR;
            }

            // c     Check the validity of the arrays nbd(i), u(i), and l(i).

            for (I = 1; I <= N; I++)
            {
                if (NBD[I + o_nbd] < 0 || NBD[I + o_nbd] > 3)
                {
                    // c                                                   return
                    //"ERROR: INVALID NBD";
                    TASK = BFGSTask.ERROR;
                    INFO = -6;
                    K    = I;
                }
                if (NBD[I + o_nbd] == 2)
                {
                    if (L[I + o_l] > U[I + o_u])
                    {
                        // c                                    return
                        //"ERROR: NO FEASIBLE SOLUTION"
                        TASK = BFGSTask.ERROR;
                        INFO = -7;
                        K    = I;
                    }
                }
            }

            return;


            #endregion
        }
Example #5
0
        /// <param name="F">
        /// is a double precision variable.
        /// On initial entry f is the value of the function at 0.
        /// On subsequent entries f is the value of the
        /// function at stp.
        /// On exit f is the value of the function at stp.
        ///</param>
        /// <param name="G">
        /// is a double precision variable.
        /// On initial entry g is the derivative of the function at 0.
        /// On subsequent entries g is the derivative of the
        /// function at stp.
        /// On exit g is the derivative of the function at stp.
        ///
        /// stp is a double precision variable.
        /// On entry stp is the current estimate of a satisfactory
        /// step. On initial entry, a positive initial estimate
        /// must be provided.
        /// On exit stp is the current estimate of a satisfactory step
        /// if task = 'FG'. If task = 'CONV' then stp satisfies
        /// the sufficient decrease and curvature condition.
        ///
        /// ftol is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        ///
        /// gtol is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the
        /// curvature condition.
        /// On exit gtol is unchanged.
        ///
        /// xtol is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        ///
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        ///
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        ///
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        ///
        /// If task(1:2) = 'FG' then evaluate the function and
        /// derivative at stp and call dcsrch again.
        ///
        /// If task(1:4) = 'CONV' then the search is successful.
        ///
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        ///
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        ///
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        ///
        /// isave is an integer work array of dimension 2.
        ///
        /// dsave is a double precision work array of dimension 13.
        ///
        /// Subprograms called
        ///
        /// MINPACK-2 ... dcstep
        ///
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory.
        /// Jorge J. More' and David J. Thuente.
        ///
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota.
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'.
        ///
        /// **********
        ///
        ///
        ///
        ///
        /// Initialization block.
        ///</param>
        /// <param name="STP">
        /// is a double precision variable.
        /// On entry stp is the current estimate of a satisfactory
        /// step. On initial entry, a positive initial estimate
        /// must be provided.
        /// On exit stp is the current estimate of a satisfactory step
        /// if task = 'FG'. If task = 'CONV' then stp satisfies
        /// the sufficient decrease and curvature condition.
        ///
        /// ftol is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        ///
        /// gtol is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the
        /// curvature condition.
        /// On exit gtol is unchanged.
        ///
        /// xtol is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        ///
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        ///
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        ///
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        ///
        /// If task(1:2) = 'FG' then evaluate the function and
        /// derivative at stp and call dcsrch again.
        ///
        /// If task(1:4) = 'CONV' then the search is successful.
        ///
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        ///
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        ///
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        ///
        /// isave is an integer work array of dimension 2.
        ///
        /// dsave is a double precision work array of dimension 13.
        ///
        /// Subprograms called
        ///
        /// MINPACK-2 ... dcstep
        ///
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory.
        /// Jorge J. More' and David J. Thuente.
        ///
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota.
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'.
        ///
        /// **********
        ///
        ///
        ///
        ///
        /// Initialization block.
        ///</param>
        /// <param name="FTOL">
        /// is a double precision variable.
        /// On entry ftol specifies a nonnegative tolerance for the
        /// sufficient decrease condition.
        /// On exit ftol is unchanged.
        ///</param>
        /// <param name="GTOL">
        /// is a double precision variable.
        /// On entry gtol specifies a nonnegative tolerance for the
        /// curvature condition.
        /// On exit gtol is unchanged.
        ///</param>
        /// <param name="XTOL">
        /// is a double precision variable.
        /// On entry xtol specifies a nonnegative relative tolerance
        /// for an acceptable step. The subroutine exits with a
        /// warning if the relative difference between sty and stx
        /// is less than xtol.
        /// On exit xtol is unchanged.
        ///
        /// stpmin is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        ///
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        ///
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        ///
        /// If task(1:2) = 'FG' then evaluate the function and
        /// derivative at stp and call dcsrch again.
        ///
        /// If task(1:4) = 'CONV' then the search is successful.
        ///
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        ///
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        ///
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        ///
        /// isave is an integer work array of dimension 2.
        ///
        /// dsave is a double precision work array of dimension 13.
        ///
        /// Subprograms called
        ///
        /// MINPACK-2 ... dcstep
        ///
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory.
        /// Jorge J. More' and David J. Thuente.
        ///
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota.
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'.
        ///
        /// **********
        ///
        ///
        ///
        ///
        /// Initialization block.
        ///</param>
        /// <param name="STPMIN">
        /// is a double precision variable.
        /// On entry stpmin is a nonnegative lower bound for the step.
        /// On exit stpmin is unchanged.
        ///
        /// stpmax is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        ///
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        ///
        /// If task(1:2) = 'FG' then evaluate the function and
        /// derivative at stp and call dcsrch again.
        ///
        /// If task(1:4) = 'CONV' then the search is successful.
        ///
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        ///
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        ///
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        ///
        /// isave is an integer work array of dimension 2.
        ///
        /// dsave is a double precision work array of dimension 13.
        ///
        /// Subprograms called
        ///
        /// MINPACK-2 ... dcstep
        ///
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory.
        /// Jorge J. More' and David J. Thuente.
        ///
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota.
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'.
        ///
        /// **********
        ///
        ///
        ///
        ///
        /// Initialization block.
        ///</param>
        /// <param name="STPMAX">
        /// is a double precision variable.
        /// On entry stpmax is a nonnegative upper bound for the step.
        /// On exit stpmax is unchanged.
        ///
        /// task is a character variable of length at least 60.
        /// On initial entry task must be set to 'START'.
        /// On exit task indicates the required action:
        ///
        /// If task(1:2) = 'FG' then evaluate the function and
        /// derivative at stp and call dcsrch again.
        ///
        /// If task(1:4) = 'CONV' then the search is successful.
        ///
        /// If task(1:4) = 'WARN' then the subroutine is not able
        /// to satisfy the convergence conditions. The exit value of
        /// stp contains the best point found during the search.
        ///
        /// If task(1:5) = 'ERROR' then there is an error in the
        /// input arguments.
        ///
        /// On exit with convergence, a warning or an error, the
        /// variable task contains additional information.
        ///
        /// isave is an integer work array of dimension 2.
        ///
        /// dsave is a double precision work array of dimension 13.
        ///
        /// Subprograms called
        ///
        /// MINPACK-2 ... dcstep
        ///
        /// MINPACK-1 Project. June 1983.
        /// Argonne National Laboratory.
        /// Jorge J. More' and David J. Thuente.
        ///
        /// MINPACK-2 Project. October 1993.
        /// Argonne National Laboratory and University of Minnesota.
        /// Brett M. Averick, Richard G. Carter, and Jorge J. More'.
        ///
        /// **********
        ///
        ///
        ///
        ///
        /// Initialization block.
        ///</param>
        /// <param name="TASK">
        /// = 'START'
        ///</param>
        /// <param name="ISAVE">
        /// is an integer work array of dimension 2.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision work array of dimension 13.
        ///</param>
        public void Run(double F, double G, ref double STP, double FTOL, double GTOL, double XTOL
                        , double STPMIN, double STPMAX, ref BFGSTask TASK, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            bool   BRACKT = false; int STAGE = 0; double FINIT = 0; double FTEST = 0; double FM = 0; double FX = 0; double FXM = 0;
            double FY = 0; double FYM = 0; double GINIT = 0; double GTEST = 0; double GM = 0; double GX = 0; double GXM = 0;
            double GY = 0; double GYM = 0; double STX = 0; double STY = 0; double STMIN = 0; double STMAX = 0; double WIDTH = 0;
            double WIDTH1 = 0;

            #endregion


            #region Array Index Correction

            int o_isave = -1 + offset_isave;  int o_dsave = -1 + offset_dsave;

            #endregion


            #region Prolog

            // c     **********
            // c
            // c     Subroutine dcsrch
            // c
            // c     This subroutine finds a step that satisfies a sufficient
            // c     decrease condition and a curvature condition.
            // c
            // c     Each call of the subroutine updates an interval with
            // c     endpoints stx and sty. The interval is initially chosen
            // c     so that it contains a minimizer of the modified function
            // c
            // c           psi(stp) = f(stp) - f(0) - ftol*stp*f'(0).
            // c
            // c     If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
            // c     interval is chosen so that it contains a minimizer of f.
            // c
            // c     The algorithm is designed to find a step that satisfies
            // c     the sufficient decrease condition
            // c
            // c           f(stp) <= f(0) + ftol*stp*f'(0),
            // c
            // c     and the curvature condition
            // c
            // c           abs(f'(stp)) <= gtol*abs(f'(0)).
            // c
            // c     If ftol is less than gtol and if, for example, the function
            // c     is bounded below, then there is always a step which satisfies
            // c     both conditions.
            // c
            // c     If no step can be found that satisfies both conditions, then
            // c     the algorithm stops with a warning. In this case stp only
            // c     satisfies the sufficient decrease condition.
            // c
            // c     A typical invocation of dcsrch has the following outline:
            // c
            // c     task = 'START'
            // c  10 continue
            // c        call dcsrch( ... )
            // c        if (task .eq. 'FG') then
            // c           Evaluate the function and the gradient at stp
            // c           goto 10
            // c           end if
            // c
            // c     NOTE: The user must no alter work arrays between calls.
            // c
            // c     The subroutine statement is
            // c
            // c        subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax,
            // c                          task,isave,dsave)
            // c     where
            // c
            // c       f is a double precision variable.
            // c         On initial entry f is the value of the function at 0.
            // c            On subsequent entries f is the value of the
            // c            function at stp.
            // c         On exit f is the value of the function at stp.
            // c
            // c	g is a double precision variable.
            // c         On initial entry g is the derivative of the function at 0.
            // c            On subsequent entries g is the derivative of the
            // c            function at stp.
            // c         On exit g is the derivative of the function at stp.
            // c
            // c	stp is a double precision variable.
            // c         On entry stp is the current estimate of a satisfactory
            // c            step. On initial entry, a positive initial estimate
            // c            must be provided.
            // c         On exit stp is the current estimate of a satisfactory step
            // c            if task = 'FG'. If task = 'CONV' then stp satisfies
            // c            the sufficient decrease and curvature condition.
            // c
            // c       ftol is a double precision variable.
            // c         On entry ftol specifies a nonnegative tolerance for the
            // c            sufficient decrease condition.
            // c         On exit ftol is unchanged.
            // c
            // c       gtol is a double precision variable.
            // c         On entry gtol specifies a nonnegative tolerance for the
            // c            curvature condition.
            // c         On exit gtol is unchanged.
            // c
            // c	xtol is a double precision variable.
            // c         On entry xtol specifies a nonnegative relative tolerance
            // c            for an acceptable step. The subroutine exits with a
            // c            warning if the relative difference between sty and stx
            // c            is less than xtol.
            // c         On exit xtol is unchanged.
            // c
            // c	stpmin is a double precision variable.
            // c         On entry stpmin is a nonnegative lower bound for the step.
            // c         On exit stpmin is unchanged.
            // c
            // c	stpmax is a double precision variable.
            // c         On entry stpmax is a nonnegative upper bound for the step.
            // c         On exit stpmax is unchanged.
            // c
            // c       task is a character variable of length at least 60.
            // c         On initial entry task must be set to 'START'.
            // c         On exit task indicates the required action:
            // c
            // c            If task(1:2) = 'FG' then evaluate the function and
            // c            derivative at stp and call dcsrch again.
            // c
            // c            If task(1:4) = 'CONV' then the search is successful.
            // c
            // c            If task(1:4) = 'WARN' then the subroutine is not able
            // c            to satisfy the convergence conditions. The exit value of
            // c            stp contains the best point found during the search.
            // c
            // c            If task(1:5) = 'ERROR' then there is an error in the
            // c            input arguments.
            // c
            // c         On exit with convergence, a warning or an error, the
            // c            variable task contains additional information.
            // c
            // c       isave is an integer work array of dimension 2.
            // c
            // c       dsave is a double precision work array of dimension 13.
            // c
            // c     Subprograms called
            // c
            // c	MINPACK-2 ... dcstep
            // c
            // c     MINPACK-1 Project. June 1983.
            // c     Argonne National Laboratory.
            // c     Jorge J. More' and David J. Thuente.
            // c
            // c     MINPACK-2 Project. October 1993.
            // c     Argonne National Laboratory and University of Minnesota.
            // c     Brett M. Averick, Richard G. Carter, and Jorge J. More'.
            // c
            // c     **********



            // c     Initialization block.


            #endregion


            #region Body

            if (TASK == BFGSTask.START)
            {
                // c        Check the input arguments for errors.

                //if (STP < STPMIN) FortranLib.Copy(ref TASK , "ERROR: STP .LT. STPMIN");
                //if (STP > STPMAX) FortranLib.Copy(ref TASK , "ERROR: STP .GT. STPMAX");
                //if (G >= ZERO) FortranLib.Copy(ref TASK , "ERROR: INITIAL G .GE. ZERO");
                //if (FTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: FTOL .LT. ZERO");
                //if (GTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: GTOL .LT. ZERO");
                //if (XTOL < ZERO) FortranLib.Copy(ref TASK , "ERROR: XTOL .LT. ZERO");
                //if (STPMIN < ZERO) FortranLib.Copy(ref TASK , "ERROR: STPMIN .LT. ZERO");
                //if (STPMAX < STPMIN) FortranLib.Copy(ref TASK , "ERROR: STPMAX .LT. STPMIN");
                if (STP < STPMIN)
                {
                    TASK = BFGSTask.ERROR;;
                }
                if (STP > STPMAX)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (G >= ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (FTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (GTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (XTOL < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (STPMIN < ZERO)
                {
                    TASK = BFGSTask.ERROR;
                }
                if (STPMAX < STPMIN)
                {
                    TASK = BFGSTask.ERROR;
                }

                // c        Exit if there are errors on input.

                if (TASK == BFGSTask.ERROR)
                {
                    return;
                }

                // c        Initialize local variables.

                BRACKT = false;
                STAGE  = 1;
                FINIT  = F;
                GINIT  = G;
                GTEST  = FTOL * GINIT;
                WIDTH  = STPMAX - STPMIN;
                WIDTH1 = WIDTH / P5;

                // c        The variables stx, fx, gx contain the values of the step,
                // c        function, and derivative at the best step.
                // c        The variables sty, fy, gy contain the value of the step,
                // c        function, and derivative at sty.
                // c        The variables stp, f, g contain the values of the step,
                // c        function, and derivative at stp.

                STX   = ZERO;
                FX    = FINIT;
                GX    = GINIT;
                STY   = ZERO;
                FY    = FINIT;
                GY    = GINIT;
                STMIN = ZERO;
                STMAX = STP + XTRAPU * STP;
                TASK  = BFGSTask.FG;

                goto LABEL1000;
            }
            else
            {
                // c        Restore local variables.

                if (ISAVE[1 + o_isave] == 1)
                {
                    BRACKT = true;
                }
                else
                {
                    BRACKT = false;
                }
                STAGE  = ISAVE[2 + o_isave];
                GINIT  = DSAVE[1 + o_dsave];
                GTEST  = DSAVE[2 + o_dsave];
                GX     = DSAVE[3 + o_dsave];
                GY     = DSAVE[4 + o_dsave];
                FINIT  = DSAVE[5 + o_dsave];
                FX     = DSAVE[6 + o_dsave];
                FY     = DSAVE[7 + o_dsave];
                STX    = DSAVE[8 + o_dsave];
                STY    = DSAVE[9 + o_dsave];
                STMIN  = DSAVE[10 + o_dsave];
                STMAX  = DSAVE[11 + o_dsave];
                WIDTH  = DSAVE[12 + o_dsave];
                WIDTH1 = DSAVE[13 + o_dsave];
            }

            // c     If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the
            // c     algorithm enters the second stage.

            FTEST = FINIT + STP * GTEST;
            if (STAGE == 1 && F <= FTEST && G >= ZERO)
            {
                STAGE = 2;
            }

            // c     Test for warnings.

            //if (BRACKT && (STP <= STMIN || STP >= STMAX)) FortranLib.Copy(ref TASK , "WARNING: ROUNDING ERRORS PREVENT PROGRESS");
            //if (BRACKT && STMAX - STMIN <= XTOL * STMAX) FortranLib.Copy(ref TASK , "WARNING: XTOL TEST SATISFIED");
            //if (STP == STPMAX && F <= FTEST && G <= GTEST) FortranLib.Copy(ref TASK , "WARNING: STP = STPMAX");
            //if (STP == STPMIN && (F > FTEST || G >= GTEST)) FortranLib.Copy(ref TASK , "WARNING: STP = STPMIN");
            if (BRACKT && (STP <= STMIN || STP >= STMAX))
            {
                TASK = BFGSTask.WARNING;
            }
            if (BRACKT && STMAX - STMIN <= XTOL * STMAX)
            {
                TASK = BFGSTask.WARNING;
            }
            if (STP == STPMAX && F <= FTEST && G <= GTEST)
            {
                TASK = BFGSTask.WARNING;
            }
            if (STP == STPMIN && (F > FTEST || G >= GTEST))
            {
                TASK = BFGSTask.WARNING;
            }
            // c     Test for convergence.

            if (F <= FTEST && Math.Abs(G) <= GTOL * (-GINIT))
            {
                TASK = BFGSTask.CONV;
            }

            // c     Test for termination.

            if (TASK == BFGSTask.WARNING || TASK == BFGSTask.CONV)
            {
                goto LABEL1000;
            }

            // c     A modified function is used to predict the step during the
            // c     first stage if a lower function value has been obtained but
            // c     the decrease is not sufficient.

            if (STAGE == 1 && F <= FX && F > FTEST)
            {
                // c        Define the modified function and derivative values.

                FM  = F - STP * GTEST;
                FXM = FX - STX * GTEST;
                FYM = FY - STY * GTEST;
                GM  = G - GTEST;
                GXM = GX - GTEST;
                GYM = GY - GTEST;

                // c        Call dcstep to update stx, sty, and to compute the new step.

                this._dcstep.Run(ref STX, ref FXM, ref GXM, ref STY, ref FYM, ref GYM
                                 , ref STP, FM, GM, ref BRACKT, STMIN, STMAX);

                // c        Reset the function and derivative values for f.

                FX = FXM + STX * GTEST;
                FY = FYM + STY * GTEST;
                GX = GXM + GTEST;
                GY = GYM + GTEST;
            }
            else
            {
                // c       Call dcstep to update stx, sty, and to compute the new step.

                this._dcstep.Run(ref STX, ref FX, ref GX, ref STY, ref FY, ref GY
                                 , ref STP, F, G, ref BRACKT, STMIN, STMAX);
            }

            // c     Decide if a bisection step is needed.

            if (BRACKT)
            {
                if (Math.Abs(STY - STX) >= P66 * WIDTH1)
                {
                    STP = STX + P5 * (STY - STX);
                }
                WIDTH1 = WIDTH;
                WIDTH  = Math.Abs(STY - STX);
            }

            // c     Set the minimum and maximum steps allowed for stp.

            if (BRACKT)
            {
                STMIN = Math.Min(STX, STY);
                STMAX = Math.Max(STX, STY);
            }
            else
            {
                STMIN = STP + XTRAPL * (STP - STX);
                STMAX = STP + XTRAPU * (STP - STX);
            }

            // c     Force the step to be within the bounds stpmax and stpmin.

            STP = Math.Max(STP, STPMIN);
            STP = Math.Min(STP, STPMAX);

            // c     If further progress is not possible, let stp be the best
            // c     point obtained during the search.

            if (BRACKT && (STP <= STMIN || STP >= STMAX) || (BRACKT && STMAX - STMIN <= XTOL * STMAX))
            {
                STP = STX;
            }

            // c     Obtain another function and derivative.

            TASK = BFGSTask.FG;

            LABEL1000 :;

            // c     Save local variables.

            if (BRACKT)
            {
                ISAVE[1 + o_isave] = 1;
            }
            else
            {
                ISAVE[1 + o_isave] = 0;
            }
            ISAVE[2 + o_isave]  = STAGE;
            DSAVE[1 + o_dsave]  = GINIT;
            DSAVE[2 + o_dsave]  = GTEST;
            DSAVE[3 + o_dsave]  = GX;
            DSAVE[4 + o_dsave]  = GY;
            DSAVE[5 + o_dsave]  = FINIT;
            DSAVE[6 + o_dsave]  = FX;
            DSAVE[7 + o_dsave]  = FY;
            DSAVE[8 + o_dsave]  = STX;
            DSAVE[9 + o_dsave]  = STY;
            DSAVE[10 + o_dsave] = STMIN;
            DSAVE[11 + o_dsave] = STMAX;
            DSAVE[12 + o_dsave] = WIDTH;
            DSAVE[13 + o_dsave] = WIDTH1;


            #endregion
        }
Example #6
0
        public void Run(int N, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd, ref double[] X, int offset_x, double F
            , ref double FOLD, ref double GD, ref double GDOLD, double[] G, int offset_g, double[] D, int offset_d, ref double[] R, int offset_r
            , ref double[] T, int offset_t, double[] Z, int offset_z, ref double STP, ref double DNORM, ref double DTD, ref double XSTEP
            , ref double STPMX, int ITER, ref int IFUN, ref int IBACK, ref int NFGV, ref int INFO
            , ref BFGSTask TASK, bool BOXED, bool CNSTND, ref BFGSTask CSAVE, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            int I = 0; double DDOT = 0; double A1 = 0; double A2 = 0;

            #endregion

            #region Array Index Correction

             int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;  int o_x = -1 + offset_x;
             int o_g = -1 + offset_g; int o_d = -1 + offset_d;  int o_r = -1 + offset_r;  int o_t = -1 + offset_t;
             int o_z = -1 + offset_z; int o_isave = -1 + offset_isave;  int o_dsave = -1 + offset_dsave;

            #endregion

            #region Prolog

            // c     **********
            // c
            // c     Subroutine lnsrlb
            // c
            // c     This subroutine calls subroutine dcsrch from the Minpack2 library
            // c       to perform the line search.  Subroutine dscrch is safeguarded so
            // c       that all trial points lie within the feasible region.
            // c
            // c     Subprograms called:
            // c
            // c       Minpack2 Library ... dcsrch.
            // c
            // c       Linpack ... dtrsl, ddot.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     **********

            #endregion

            #region Body

            if (TASK == BFGSTask.FG_LNSRCH) goto LABEL556;

            DTD = this._ddot.Run(N, D, offset_d, 1, D, offset_d, 1);
            DNORM = Math.Sqrt(DTD);

            // c     Determine the maximum step length.

            STPMX = BIG;
            if (CNSTND)
            {
                if (ITER == 0)
                {
                    STPMX = ONE;
                }
                else
                {
                    for (I = 1; I <= N; I++)
                    {
                        A1 = D[I + o_d];
                        if (NBD[I + o_nbd] != 0)
                        {
                            if (A1 < ZERO && NBD[I + o_nbd] <= 2)
                            {
                                A2 = L[I + o_l] - X[I + o_x];
                                if (A2 >= ZERO)
                                {
                                    STPMX = ZERO;
                                }
                                else
                                {
                                    if (A1 * STPMX < A2)
                                    {
                                        STPMX = A2 / A1;
                                    }
                                }
                            }
                            else
                            {
                                if (A1 > ZERO && NBD[I + o_nbd] >= 2)
                                {
                                    A2 = U[I + o_u] - X[I + o_x];
                                    if (A2 <= ZERO)
                                    {
                                        STPMX = ZERO;
                                    }
                                    else
                                    {
                                        if (A1 * STPMX > A2)
                                        {
                                            STPMX = A2 / A1;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (ITER == 0 && !BOXED)
            {
                STP = Math.Min(ONE / DNORM, STPMX);
            }
            else
            {
                STP = ONE;
            }

            this._dcopy.Run(N, X, offset_x, 1, ref T, offset_t, 1);
            this._dcopy.Run(N, G, offset_g, 1, ref R, offset_r, 1);
            FOLD = F;
            IFUN = 0;
            IBACK = 0;
            CSAVE = BFGSTask.START;
            LABEL556:;
            GD = this._ddot.Run(N, G, offset_g, 1, D, offset_d, 1);
            if (IFUN == 0)
            {
                GDOLD = GD;
                if (GD >= ZERO)
                {
                    // c                               the directional derivative >=0.
                    // c                               Line search is impossible.
                    INFO =  - 4;
                    return;
                }
            }

            this._dcsrch.Run(F, GD, ref STP, FTOL, GTOL, XTOL
                             , ZERO, STPMX, ref CSAVE, ref ISAVE, offset_isave, ref DSAVE, offset_dsave);

            XSTEP = STP * DNORM;
            if (CSAVE != BFGSTask.CONV && CSAVE != BFGSTask.WARNING)
            {
                TASK = BFGSTask.FG_LNSRCH;
                IFUN += 1;
                NFGV += 1;
                IBACK = IFUN - 1;
                if (STP == ONE)
                {
                    this._dcopy.Run(N, Z, offset_z, 1, ref X, offset_x, 1);
                }
                else
                {
                    for (I = 1; I <= N; I++)
                    {
                        X[I + o_x] = STP * D[I + o_d] + T[I + o_t];
                    }
                }
            }
            else
            {
                TASK = BFGSTask.NEW_X;
            }

            return;

            #endregion
        }
Example #7
0
        public void Run(int N, double[] X, int offset_x, double F, BFGSTask TASK, int IPRINT, int INFO
                        , int ITFILE, int ITER, int NFGV, int NINTOL, int NSKIP, int NACT
                        , double SBGNRM, double TIME, int NINT, BFGSWord WORD, int IBACK, double STP
                        , double XSTEP, int K, double CACHYT, double SBTIME, double LNSCHT)
        {
            #region Variables

            int I = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine prn3lb
            // c
            // c     This subroutine prints out information when either a built-in
            // c       convergence test is satisfied or when an error message is
            // c       generated.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            #endregion


            #region Body

            if (TASK == BFGSTask.ERROR)
            {
                goto LABEL999;
            }

            if (IPRINT >= 0)
            {
                //ERROR-ERROR         WRITE (6,3003);
                //ERROR-ERROR         WRITE (6,3004);
                //ERROR-ERROR         WRITE(6,3005) N,ITER,NFGV,NINTOL,NSKIP,NACT,SBGNRM,F;
                if (IPRINT >= 100)
                {
                    //ERROR-ERROR            WRITE (6,1004) 'X =',(X(I),I = 1,N);
                }
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,*)' F =',F
                }
            }
            LABEL999 :;
            if (IPRINT >= 0)
            {
                //ERROR-ERROR         WRITE (6,3009) TASK;
                if (INFO != 0)
                {
                    if (INFO == -1)
                    {
                        ;              //ERROR-ERRORWRITE(6,9011)
                    }
                    if (INFO == -2)
                    {
                        ;              //ERROR-ERRORWRITE(6,9012)
                    }
                    if (INFO == -3)
                    {
                        ;              //ERROR-ERRORWRITE(6,9013)
                    }
                    if (INFO == -4)
                    {
                        ;              //ERROR-ERRORWRITE(6,9014)
                    }
                    if (INFO == -5)
                    {
                        ;              //ERROR-ERRORWRITE(6,9015)
                    }
                    if (INFO == -6)
                    {
                        ;              //ERROR-ERRORWRITE(6,*)' Input nbd(',K,') is invalid.'
                    }
                    if (INFO == -7)
                    {
                        ;              //ERROR-ERRORWRITE(6,*)' l(',K,') > u(',K,').  No feasible solution.'
                    }
                    if (INFO == -8)
                    {
                        ;              //ERROR-ERRORWRITE(6,9018)
                    }
                    if (INFO == -9)
                    {
                        ;              //ERROR-ERRORWRITE(6,9019)
                    }
                }
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,3007)CACHYT,SBTIME,LNSCHT
                }
                //ERROR-ERROR         WRITE (6,3008) TIME;
                if (IPRINT >= 1)
                {
                    if (INFO == -4 || INFO == -9)
                    {
                        //ERROR-ERROR               WRITE (ITFILE,3002)ITER,NFGV,NINT,NACT,WORD,IBACK,STP,XSTEP;
                    }
                    //ERROR-ERROR            WRITE (ITFILE,3009) TASK;
                    if (INFO != 0)
                    {
                        if (INFO == -1)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9011)
                        }
                        if (INFO == -2)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9012)
                        }
                        if (INFO == -3)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9013)
                        }
                        if (INFO == -4)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9014)
                        }
                        if (INFO == -5)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9015)
                        }
                        if (INFO == -8)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9018)
                        }
                        if (INFO == -9)
                        {
                            ;              //ERROR-ERRORWRITE(ITFILE,9019)
                        }
                    }
                    //ERROR-ERROR            WRITE (ITFILE,3008) TIME;
                }
            }


            return;


            #endregion
        }
Example #8
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the number of variables.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric
        /// corrections allowed in the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x is an approximation to the solution.
        /// On exit x is the current approximation.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound of x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound of x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is an integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds,
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="F">
        /// is a double precision variable.
        /// On first entry f is unspecified.
        /// On final exit f is the value of the function at x.
        ///</param>
        /// <param name="G">
        /// is a double precision array of dimension n.
        /// On first entry g is unspecified.
        /// On final exit g is the value of the gradient at x.
        ///</param>
        /// <param name="FACTR">
        /// is a double precision variable.
        /// On entry factr .GE. 0 is specified by the user.  The iteration
        /// will stop when
        /// 
        /// (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} .LE. factr*epsmch
        /// 
        /// where epsmch is the machine precision, which is automatically
        /// generated by the code.
        /// On exit factr is unchanged.
        ///</param>
        /// <param name="PGTOL">
        /// is a double precision variable.
        /// On entry pgtol .GE. 0 is specified by the user.  The iteration
        /// will stop when
        /// 
        /// max{|proj g_i | i = 1, ..., n} .LE. pgtol
        /// 
        /// where pg_i is the ith component of the projected gradient.
        /// On exit pgtol is unchanged.
        ///</param>
        /// <param name="WN">
        /// is a double precision working array of dimension 2m x 2m
        /// used to store the LEL^T factorization of the indefinite matrix
        /// K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        /// 
        /// where     E = [-I  0]
        /// [ 0  I]
        ///</param>
        /// <param name="SND">
        /// is a double precision working array of dimension 2m x 2m
        /// used to store the lower triangular part of
        /// N = [Y' ZZ'Y   L_a'+R_z']
        /// [L_a +R_z  S'AA'S   ]
        ///</param>
        /// <param name="Z">
        /// is used at different times to store the Cauchy point and
        ///</param>
        /// <param name="INDEX">
        /// is an integer working array of dimension n.
        /// In subroutine freev, index is used to store the free and fixed
        /// variables at the Generalized Cauchy Point (GCP).
        ///</param>
        /// <param name="IWHERE">
        /// is an integer working array of dimension n used to record
        /// the status of the vector x for GCP computation.
        /// iwhere(i)=0 or -3 if x(i) is free and has bounds,
        /// 1       if x(i) is fixed at l(i), and l(i) .ne. u(i)
        /// 2       if x(i) is fixed at u(i), and u(i) .ne. l(i)
        /// 3       if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
        /// -1       if x(i) is always free, i.e., no bounds on it.
        ///</param>
        /// <param name="INDX2">
        /// is an integer working array of dimension n.
        /// Within subroutine cauchy, indx2 corresponds to the array iorder.
        /// In subroutine freev, a list of variables entering and leaving
        /// the free set is stored in indx2, and it is passed on to
        /// subroutine formk with this information.
        ///</param>
        /// <param name="TASK">
        /// is a working string of characters of length 60 indicating
        /// the current job when entering and leaving this subroutine.
        ///</param>
        /// <param name="IPRINT">
        /// is an INTEGER variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="CSAVE">
        /// is a working string of characters of length 60.
        ///</param>
        /// <param name="LSAVE">
        /// is a logical working array of dimension 4.
        ///</param>
        /// <param name="ISAVE">
        /// is an integer working array of dimension 23.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision working array of dimension 29.
        /// 
        ///</param>
        public void Run(int N, int M, ref double[] X, int offset_x, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
            , ref double F, ref double[] G, int offset_g, double FACTR, double PGTOL, ref double[] WS, int offset_ws, ref double[] WY, int offset_wy
            , ref double[] SY, int offset_sy, ref double[] SS, int offset_ss, double[] YY, int offset_yy, ref double[] WT, int offset_wt, ref double[] WN, int offset_wn, ref double[] SND, int offset_snd
            , ref double[] Z, int offset_z, ref double[] R, int offset_r, ref double[] D, int offset_d, ref double[] T, int offset_t, ref double[] WA, int offset_wa, double[] SG, int offset_sg
            , double[] SGO, int offset_sgo, double[] YG, int offset_yg, double[] YGO, int offset_ygo, ref int[] INDEX, int offset_index, ref int[] IWHERE, int offset_iwhere, ref int[] INDX2, int offset_indx2
            , ref BFGSTask TASK, int IPRINT, ref BFGSTask CSAVE, ref bool[] LSAVE, int offset_lsave, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            BFGSWord WORD = BFGSWord.aaa;

            bool PRJCTD = false; bool CNSTND = false; bool BOXED = false; bool UPDATD = false; bool WRK = false;
            int I = 0; int K = 0; int NINTOL = 0; int ITFILE = 0; int IBACK = 0; int NSKIP = 0;
            int HEAD = 0;int COL = 0; int ITER = 0; int ITAIL = 0; int IUPDAT = 0; int NINT = 0; int NFGV = 0; int INFO = 0;
            int IFUN = 0;int IWORD = 0; int NFREE = 0; int NACT = 0; int ILEAVE = 0; int NENTER = 0; double THETA = 0;
            double FOLD = 0;double DDOT = 0; double DR = 0; double RR = 0; double TOL = 0; double DPMEPS = 0; double XSTEP = 0;
            double SBGNRM = 0;double DDUM = 0; double DNORM = 0; double DTD = 0; double EPSMCH = 0; double CPU1 = 0;
            double CPU2 = 0;double CACHYT = 0; double SBTIME = 0; double LNSCHT = 0; double TIME1 = 0; double TIME2 = 0;
            double GD = 0;double GDOLD = 0; double STP = 0; double STPMX = 0; double TIME = 0;

            #endregion

            #region Array Index Correction

             int o_x = -1 + offset_x;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
             int o_g = -1 + offset_g; int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;
             int o_sy = -1 - M + offset_sy; int o_ss = -1 - M + offset_ss;  int o_yy = -1 - M + offset_yy;
             int o_wt = -1 - M + offset_wt; int o_wn = -1 - (2*M) + offset_wn;  int o_snd = -1 - (2*M) + offset_snd;
             int o_z = -1 + offset_z; int o_r = -1 + offset_r;  int o_d = -1 + offset_d;  int o_t = -1 + offset_t;
             int o_wa = -1 + offset_wa; int o_sg = -1 + offset_sg;  int o_sgo = -1 + offset_sgo;  int o_yg = -1 + offset_yg;
             int o_ygo = -1 + offset_ygo; int o_index = -1 + offset_index;  int o_iwhere = -1 + offset_iwhere;
             int o_indx2 = -1 + offset_indx2; int o_lsave = -1 + offset_lsave;  int o_isave = -1 + offset_isave;
             int o_dsave = -1 + offset_dsave;

            #endregion

            #region Prolog

            // c     ************
            // c
            // c     Subroutine mainlb
            // c
            // c     This subroutine solves bound constrained optimization problems by
            // c       using the compact formula of the limited memory BFGS updates.
            // c
            // c     n is an integer variable.
            // c       On entry n is the number of variables.
            // c       On exit n is unchanged.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric
            // c          corrections allowed in the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x is an approximation to the solution.
            // c       On exit x is the current approximation.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound of x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound of x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is an integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds,
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     f is a double precision variable.
            // c       On first entry f is unspecified.
            // c       On final exit f is the value of the function at x.
            // c
            // c     g is a double precision array of dimension n.
            // c       On first entry g is unspecified.
            // c       On final exit g is the value of the gradient at x.
            // c
            // c     factr is a double precision variable.
            // c       On entry factr >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c         (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
            // c
            // c         where epsmch is the machine precision, which is automatically
            // c         generated by the code.
            // c       On exit factr is unchanged.
            // c
            // c     pgtol is a double precision variable.
            // c       On entry pgtol >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c                 max{|proj g_i | i = 1, ..., n} <= pgtol
            // c
            // c         where pg_i is the ith component of the projected gradient.
            // c       On exit pgtol is unchanged.
            // c
            // c     ws, wy, sy, and wt are double precision working arrays used to
            // c       store the following information defining the limited memory
            // c          BFGS matrix:
            // c          ws, of dimension n x m, stores S, the matrix of s-vectors;
            // c          wy, of dimension n x m, stores Y, the matrix of y-vectors;
            // c          sy, of dimension m x m, stores S'Y;
            // c          ss, of dimension m x m, stores S'S;
            // c	   yy, of dimension m x m, stores Y'Y;
            // c          wt, of dimension m x m, stores the Cholesky factorization
            // c                                  of (theta*S'S+LD^(-1)L'); see eq.
            // c                                  (2.26) in [3].
            // c
            // c     wn is a double precision working array of dimension 2m x 2m
            // c       used to store the LEL^T factorization of the indefinite matrix
            // c                 K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c
            // c       where     E = [-I  0]
            // c                     [ 0  I]
            // c
            // c     snd is a double precision working array of dimension 2m x 2m
            // c       used to store the lower triangular part of
            // c                 N = [Y' ZZ'Y   L_a'+R_z']
            // c                     [L_a +R_z  S'AA'S   ]
            // c
            // c     z(n),r(n),d(n),t(n),wa(8*m) are double precision working arrays.
            // c       z is used at different times to store the Cauchy point and
            // c       the Newton point.
            // c
            // c     sg(m),sgo(m),yg(m),ygo(m) are double precision working arrays.
            // c
            // c     index is an integer working array of dimension n.
            // c       In subroutine freev, index is used to store the free and fixed
            // c          variables at the Generalized Cauchy Point (GCP).
            // c
            // c     iwhere is an integer working array of dimension n used to record
            // c       the status of the vector x for GCP computation.
            // c       iwhere(i)=0 or -3 if x(i) is free and has bounds,
            // c                 1       if x(i) is fixed at l(i), and l(i) .ne. u(i)
            // c                 2       if x(i) is fixed at u(i), and u(i) .ne. l(i)
            // c                 3       if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
            // c                -1       if x(i) is always free, i.e., no bounds on it.
            // c
            // c     indx2 is an integer working array of dimension n.
            // c       Within subroutine cauchy, indx2 corresponds to the array iorder.
            // c       In subroutine freev, a list of variables entering and leaving
            // c       the free set is stored in indx2, and it is passed on to
            // c       subroutine formk with this information.
            // c
            // c     task is a working string of characters of length 60 indicating
            // c       the current job when entering and leaving this subroutine.
            // c
            // c     iprint is an INTEGER variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     csave is a working string of characters of length 60.
            // c
            // c     lsave is a logical working array of dimension 4.
            // c
            // c     isave is an integer working array of dimension 23.
            // c
            // c     dsave is a double precision working array of dimension 29.
            // c
            // c
            // c     Subprograms called
            // c
            // c       L-BFGS-B Library ... cauchy, subsm, lnsrlb, formk,
            // c
            // c        errclb, prn1lb, prn2lb, prn3lb, active, projgr,
            // c
            // c        freev, cmprlb, matupd, formt.
            // c
            // c       Minpack2 Library ... timer, dpmeps.
            // c
            // c       Linpack Library ... dcopy, ddot.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
            // c       Subroutines for Large Scale Bound Constrained Optimization''
            // c       Tech. Report, NAM-11, EECS Department, Northwestern University,
            // c       1994.
            // c
            // c       [3] R. Byrd, J. Nocedal and R. Schnabel "Representations of
            // c       Quasi-Newton Matrices and their use in Limited Memory Methods'',
            // c       Mathematical Programming 63 (1994), no. 4, pp. 129-156.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************

            #endregion

            #region Body

             if (TASK == BFGSTask.START)
            {

                this._timer.Run(ref TIME1);

                // c        Generate the current machine precision.

                EPSMCH = this._dpmeps.Run();

                // c        Initialize counters and scalars when task='START'.

                // c           for the limited memory BFGS matrices:
                COL = 0;
                HEAD = 1;
                THETA = ONE;
                IUPDAT = 0;
                UPDATD = false;

                // c           for operation counts:
                ITER = 0;
                NFGV = 0;
                NINT = 0;
                NINTOL = 0;
                NSKIP = 0;
                NFREE = N;

                // c           for stopping tolerance:
                TOL = FACTR * EPSMCH;

                // c           for measuring running time:
                CACHYT = 0;
                SBTIME = 0;
                LNSCHT = 0;

                // c           'word' records the status of subspace solutions.
                WORD = BFGSWord.aaa;

                // c           'info' records the termination information.
                INFO = 0;

                if (IPRINT >= 1)
                {
                    // c                                open a summary file 'iterate.dat'
                    //ERROR-ERROR            OPEN (8, FILE = 'iterate.dat', STATUS = 'unknown');
                    ITFILE = 8;
                }

                // c        Check the input arguments for errors.

                this._errclb.Run(N, M, FACTR, L, offset_l, U, offset_u, NBD, offset_nbd
                                 , ref TASK, ref INFO, ref K);
                if (TASK == BFGSTask.ERROR)
                {
                    this._prn3lb.Run(N, X, offset_x, F, TASK, IPRINT, INFO
                                     , ITFILE, ITER, NFGV, NINTOL, NSKIP, NACT
                                     , SBGNRM, ZERO, NINT, WORD, IBACK, STP
                                     , XSTEP, K, CACHYT, SBTIME, LNSCHT);
                    return;
                }

                this._prn1lb.Run(N, M, L, offset_l, U, offset_u, X, offset_x, IPRINT
                                 , ITFILE, EPSMCH);

                // c        Initialize iwhere & project x onto the feasible set.

                this._active.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, ref X, offset_x, ref IWHERE, offset_iwhere
                                 , IPRINT, ref PRJCTD, ref CNSTND, ref BOXED);

                // c        The end of the initialization.

            }
            else
            {
                // c          restore local variables.

                PRJCTD = LSAVE[1 + o_lsave];
                CNSTND = LSAVE[2 + o_lsave];
                BOXED = LSAVE[3 + o_lsave];
                UPDATD = LSAVE[4 + o_lsave];

                NINTOL = ISAVE[1 + o_isave];
                ITFILE = ISAVE[3 + o_isave];
                IBACK = ISAVE[4 + o_isave];
                NSKIP = ISAVE[5 + o_isave];
                HEAD = ISAVE[6 + o_isave];
                COL = ISAVE[7 + o_isave];
                ITAIL = ISAVE[8 + o_isave];
                ITER = ISAVE[9 + o_isave];
                IUPDAT = ISAVE[10 + o_isave];
                NINT = ISAVE[12 + o_isave];
                NFGV = ISAVE[13 + o_isave];
                INFO = ISAVE[14 + o_isave];
                IFUN = ISAVE[15 + o_isave];
                IWORD = ISAVE[16 + o_isave];
                NFREE = ISAVE[17 + o_isave];
                NACT = ISAVE[18 + o_isave];
                ILEAVE = ISAVE[19 + o_isave];
                NENTER = ISAVE[20 + o_isave];

                THETA = DSAVE[1 + o_dsave];
                FOLD = DSAVE[2 + o_dsave];
                TOL = DSAVE[3 + o_dsave];
                DNORM = DSAVE[4 + o_dsave];
                EPSMCH = DSAVE[5 + o_dsave];
                CPU1 = DSAVE[6 + o_dsave];
                CACHYT = DSAVE[7 + o_dsave];
                SBTIME = DSAVE[8 + o_dsave];
                LNSCHT = DSAVE[9 + o_dsave];
                TIME1 = DSAVE[10 + o_dsave];
                GD = DSAVE[11 + o_dsave];
                STPMX = DSAVE[12 + o_dsave];
                SBGNRM = DSAVE[13 + o_dsave];
                STP = DSAVE[14 + o_dsave];
                GDOLD = DSAVE[15 + o_dsave];
                DTD = DSAVE[16 + o_dsave];

                // c        After returning from the driver go to the point where execution
                // c        is to resume.

                if (TASK == BFGSTask.FG_LNSRCH) goto LABEL666;
                if (TASK == BFGSTask.NEW_X) goto LABEL777;
                if (TASK == BFGSTask.FG_ST || TASK == BFGSTask.FG_START) goto LABEL111;
                if (TASK == BFGSTask.STOP)
                {
                    if (TASK== BFGSTask.CPU)
                    {
                        // c                                          restore the previous iterate.
                        this._dcopy.Run(N, T, offset_t, 1, ref X, offset_x, 1);
                        this._dcopy.Run(N, R, offset_r, 1, ref G, offset_g, 1);
                        F = FOLD;
                    }
                    goto LABEL999;
                }
            }

            // c     Compute f0 and g0.

             TASK = BFGSTask.FG_START;
            // c          return to the driver to calculate f and g; reenter at 111.
            goto LABEL1000;
            LABEL111:;
            NFGV = 1;

            // c     Compute the infinity norm of the (-) projected gradient.

            this._projgr.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, X, offset_x, G, offset_g
                             , ref SBGNRM);

            if (IPRINT >= 1)
            {
                //ERROR-ERROR         WRITE (6,1002) ITER,F,SBGNRM;
                //ERROR-ERROR         WRITE (ITFILE,1003) ITER,NFGV,SBGNRM,F;
            }
            if (SBGNRM <= PGTOL)
            {
                // c                                terminate the algorithm.
                TASK = BFGSTask.CONV;
                goto LABEL999;
            }

            // c ----------------- the beginning of the loop --------------------------

            LABEL222:;
            if (IPRINT >= 99) ;//ERROR-ERRORWRITE(6,1001)ITER+1
            IWORD =  - 1;
            // c
            if (!CNSTND && COL > 0)
            {
                // c                                            skip the search for GCP.
                this._dcopy.Run(N, X, offset_x, 1, ref Z, offset_z, 1);
                WRK = UPDATD;
                NINT = 0;
                goto LABEL333;
            }

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Compute the Generalized Cauchy Point (GCP).
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            this._timer.Run(ref CPU1);
            this._cauchy.Run(N, X, offset_x, L, offset_l, U, offset_u, NBD, offset_nbd, G, offset_g
                             , ref INDX2, offset_indx2, ref IWHERE, offset_iwhere, ref T, offset_t, ref D, offset_d, ref Z, offset_z, M
                             , WY, offset_wy, WS, offset_ws, SY, offset_sy, WT, offset_wt, THETA, COL
                             , HEAD, ref WA, 1 + o_wa, ref WA, 2 * M + 1 + o_wa, ref WA, 4 * M + 1 + o_wa, ref WA, 6 * M + 1 + o_wa, ref NINT
                             , SG, offset_sg, YG, offset_yg, IPRINT, SBGNRM, ref INFO, EPSMCH);
            if (INFO != 0)
            {
                // c         singular triangular system detected; refresh the lbfgs memory.
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1005)
                INFO = 0;
                COL = 0;
                HEAD = 1;
                THETA = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                CACHYT += CPU2 - CPU1;
                goto LABEL222;
            }
            this._timer.Run(ref CPU2);
            CACHYT += CPU2 - CPU1;
            NINTOL += NINT;

            // c     Count the entering and leaving variables for iter > 0;
            // c     find the index set of free and active variables at the GCP.

            this._freev.Run(N, ref NFREE, ref INDEX, offset_index, ref NENTER, ref ILEAVE, ref INDX2, offset_indx2
                            , IWHERE, offset_iwhere, ref WRK, UPDATD, CNSTND, IPRINT, ITER);

            NACT = N - NFREE;

            LABEL333:;

            // c     If there are no free variables or B=theta*I, then
            // c                                        skip the subspace minimization.

            if (NFREE == 0 || COL == 0) goto LABEL555;

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Subspace minimization.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            this._timer.Run(ref CPU1);

            // c     Form  the LEL^T factorization of the indefinite
            // c       matrix    K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c       where     E = [-I  0]
            // c                     [ 0  I]

            if (WRK)
            {
                this._formk.Run(N, NFREE, INDEX, offset_index, NENTER, ILEAVE, INDX2, offset_indx2
                                , IUPDAT, UPDATD, ref WN, offset_wn, ref SND, offset_snd, M, WS, offset_ws
                                , WY, offset_wy, SY, offset_sy, THETA, COL, HEAD, ref INFO);
            }
            if (INFO != 0)
            {
                // c          nonpositive definiteness in Cholesky factorization;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1006)
                INFO = 0;
                COL = 0;
                HEAD = 1;
                THETA = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                SBTIME += CPU2 - CPU1;
                goto LABEL222;
            }

            // c        compute r=-Z'B(xcp-xk)-Z'g (using wa(2m+1)=W'(xcp-x)
            // c                                                   from 'cauchy').
            this._cmprlb.Run(N, M, X, offset_x, G, offset_g, WS, offset_ws, WY, offset_wy
                             , SY, offset_sy, WT, offset_wt, Z, offset_z, ref R, offset_r, ref WA, offset_wa, INDEX, offset_index
                             , THETA, COL, HEAD, NFREE, CNSTND, ref INFO);
            if (INFO != 0) goto LABEL444;
            // c       call the direct method.
            this._subsm.Run(N, M, NFREE, INDEX, offset_index, L, offset_l, U, offset_u
                            , NBD, offset_nbd, ref Z, offset_z, ref R, offset_r, WS, offset_ws, WY, offset_wy, THETA
                            , COL, HEAD, ref IWORD, ref WA, offset_wa, WN, offset_wn, IPRINT
                            , ref INFO);
            LABEL444:;
            if (INFO != 0)
            {
                // c          singular triangular system detected;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1005)
                INFO = 0;
                COL = 0;
                HEAD = 1;
                THETA = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                SBTIME += CPU2 - CPU1;
                goto LABEL222;
            }

            this._timer.Run(ref CPU2);
            SBTIME += CPU2 - CPU1;
            LABEL555:;

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Line search and optimality tests.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            // c     Generate the search direction d:=z-x.

            for (I = 1; I <= N; I++)
            {
                D[I + o_d] = Z[I + o_z] - X[I + o_x];
            }
            this._timer.Run(ref CPU1);
            LABEL666:;
            this._lnsrlb.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, ref X, offset_x, F
                             , ref FOLD, ref GD, ref GDOLD, G, offset_g, D, offset_d, ref R, offset_r
                             , ref T, offset_t, Z, offset_z, ref STP, ref DNORM, ref DTD, ref XSTEP
                             , ref STPMX, ITER, ref IFUN, ref IBACK, ref NFGV, ref INFO
                             , ref TASK, BOXED, CNSTND, ref CSAVE, ref ISAVE, 22 + o_isave, ref DSAVE, 17 + o_dsave);
            if (INFO != 0 || IBACK >= 20)
            {
                // c          restore the previous iterate.
                this._dcopy.Run(N, T, offset_t, 1, ref X, offset_x, 1);
                this._dcopy.Run(N, R, offset_r, 1, ref G, offset_g, 1);
                F = FOLD;
                if (COL == 0)
                {
                    // c             abnormal termination.
                    if (INFO == 0)
                    {
                        INFO =  - 9;
                        // c                restore the actual number of f and g evaluations etc.
                        NFGV -= 1;
                        IFUN -= 1;
                        IBACK -= 1;
                    }
                    TASK = BFGSTask.ABNO;
                    ITER += 1;
                    goto LABEL999;
                }
                else
                {
                    // c             refresh the lbfgs memory and restart the iteration.
                    if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1008)
                    if (INFO == 0) NFGV -= 1;
                    INFO = 0;
                    COL = 0;
                    HEAD = 1;
                    THETA = ONE;
                    IUPDAT = 0;
                    UPDATD = false;
                    TASK = BFGSTask.RESTART;
                    this._timer.Run(ref CPU2);
                    LNSCHT += CPU2 - CPU1;
                    goto LABEL222;
                }
            }
            else
            {
                if (TASK == BFGSTask.FG_LNSRCH)
                {
                    // c          return to the driver for calculating f and g; reenter at 666.
                    goto LABEL1000;
                }
                else
                {
                    // c          calculate and print out the quantities related to the new X.
                    this._timer.Run(ref CPU2);
                    LNSCHT += CPU2 - CPU1;
                    ITER += 1;

                    // c        Compute the infinity norm of the projected (-)gradient.

                    this._projgr.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, X, offset_x, G, offset_g
                                     , ref SBGNRM);

                    // c        Print iteration information.

                    this._prn2lb.Run(N, X, offset_x, F, G, offset_g, IPRINT, ITFILE
                                     , ITER, NFGV, NACT, SBGNRM, NINT, ref WORD
                                     , IWORD, IBACK, STP, XSTEP);
                    goto LABEL1000;
                }
            }
            LABEL777:;

            // c     Test for termination.

            if (SBGNRM <= PGTOL)
            {
                // c                                terminate the algorithm.
                TASK = BFGSTask.CONV;
                goto LABEL999;
            }

            DDUM = Math.Max(Math.Abs(FOLD), Math.Max(Math.Abs(F), ONE));
            if ((FOLD - F) <= TOL * DDUM)
            {
                // c                                        terminate the algorithm.
                TASK = BFGSTask.CONV;
                if (IBACK >= 10) INFO =  - 5;
                // c           i.e., to issue a warning if iback>10 in the line search.
                goto LABEL999;
            }

            // c     Compute d=newx-oldx, r=newg-oldg, rr=y'y and dr=y's.

            for (I = 1; I <= N; I++)
            {
                R[I + o_r] = G[I + o_g] - R[I + o_r];
            }
            RR = this._ddot.Run(N, R, offset_r, 1, R, offset_r, 1);
            if (STP == ONE)
            {
                DR = GD - GDOLD;
                DDUM =  - GDOLD;
            }
            else
            {
                DR = (GD - GDOLD) * STP;
                this._dscal.Run(N, STP, ref D, offset_d, 1);
                DDUM =  - GDOLD * STP;
            }

            if (DR <= EPSMCH * DDUM)
            {
                // c                            skip the L-BFGS update.
                NSKIP += 1;
                UPDATD = false;
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1004)DR,DDUM
                goto LABEL888;
            }

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Update the L-BFGS matrix.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            UPDATD = true;
            IUPDAT += 1;

            // c     Update matrices WS and WY and form the middle matrix in B.

            this._matupd.Run(N, M, ref WS, offset_ws, ref WY, offset_wy, ref SY, offset_sy, ref SS, offset_ss
                             , D, offset_d, R, offset_r, ref ITAIL, IUPDAT, ref COL, ref HEAD
                             , ref THETA, RR, DR, STP, DTD);

            // c     Form the upper half of the pds T = theta*SS + L*D^(-1)*L';
            // c        Store T in the upper triangular of the array wt;
            // c        Cholesky factorize T to J*J' with
            // c           J' stored in the upper triangular of wt.

            this._formt.Run(M, ref WT, offset_wt, SY, offset_sy, SS, offset_ss, COL, THETA
                            , ref INFO);

            if (INFO != 0)
            {
                // c          nonpositive definiteness in Cholesky factorization;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,1007)
                INFO = 0;
                COL = 0;
                HEAD = 1;
                THETA = ONE;
                IUPDAT = 0;
                UPDATD = false;
                goto LABEL222;
            }

            // c     Now the inverse of the middle matrix in B is

            // c       [  D^(1/2)      O ] [ -D^(1/2)  D^(-1/2)*L' ]
            // c       [ -L*D^(-1/2)   J ] [  0        J'          ]

            LABEL888:;

            // c -------------------- the end of the loop -----------------------------

            goto LABEL222;
            LABEL999:;
            this._timer.Run(ref TIME2);
            TIME = TIME2 - TIME1;
            this._prn3lb.Run(N, X, offset_x, F, TASK, IPRINT, INFO
                             , ITFILE, ITER, NFGV, NINTOL, NSKIP, NACT
                             , SBGNRM, TIME, NINT, WORD, IBACK, STP
                             , XSTEP, K, CACHYT, SBTIME, LNSCHT);
            LABEL1000:;

            // c     Save local variables.

            LSAVE[1 + o_lsave] = PRJCTD;
            LSAVE[2 + o_lsave] = CNSTND;
            LSAVE[3 + o_lsave] = BOXED;
            LSAVE[4 + o_lsave] = UPDATD;

            ISAVE[1 + o_isave] = NINTOL;
            ISAVE[3 + o_isave] = ITFILE;
            ISAVE[4 + o_isave] = IBACK;
            ISAVE[5 + o_isave] = NSKIP;
            ISAVE[6 + o_isave] = HEAD;
            ISAVE[7 + o_isave] = COL;
            ISAVE[8 + o_isave] = ITAIL;
            ISAVE[9 + o_isave] = ITER;
            ISAVE[10 + o_isave] = IUPDAT;
            ISAVE[12 + o_isave] = NINT;
            ISAVE[13 + o_isave] = NFGV;
            ISAVE[14 + o_isave] = INFO;
            ISAVE[15 + o_isave] = IFUN;
            ISAVE[16 + o_isave] = IWORD;
            ISAVE[17 + o_isave] = NFREE;
            ISAVE[18 + o_isave] = NACT;
            ISAVE[19 + o_isave] = ILEAVE;
            ISAVE[20 + o_isave] = NENTER;

            DSAVE[1 + o_dsave] = THETA;
            DSAVE[2 + o_dsave] = FOLD;
            DSAVE[3 + o_dsave] = TOL;
            DSAVE[4 + o_dsave] = DNORM;
            DSAVE[5 + o_dsave] = EPSMCH;
            DSAVE[6 + o_dsave] = CPU1;
            DSAVE[7 + o_dsave] = CACHYT;
            DSAVE[8 + o_dsave] = SBTIME;
            DSAVE[9 + o_dsave] = LNSCHT;
            DSAVE[10 + o_dsave] = TIME1;
            DSAVE[11 + o_dsave] = GD;
            DSAVE[12 + o_dsave] = STPMX;
            DSAVE[13 + o_dsave] = SBGNRM;
            DSAVE[14 + o_dsave] = STP;
            DSAVE[15 + o_dsave] = GDOLD;
            DSAVE[16 + o_dsave] = DTD;

            return;

            #endregion
        }
Example #9
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x is an approximation to the solution.
        /// On exit x is the current approximation.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound on x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound on x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is an integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds, and
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="F">
        /// is a double precision variable.
        /// On first entry f is unspecified.
        /// On final exit f is the value of the function at x.
        ///</param>
        /// <param name="G">
        /// is a double precision array of dimension n.
        /// On first entry g is unspecified.
        /// On final exit g is the value of the gradient at x.
        ///</param>
        /// <param name="FACTR">
        /// is a double precision variable.
        /// On entry factr .GE. 0 is specified by the user.  The iteration
        /// will stop when
        /// 
        /// (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} .LE. factr*epsmch
        /// 
        /// where epsmch is the machine precision, which is automatically
        /// generated by the code. Typical values for factr: 1.d+12 for
        /// low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely
        /// high accuracy.
        /// On exit factr is unchanged.
        ///</param>
        /// <param name="PGTOL">
        /// is a double precision variable.
        /// On entry pgtol .GE. 0 is specified by the user.  The iteration
        /// will stop when
        /// 
        /// max{|proj g_i | i = 1, ..., n} .LE. pgtol
        /// 
        /// where pg_i is the ith component of the projected gradient.   
        /// On exit pgtol is unchanged.
        ///</param>
        /// <param name="WA">
        /// is a double precision working array of length 
        /// (2mmax + 4)nmax + 12mmax^2 + 12mmax.
        ///</param>
        /// <param name="IWA">
        /// is an integer working array of length 3nmax.
        ///</param>
        /// <param name="TASK">
        /// is a working string of characters of length 60 indicating
        /// the current job when entering and quitting this subroutine.
        ///</param>
        /// <param name="IPRINT">
        /// is an integer variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="CSAVE">
        /// is a working string of characters of length 60.
        ///</param>
        /// <param name="LSAVE">
        /// is a logical working array of dimension 4.
        /// On exit with 'task' = NEW_X, the following information is 
        /// available:
        /// If lsave(1) = .true.  then  the initial X has been replaced by
        /// its projection in the feasible set;
        /// If lsave(2) = .true.  then  the problem is constrained;
        /// If lsave(3) = .true.  then  each variable has upper and lower
        /// bounds;
        ///</param>
        /// <param name="ISAVE">
        /// is an integer working array of dimension 44.
        /// On exit with 'task' = NEW_X, the following information is 
        /// available:
        /// isave(22) = the total number of intervals explored in the 
        /// search of Cauchy points;
        /// isave(26) = the total number of skipped BFGS updates before 
        /// the current iteration;
        /// isave(30) = the number of current iteration;
        /// isave(31) = the total number of BFGS updates prior the current
        /// iteration;
        /// isave(33) = the number of intervals explored in the search of
        /// Cauchy point in the current iteration;
        /// isave(34) = the total number of function and gradient 
        /// evaluations;
        /// isave(36) = the number of function value or gradient
        /// evaluations in the current iteration;
        /// if isave(37) = 0  then the subspace argmin is within the box;
        /// if isave(37) = 1  then the subspace argmin is beyond the box;
        /// isave(38) = the number of free variables in the current
        /// iteration;
        /// isave(39) = the number of active constraints in the current
        /// iteration;
        /// n + 1 - isave(40) = the number of variables leaving the set of
        /// active constraints in the current iteration;
        /// isave(41) = the number of variables entering the set of active
        /// constraints in the current iteration.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision working array of dimension 29.
        /// On exit with 'task' = NEW_X, the following information is
        /// available:
        /// dsave(1) = current 'theta' in the BFGS matrix;
        /// dsave(2) = f(x) in the previous iteration;
        /// dsave(3) = factr*epsmch;
        /// dsave(4) = 2-norm of the line search direction vector;
        /// dsave(5) = the machine precision epsmch generated by the code;
        /// dsave(7) = the accumulated time spent on searching for
        /// Cauchy points;
        /// dsave(8) = the accumulated time spent on
        /// subspace minimization;
        /// dsave(9) = the accumulated time spent on line search;
        /// dsave(11) = the slope of the line search function at
        /// the current point of line search;
        /// dsave(12) = the maximum relative step length imposed in
        /// line search;
        /// dsave(13) = the infinity norm of the projected gradient;
        /// dsave(14) = the relative step length in the line search;
        /// dsave(15) = the slope of the line search function at
        /// the starting point of the line search;
        /// dsave(16) = the square of the 2-norm of the line search
        /// direction vector.
        ///</param>
        public void Run(int N, int M, ref double[] X, int offset_x, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
            , ref double F, ref double[] G, int offset_g, double FACTR, double PGTOL, ref double[] WA, int offset_wa, ref int[] IWA, int offset_iwa
            , ref BFGSTask TASK, int IPRINT, ref BFGSTask CSAVE, ref bool[] LSAVE, int offset_lsave, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            int L1 = 0; int L2 = 0; int L3 = 0; int LWS = 0; int LR = 0; int LZ = 0; int LT = 0; int LD = 0; int LSG = 0;
            int LWA = 0;int LYG = 0; int LSGO = 0; int LWY = 0; int LSY = 0; int LSS = 0; int LYY = 0; int LWT = 0; int LWN = 0;
            int LSND = 0;int LYGO = 0;

            #endregion

            #region Array Index Correction

             int o_x = -1 + offset_x;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
             int o_g = -1 + offset_g; int o_wa = -1 + offset_wa;  int o_iwa = -1 + offset_iwa;  int o_lsave = -1 + offset_lsave;
             int o_isave = -1 + offset_isave; int o_dsave = -1 + offset_dsave;

            #endregion

            #region Prolog

            // c     ************
            // c
            // c     Subroutine setulb
            // c
            // c     This subroutine partitions the working arrays wa and iwa, and
            // c       then uses the limited memory BFGS method to solve the bound
            // c       constrained optimization problem by calling mainlb.
            // c       (The direct method will be used in the subspace minimization.)
            // c
            // c     n is an integer variable.
            // c       On entry n is the dimension of the problem.
            // c       On exit n is unchanged.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric corrections
            // c         used to define the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x is an approximation to the solution.
            // c       On exit x is the current approximation.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound on x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound on x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is an integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds, and
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     f is a double precision variable.
            // c       On first entry f is unspecified.
            // c       On final exit f is the value of the function at x.
            // c
            // c     g is a double precision array of dimension n.
            // c       On first entry g is unspecified.
            // c       On final exit g is the value of the gradient at x.
            // c
            // c     factr is a double precision variable.
            // c       On entry factr >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c         (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
            // c
            // c         where epsmch is the machine precision, which is automatically
            // c         generated by the code. Typical values for factr: 1.d+12 for
            // c         low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely
            // c         high accuracy.
            // c       On exit factr is unchanged.
            // c
            // c     pgtol is a double precision variable.
            // c       On entry pgtol >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c                 max{|proj g_i | i = 1, ..., n} <= pgtol
            // c
            // c         where pg_i is the ith component of the projected gradient.
            // c       On exit pgtol is unchanged.
            // c
            // c     wa is a double precision working array of length
            // c       (2mmax + 4)nmax + 12mmax^2 + 12mmax.
            // c
            // c     iwa is an integer working array of length 3nmax.
            // c
            // c     task is a working string of characters of length 60 indicating
            // c       the current job when entering and quitting this subroutine.
            // c
            // c     iprint is an integer variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     csave is a working string of characters of length 60.
            // c
            // c     lsave is a logical working array of dimension 4.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         If lsave(1) = .true.  then  the initial X has been replaced by
            // c                                     its projection in the feasible set;
            // c         If lsave(2) = .true.  then  the problem is constrained;
            // c         If lsave(3) = .true.  then  each variable has upper and lower
            // c                                     bounds;
            // c
            // c     isave is an integer working array of dimension 44.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         isave(22) = the total number of intervals explored in the
            // c                         search of Cauchy points;
            // c         isave(26) = the total number of skipped BFGS updates before
            // c                         the current iteration;
            // c         isave(30) = the number of current iteration;
            // c         isave(31) = the total number of BFGS updates prior the current
            // c                         iteration;
            // c         isave(33) = the number of intervals explored in the search of
            // c                         Cauchy point in the current iteration;
            // c         isave(34) = the total number of function and gradient
            // c                         evaluations;
            // c         isave(36) = the number of function value or gradient
            // c                                  evaluations in the current iteration;
            // c         if isave(37) = 0  then the subspace argmin is within the box;
            // c         if isave(37) = 1  then the subspace argmin is beyond the box;
            // c         isave(38) = the number of free variables in the current
            // c                         iteration;
            // c         isave(39) = the number of active constraints in the current
            // c                         iteration;
            // c         n + 1 - isave(40) = the number of variables leaving the set of
            // c                           active constraints in the current iteration;
            // c         isave(41) = the number of variables entering the set of active
            // c                         constraints in the current iteration.
            // c
            // c     dsave is a double precision working array of dimension 29.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         dsave(1) = current 'theta' in the BFGS matrix;
            // c         dsave(2) = f(x) in the previous iteration;
            // c         dsave(3) = factr*epsmch;
            // c         dsave(4) = 2-norm of the line search direction vector;
            // c         dsave(5) = the machine precision epsmch generated by the code;
            // c         dsave(7) = the accumulated time spent on searching for
            // c                                                         Cauchy points;
            // c         dsave(8) = the accumulated time spent on
            // c                                                 subspace minimization;
            // c         dsave(9) = the accumulated time spent on line search;
            // c         dsave(11) = the slope of the line search function at
            // c                                  the current point of line search;
            // c         dsave(12) = the maximum relative step length imposed in
            // c                                                           line search;
            // c         dsave(13) = the infinity norm of the projected gradient;
            // c         dsave(14) = the relative step length in the line search;
            // c         dsave(15) = the slope of the line search function at
            // c                                 the starting point of the line search;
            // c         dsave(16) = the square of the 2-norm of the line search
            // c                                                      direction vector.
            // c
            // c     Subprograms called:
            // c
            // c       L-BFGS-B Library ... mainlb.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
            // c       limited memory FORTRAN code for solving bound constrained
            // c       optimization problems'', Tech. Report, NAM-11, EECS Department,
            // c       Northwestern University, 1994.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************

            #endregion

            #region Body

             if (TASK == BFGSTask.START)
            {
                ISAVE[1 + o_isave] = M * N;
                ISAVE[2 + o_isave] = (int)Math.Pow(M,2);
                ISAVE[3 + o_isave] = 4 * (int)Math.Pow(M,2);
                ISAVE[4 + o_isave] = 1;
                ISAVE[5 + o_isave] = ISAVE[4 + o_isave] + ISAVE[1 + o_isave];
                ISAVE[6 + o_isave] = ISAVE[5 + o_isave] + ISAVE[1 + o_isave];
                ISAVE[7 + o_isave] = ISAVE[6 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[8 + o_isave] = ISAVE[7 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[9 + o_isave] = ISAVE[8 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[10 + o_isave] = ISAVE[9 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[11 + o_isave] = ISAVE[10 + o_isave] + ISAVE[3 + o_isave];
                ISAVE[12 + o_isave] = ISAVE[11 + o_isave] + ISAVE[3 + o_isave];
                ISAVE[13 + o_isave] = ISAVE[12 + o_isave] + N;
                ISAVE[14 + o_isave] = ISAVE[13 + o_isave] + N;
                ISAVE[15 + o_isave] = ISAVE[14 + o_isave] + N;
                ISAVE[16 + o_isave] = ISAVE[15 + o_isave] + N;
                ISAVE[17 + o_isave] = ISAVE[16 + o_isave] + 8 * M;
                ISAVE[18 + o_isave] = ISAVE[17 + o_isave] + M;
                ISAVE[19 + o_isave] = ISAVE[18 + o_isave] + M;
                ISAVE[20 + o_isave] = ISAVE[19 + o_isave] + M;
            }
            L1 = ISAVE[1 + o_isave];
            L2 = ISAVE[2 + o_isave];
            L3 = ISAVE[3 + o_isave];
            LWS = ISAVE[4 + o_isave];
            LWY = ISAVE[5 + o_isave];
            LSY = ISAVE[6 + o_isave];
            LSS = ISAVE[7 + o_isave];
            LYY = ISAVE[8 + o_isave];
            LWT = ISAVE[9 + o_isave];
            LWN = ISAVE[10 + o_isave];
            LSND = ISAVE[11 + o_isave];
            LZ = ISAVE[12 + o_isave];
            LR = ISAVE[13 + o_isave];
            LD = ISAVE[14 + o_isave];
            LT = ISAVE[15 + o_isave];
            LWA = ISAVE[16 + o_isave];
            LSG = ISAVE[17 + o_isave];
            LSGO = ISAVE[18 + o_isave];
            LYG = ISAVE[19 + o_isave];
            LYGO = ISAVE[20 + o_isave];

            this._mainlb.Run(N, M, ref X, offset_x, L, offset_l, U, offset_u, NBD, offset_nbd
                             , ref F, ref G, offset_g, FACTR, PGTOL, ref WA, LWS + o_wa, ref WA, LWY + o_wa
                             , ref WA, LSY + o_wa, ref WA, LSS + o_wa, WA, LYY + o_wa, ref WA, LWT + o_wa, ref WA, LWN + o_wa, ref WA, LSND + o_wa
                             , ref WA, LZ + o_wa, ref WA, LR + o_wa, ref WA, LD + o_wa, ref WA, LT + o_wa, ref WA, LWA + o_wa, WA, LSG + o_wa
                             , WA, LSGO + o_wa, WA, LYG + o_wa, WA, LYGO + o_wa, ref IWA, 1 + o_iwa, ref IWA, N + 1 + o_iwa, ref IWA, 2 * N + 1 + o_iwa
                             , ref TASK, IPRINT, ref CSAVE, ref LSAVE, offset_lsave, ref ISAVE, 22 + o_isave, ref DSAVE, offset_dsave);

            return;

            #endregion
        }
Example #10
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the dimension of the problem.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric corrections
        /// used to define the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x is an approximation to the solution.
        /// On exit x is the current approximation.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound on x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound on x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is an integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds, and
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="F">
        /// is a double precision variable.
        /// On first entry f is unspecified.
        /// On final exit f is the value of the function at x.
        ///</param>
        /// <param name="G">
        /// is a double precision array of dimension n.
        /// On first entry g is unspecified.
        /// On final exit g is the value of the gradient at x.
        ///</param>
        /// <param name="FACTR">
        /// is a double precision variable.
        /// On entry factr .GE. 0 is specified by the user.  The iteration
        /// will stop when
        ///
        /// (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} .LE. factr*epsmch
        ///
        /// where epsmch is the machine precision, which is automatically
        /// generated by the code. Typical values for factr: 1.d+12 for
        /// low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely
        /// high accuracy.
        /// On exit factr is unchanged.
        ///</param>
        /// <param name="PGTOL">
        /// is a double precision variable.
        /// On entry pgtol .GE. 0 is specified by the user.  The iteration
        /// will stop when
        ///
        /// max{|proj g_i | i = 1, ..., n} .LE. pgtol
        ///
        /// where pg_i is the ith component of the projected gradient.
        /// On exit pgtol is unchanged.
        ///</param>
        /// <param name="WA">
        /// is a double precision working array of length
        /// (2mmax + 4)nmax + 12mmax^2 + 12mmax.
        ///</param>
        /// <param name="IWA">
        /// is an integer working array of length 3nmax.
        ///</param>
        /// <param name="TASK">
        /// is a working string of characters of length 60 indicating
        /// the current job when entering and quitting this subroutine.
        ///</param>
        /// <param name="IPRINT">
        /// is an integer variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="CSAVE">
        /// is a working string of characters of length 60.
        ///</param>
        /// <param name="LSAVE">
        /// is a logical working array of dimension 4.
        /// On exit with 'task' = NEW_X, the following information is
        /// available:
        /// If lsave(1) = .true.  then  the initial X has been replaced by
        /// its projection in the feasible set;
        /// If lsave(2) = .true.  then  the problem is constrained;
        /// If lsave(3) = .true.  then  each variable has upper and lower
        /// bounds;
        ///</param>
        /// <param name="ISAVE">
        /// is an integer working array of dimension 44.
        /// On exit with 'task' = NEW_X, the following information is
        /// available:
        /// isave(22) = the total number of intervals explored in the
        /// search of Cauchy points;
        /// isave(26) = the total number of skipped BFGS updates before
        /// the current iteration;
        /// isave(30) = the number of current iteration;
        /// isave(31) = the total number of BFGS updates prior the current
        /// iteration;
        /// isave(33) = the number of intervals explored in the search of
        /// Cauchy point in the current iteration;
        /// isave(34) = the total number of function and gradient
        /// evaluations;
        /// isave(36) = the number of function value or gradient
        /// evaluations in the current iteration;
        /// if isave(37) = 0  then the subspace argmin is within the box;
        /// if isave(37) = 1  then the subspace argmin is beyond the box;
        /// isave(38) = the number of free variables in the current
        /// iteration;
        /// isave(39) = the number of active constraints in the current
        /// iteration;
        /// n + 1 - isave(40) = the number of variables leaving the set of
        /// active constraints in the current iteration;
        /// isave(41) = the number of variables entering the set of active
        /// constraints in the current iteration.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision working array of dimension 29.
        /// On exit with 'task' = NEW_X, the following information is
        /// available:
        /// dsave(1) = current 'theta' in the BFGS matrix;
        /// dsave(2) = f(x) in the previous iteration;
        /// dsave(3) = factr*epsmch;
        /// dsave(4) = 2-norm of the line search direction vector;
        /// dsave(5) = the machine precision epsmch generated by the code;
        /// dsave(7) = the accumulated time spent on searching for
        /// Cauchy points;
        /// dsave(8) = the accumulated time spent on
        /// subspace minimization;
        /// dsave(9) = the accumulated time spent on line search;
        /// dsave(11) = the slope of the line search function at
        /// the current point of line search;
        /// dsave(12) = the maximum relative step length imposed in
        /// line search;
        /// dsave(13) = the infinity norm of the projected gradient;
        /// dsave(14) = the relative step length in the line search;
        /// dsave(15) = the slope of the line search function at
        /// the starting point of the line search;
        /// dsave(16) = the square of the 2-norm of the line search
        /// direction vector.
        ///</param>
        public void Run(int N, int M, ref double[] X, int offset_x, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
                        , ref double F, ref double[] G, int offset_g, double FACTR, double PGTOL, ref double[] WA, int offset_wa, ref int[] IWA, int offset_iwa
                        , ref BFGSTask TASK, int IPRINT, ref BFGSTask CSAVE, ref bool[] LSAVE, int offset_lsave, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            int L1 = 0; int L2 = 0; int L3 = 0; int LWS = 0; int LR = 0; int LZ = 0; int LT = 0; int LD = 0; int LSG = 0;
            int LWA = 0; int LYG = 0; int LSGO = 0; int LWY = 0; int LSY = 0; int LSS = 0; int LYY = 0; int LWT = 0; int LWN = 0;
            int LSND = 0; int LYGO = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
            int o_g = -1 + offset_g; int o_wa = -1 + offset_wa;  int o_iwa = -1 + offset_iwa;  int o_lsave = -1 + offset_lsave;
            int o_isave = -1 + offset_isave; int o_dsave = -1 + offset_dsave;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine setulb
            // c
            // c     This subroutine partitions the working arrays wa and iwa, and
            // c       then uses the limited memory BFGS method to solve the bound
            // c       constrained optimization problem by calling mainlb.
            // c       (The direct method will be used in the subspace minimization.)
            // c
            // c     n is an integer variable.
            // c       On entry n is the dimension of the problem.
            // c       On exit n is unchanged.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric corrections
            // c         used to define the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x is an approximation to the solution.
            // c       On exit x is the current approximation.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound on x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound on x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is an integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds, and
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     f is a double precision variable.
            // c       On first entry f is unspecified.
            // c       On final exit f is the value of the function at x.
            // c
            // c     g is a double precision array of dimension n.
            // c       On first entry g is unspecified.
            // c       On final exit g is the value of the gradient at x.
            // c
            // c     factr is a double precision variable.
            // c       On entry factr >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c         (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
            // c
            // c         where epsmch is the machine precision, which is automatically
            // c         generated by the code. Typical values for factr: 1.d+12 for
            // c         low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely
            // c         high accuracy.
            // c       On exit factr is unchanged.
            // c
            // c     pgtol is a double precision variable.
            // c       On entry pgtol >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c                 max{|proj g_i | i = 1, ..., n} <= pgtol
            // c
            // c         where pg_i is the ith component of the projected gradient.
            // c       On exit pgtol is unchanged.
            // c
            // c     wa is a double precision working array of length
            // c       (2mmax + 4)nmax + 12mmax^2 + 12mmax.
            // c
            // c     iwa is an integer working array of length 3nmax.
            // c
            // c     task is a working string of characters of length 60 indicating
            // c       the current job when entering and quitting this subroutine.
            // c
            // c     iprint is an integer variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     csave is a working string of characters of length 60.
            // c
            // c     lsave is a logical working array of dimension 4.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         If lsave(1) = .true.  then  the initial X has been replaced by
            // c                                     its projection in the feasible set;
            // c         If lsave(2) = .true.  then  the problem is constrained;
            // c         If lsave(3) = .true.  then  each variable has upper and lower
            // c                                     bounds;
            // c
            // c     isave is an integer working array of dimension 44.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         isave(22) = the total number of intervals explored in the
            // c                         search of Cauchy points;
            // c         isave(26) = the total number of skipped BFGS updates before
            // c                         the current iteration;
            // c         isave(30) = the number of current iteration;
            // c         isave(31) = the total number of BFGS updates prior the current
            // c                         iteration;
            // c         isave(33) = the number of intervals explored in the search of
            // c                         Cauchy point in the current iteration;
            // c         isave(34) = the total number of function and gradient
            // c                         evaluations;
            // c         isave(36) = the number of function value or gradient
            // c                                  evaluations in the current iteration;
            // c         if isave(37) = 0  then the subspace argmin is within the box;
            // c         if isave(37) = 1  then the subspace argmin is beyond the box;
            // c         isave(38) = the number of free variables in the current
            // c                         iteration;
            // c         isave(39) = the number of active constraints in the current
            // c                         iteration;
            // c         n + 1 - isave(40) = the number of variables leaving the set of
            // c                           active constraints in the current iteration;
            // c         isave(41) = the number of variables entering the set of active
            // c                         constraints in the current iteration.
            // c
            // c     dsave is a double precision working array of dimension 29.
            // c       On exit with 'task' = NEW_X, the following information is
            // c                                                             available:
            // c         dsave(1) = current 'theta' in the BFGS matrix;
            // c         dsave(2) = f(x) in the previous iteration;
            // c         dsave(3) = factr*epsmch;
            // c         dsave(4) = 2-norm of the line search direction vector;
            // c         dsave(5) = the machine precision epsmch generated by the code;
            // c         dsave(7) = the accumulated time spent on searching for
            // c                                                         Cauchy points;
            // c         dsave(8) = the accumulated time spent on
            // c                                                 subspace minimization;
            // c         dsave(9) = the accumulated time spent on line search;
            // c         dsave(11) = the slope of the line search function at
            // c                                  the current point of line search;
            // c         dsave(12) = the maximum relative step length imposed in
            // c                                                           line search;
            // c         dsave(13) = the infinity norm of the projected gradient;
            // c         dsave(14) = the relative step length in the line search;
            // c         dsave(15) = the slope of the line search function at
            // c                                 the starting point of the line search;
            // c         dsave(16) = the square of the 2-norm of the line search
            // c                                                      direction vector.
            // c
            // c     Subprograms called:
            // c
            // c       L-BFGS-B Library ... mainlb.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a
            // c       limited memory FORTRAN code for solving bound constrained
            // c       optimization problems'', Tech. Report, NAM-11, EECS Department,
            // c       Northwestern University, 1994.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            #endregion


            #region Body

            if (TASK == BFGSTask.START)
            {
                ISAVE[1 + o_isave]  = M * N;
                ISAVE[2 + o_isave]  = (int)Math.Pow(M, 2);
                ISAVE[3 + o_isave]  = 4 * (int)Math.Pow(M, 2);
                ISAVE[4 + o_isave]  = 1;
                ISAVE[5 + o_isave]  = ISAVE[4 + o_isave] + ISAVE[1 + o_isave];
                ISAVE[6 + o_isave]  = ISAVE[5 + o_isave] + ISAVE[1 + o_isave];
                ISAVE[7 + o_isave]  = ISAVE[6 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[8 + o_isave]  = ISAVE[7 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[9 + o_isave]  = ISAVE[8 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[10 + o_isave] = ISAVE[9 + o_isave] + ISAVE[2 + o_isave];
                ISAVE[11 + o_isave] = ISAVE[10 + o_isave] + ISAVE[3 + o_isave];
                ISAVE[12 + o_isave] = ISAVE[11 + o_isave] + ISAVE[3 + o_isave];
                ISAVE[13 + o_isave] = ISAVE[12 + o_isave] + N;
                ISAVE[14 + o_isave] = ISAVE[13 + o_isave] + N;
                ISAVE[15 + o_isave] = ISAVE[14 + o_isave] + N;
                ISAVE[16 + o_isave] = ISAVE[15 + o_isave] + N;
                ISAVE[17 + o_isave] = ISAVE[16 + o_isave] + 8 * M;
                ISAVE[18 + o_isave] = ISAVE[17 + o_isave] + M;
                ISAVE[19 + o_isave] = ISAVE[18 + o_isave] + M;
                ISAVE[20 + o_isave] = ISAVE[19 + o_isave] + M;
            }
            L1   = ISAVE[1 + o_isave];
            L2   = ISAVE[2 + o_isave];
            L3   = ISAVE[3 + o_isave];
            LWS  = ISAVE[4 + o_isave];
            LWY  = ISAVE[5 + o_isave];
            LSY  = ISAVE[6 + o_isave];
            LSS  = ISAVE[7 + o_isave];
            LYY  = ISAVE[8 + o_isave];
            LWT  = ISAVE[9 + o_isave];
            LWN  = ISAVE[10 + o_isave];
            LSND = ISAVE[11 + o_isave];
            LZ   = ISAVE[12 + o_isave];
            LR   = ISAVE[13 + o_isave];
            LD   = ISAVE[14 + o_isave];
            LT   = ISAVE[15 + o_isave];
            LWA  = ISAVE[16 + o_isave];
            LSG  = ISAVE[17 + o_isave];
            LSGO = ISAVE[18 + o_isave];
            LYG  = ISAVE[19 + o_isave];
            LYGO = ISAVE[20 + o_isave];

            this._mainlb.Run(N, M, ref X, offset_x, L, offset_l, U, offset_u, NBD, offset_nbd
                             , ref F, ref G, offset_g, FACTR, PGTOL, ref WA, LWS + o_wa, ref WA, LWY + o_wa
                             , ref WA, LSY + o_wa, ref WA, LSS + o_wa, WA, LYY + o_wa, ref WA, LWT + o_wa, ref WA, LWN + o_wa, ref WA, LSND + o_wa
                             , ref WA, LZ + o_wa, ref WA, LR + o_wa, ref WA, LD + o_wa, ref WA, LT + o_wa, ref WA, LWA + o_wa, WA, LSG + o_wa
                             , WA, LSGO + o_wa, WA, LYG + o_wa, WA, LYGO + o_wa, ref IWA, 1 + o_iwa, ref IWA, N + 1 + o_iwa, ref IWA, 2 * N + 1 + o_iwa
                             , ref TASK, IPRINT, ref CSAVE, ref LSAVE, offset_lsave, ref ISAVE, 22 + o_isave, ref DSAVE, offset_dsave);

            return;


            #endregion
        }
Example #11
0
        /// <param name="N">
        /// is an integer variable.
        /// On entry n is the number of variables.
        /// On exit n is unchanged.
        ///</param>
        /// <param name="M">
        /// is an integer variable.
        /// On entry m is the maximum number of variable metric
        /// corrections allowed in the limited memory matrix.
        /// On exit m is unchanged.
        ///</param>
        /// <param name="X">
        /// is a double precision array of dimension n.
        /// On entry x is an approximation to the solution.
        /// On exit x is the current approximation.
        ///</param>
        /// <param name="L">
        /// is a double precision array of dimension n.
        /// On entry l is the lower bound of x.
        /// On exit l is unchanged.
        ///</param>
        /// <param name="U">
        /// is a double precision array of dimension n.
        /// On entry u is the upper bound of x.
        /// On exit u is unchanged.
        ///</param>
        /// <param name="NBD">
        /// is an integer array of dimension n.
        /// On entry nbd represents the type of bounds imposed on the
        /// variables, and must be specified as follows:
        /// nbd(i)=0 if x(i) is unbounded,
        /// 1 if x(i) has only a lower bound,
        /// 2 if x(i) has both lower and upper bounds,
        /// 3 if x(i) has only an upper bound.
        /// On exit nbd is unchanged.
        ///</param>
        /// <param name="F">
        /// is a double precision variable.
        /// On first entry f is unspecified.
        /// On final exit f is the value of the function at x.
        ///</param>
        /// <param name="G">
        /// is a double precision array of dimension n.
        /// On first entry g is unspecified.
        /// On final exit g is the value of the gradient at x.
        ///</param>
        /// <param name="FACTR">
        /// is a double precision variable.
        /// On entry factr .GE. 0 is specified by the user.  The iteration
        /// will stop when
        ///
        /// (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} .LE. factr*epsmch
        ///
        /// where epsmch is the machine precision, which is automatically
        /// generated by the code.
        /// On exit factr is unchanged.
        ///</param>
        /// <param name="PGTOL">
        /// is a double precision variable.
        /// On entry pgtol .GE. 0 is specified by the user.  The iteration
        /// will stop when
        ///
        /// max{|proj g_i | i = 1, ..., n} .LE. pgtol
        ///
        /// where pg_i is the ith component of the projected gradient.
        /// On exit pgtol is unchanged.
        ///</param>
        /// <param name="WN">
        /// is a double precision working array of dimension 2m x 2m
        /// used to store the LEL^T factorization of the indefinite matrix
        /// K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
        /// [L_a -R_z           theta*S'AA'S ]
        ///
        /// where     E = [-I  0]
        /// [ 0  I]
        ///</param>
        /// <param name="SND">
        /// is a double precision working array of dimension 2m x 2m
        /// used to store the lower triangular part of
        /// N = [Y' ZZ'Y   L_a'+R_z']
        /// [L_a +R_z  S'AA'S   ]
        ///</param>
        /// <param name="Z">
        /// is used at different times to store the Cauchy point and
        ///</param>
        /// <param name="INDEX">
        /// is an integer working array of dimension n.
        /// In subroutine freev, index is used to store the free and fixed
        /// variables at the Generalized Cauchy Point (GCP).
        ///</param>
        /// <param name="IWHERE">
        /// is an integer working array of dimension n used to record
        /// the status of the vector x for GCP computation.
        /// iwhere(i)=0 or -3 if x(i) is free and has bounds,
        /// 1       if x(i) is fixed at l(i), and l(i) .ne. u(i)
        /// 2       if x(i) is fixed at u(i), and u(i) .ne. l(i)
        /// 3       if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
        /// -1       if x(i) is always free, i.e., no bounds on it.
        ///</param>
        /// <param name="INDX2">
        /// is an integer working array of dimension n.
        /// Within subroutine cauchy, indx2 corresponds to the array iorder.
        /// In subroutine freev, a list of variables entering and leaving
        /// the free set is stored in indx2, and it is passed on to
        /// subroutine formk with this information.
        ///</param>
        /// <param name="TASK">
        /// is a working string of characters of length 60 indicating
        /// the current job when entering and leaving this subroutine.
        ///</param>
        /// <param name="IPRINT">
        /// is an INTEGER variable that must be set by the user.
        /// It controls the frequency and type of output generated:
        /// iprint.LT.0    no output is generated;
        /// iprint=0    print only one line at the last iteration;
        /// 0.LT.iprint.LT.99 print also f and |proj g| every iprint iterations;
        /// iprint=99   print details of every iteration except n-vectors;
        /// iprint=100  print also the changes of active set and final x;
        /// iprint.GT.100  print details of every iteration including x and g;
        /// When iprint .GT. 0, the file iterate.dat will be created to
        /// summarize the iteration.
        ///</param>
        /// <param name="CSAVE">
        /// is a working string of characters of length 60.
        ///</param>
        /// <param name="LSAVE">
        /// is a logical working array of dimension 4.
        ///</param>
        /// <param name="ISAVE">
        /// is an integer working array of dimension 23.
        ///</param>
        /// <param name="DSAVE">
        /// is a double precision working array of dimension 29.
        ///
        ///</param>
        public void Run(int N, int M, ref double[] X, int offset_x, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd
                        , ref double F, ref double[] G, int offset_g, double FACTR, double PGTOL, ref double[] WS, int offset_ws, ref double[] WY, int offset_wy
                        , ref double[] SY, int offset_sy, ref double[] SS, int offset_ss, double[] YY, int offset_yy, ref double[] WT, int offset_wt, ref double[] WN, int offset_wn, ref double[] SND, int offset_snd
                        , ref double[] Z, int offset_z, ref double[] R, int offset_r, ref double[] D, int offset_d, ref double[] T, int offset_t, ref double[] WA, int offset_wa, double[] SG, int offset_sg
                        , double[] SGO, int offset_sgo, double[] YG, int offset_yg, double[] YGO, int offset_ygo, ref int[] INDEX, int offset_index, ref int[] IWHERE, int offset_iwhere, ref int[] INDX2, int offset_indx2
                        , ref BFGSTask TASK, int IPRINT, ref BFGSTask CSAVE, ref bool[] LSAVE, int offset_lsave, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            BFGSWord WORD = BFGSWord.aaa;

            bool   PRJCTD = false; bool CNSTND = false; bool BOXED = false; bool UPDATD = false; bool WRK = false;
            int    I = 0; int K = 0; int NINTOL = 0; int ITFILE = 0; int IBACK = 0; int NSKIP = 0;
            int    HEAD = 0; int COL = 0; int ITER = 0; int ITAIL = 0; int IUPDAT = 0; int NINT = 0; int NFGV = 0; int INFO = 0;
            int    IFUN = 0; int IWORD = 0; int NFREE = 0; int NACT = 0; int ILEAVE = 0; int NENTER = 0; double THETA = 0;
            double FOLD = 0; double DDOT = 0; double DR = 0; double RR = 0; double TOL = 0; double DPMEPS = 0; double XSTEP = 0;
            double SBGNRM = 0; double DDUM = 0; double DNORM = 0; double DTD = 0; double EPSMCH = 0; double CPU1 = 0;
            double CPU2 = 0; double CACHYT = 0; double SBTIME = 0; double LNSCHT = 0; double TIME1 = 0; double TIME2 = 0;
            double GD = 0; double GDOLD = 0; double STP = 0; double STPMX = 0; double TIME = 0;

            #endregion


            #region Array Index Correction

            int o_x = -1 + offset_x;  int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;
            int o_g = -1 + offset_g; int o_ws = -1 - N + offset_ws;  int o_wy = -1 - N + offset_wy;
            int o_sy = -1 - M + offset_sy; int o_ss = -1 - M + offset_ss;  int o_yy = -1 - M + offset_yy;
            int o_wt = -1 - M + offset_wt; int o_wn = -1 - (2 * M) + offset_wn;  int o_snd = -1 - (2 * M) + offset_snd;
            int o_z = -1 + offset_z; int o_r = -1 + offset_r;  int o_d = -1 + offset_d;  int o_t = -1 + offset_t;
            int o_wa = -1 + offset_wa; int o_sg = -1 + offset_sg;  int o_sgo = -1 + offset_sgo;  int o_yg = -1 + offset_yg;
            int o_ygo = -1 + offset_ygo; int o_index = -1 + offset_index;  int o_iwhere = -1 + offset_iwhere;
            int o_indx2 = -1 + offset_indx2; int o_lsave = -1 + offset_lsave;  int o_isave = -1 + offset_isave;
            int o_dsave = -1 + offset_dsave;

            #endregion


            #region Prolog



            // c     ************
            // c
            // c     Subroutine mainlb
            // c
            // c     This subroutine solves bound constrained optimization problems by
            // c       using the compact formula of the limited memory BFGS updates.
            // c
            // c     n is an integer variable.
            // c       On entry n is the number of variables.
            // c       On exit n is unchanged.
            // c
            // c     m is an integer variable.
            // c       On entry m is the maximum number of variable metric
            // c          corrections allowed in the limited memory matrix.
            // c       On exit m is unchanged.
            // c
            // c     x is a double precision array of dimension n.
            // c       On entry x is an approximation to the solution.
            // c       On exit x is the current approximation.
            // c
            // c     l is a double precision array of dimension n.
            // c       On entry l is the lower bound of x.
            // c       On exit l is unchanged.
            // c
            // c     u is a double precision array of dimension n.
            // c       On entry u is the upper bound of x.
            // c       On exit u is unchanged.
            // c
            // c     nbd is an integer array of dimension n.
            // c       On entry nbd represents the type of bounds imposed on the
            // c         variables, and must be specified as follows:
            // c         nbd(i)=0 if x(i) is unbounded,
            // c                1 if x(i) has only a lower bound,
            // c                2 if x(i) has both lower and upper bounds,
            // c                3 if x(i) has only an upper bound.
            // c       On exit nbd is unchanged.
            // c
            // c     f is a double precision variable.
            // c       On first entry f is unspecified.
            // c       On final exit f is the value of the function at x.
            // c
            // c     g is a double precision array of dimension n.
            // c       On first entry g is unspecified.
            // c       On final exit g is the value of the gradient at x.
            // c
            // c     factr is a double precision variable.
            // c       On entry factr >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c         (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch
            // c
            // c         where epsmch is the machine precision, which is automatically
            // c         generated by the code.
            // c       On exit factr is unchanged.
            // c
            // c     pgtol is a double precision variable.
            // c       On entry pgtol >= 0 is specified by the user.  The iteration
            // c         will stop when
            // c
            // c                 max{|proj g_i | i = 1, ..., n} <= pgtol
            // c
            // c         where pg_i is the ith component of the projected gradient.
            // c       On exit pgtol is unchanged.
            // c
            // c     ws, wy, sy, and wt are double precision working arrays used to
            // c       store the following information defining the limited memory
            // c          BFGS matrix:
            // c          ws, of dimension n x m, stores S, the matrix of s-vectors;
            // c          wy, of dimension n x m, stores Y, the matrix of y-vectors;
            // c          sy, of dimension m x m, stores S'Y;
            // c          ss, of dimension m x m, stores S'S;
            // c	   yy, of dimension m x m, stores Y'Y;
            // c          wt, of dimension m x m, stores the Cholesky factorization
            // c                                  of (theta*S'S+LD^(-1)L'); see eq.
            // c                                  (2.26) in [3].
            // c
            // c     wn is a double precision working array of dimension 2m x 2m
            // c       used to store the LEL^T factorization of the indefinite matrix
            // c                 K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c
            // c       where     E = [-I  0]
            // c                     [ 0  I]
            // c
            // c     snd is a double precision working array of dimension 2m x 2m
            // c       used to store the lower triangular part of
            // c                 N = [Y' ZZ'Y   L_a'+R_z']
            // c                     [L_a +R_z  S'AA'S   ]
            // c
            // c     z(n),r(n),d(n),t(n),wa(8*m) are double precision working arrays.
            // c       z is used at different times to store the Cauchy point and
            // c       the Newton point.
            // c
            // c     sg(m),sgo(m),yg(m),ygo(m) are double precision working arrays.
            // c
            // c     index is an integer working array of dimension n.
            // c       In subroutine freev, index is used to store the free and fixed
            // c          variables at the Generalized Cauchy Point (GCP).
            // c
            // c     iwhere is an integer working array of dimension n used to record
            // c       the status of the vector x for GCP computation.
            // c       iwhere(i)=0 or -3 if x(i) is free and has bounds,
            // c                 1       if x(i) is fixed at l(i), and l(i) .ne. u(i)
            // c                 2       if x(i) is fixed at u(i), and u(i) .ne. l(i)
            // c                 3       if x(i) is always fixed, i.e.,  u(i)=x(i)=l(i)
            // c                -1       if x(i) is always free, i.e., no bounds on it.
            // c
            // c     indx2 is an integer working array of dimension n.
            // c       Within subroutine cauchy, indx2 corresponds to the array iorder.
            // c       In subroutine freev, a list of variables entering and leaving
            // c       the free set is stored in indx2, and it is passed on to
            // c       subroutine formk with this information.
            // c
            // c     task is a working string of characters of length 60 indicating
            // c       the current job when entering and leaving this subroutine.
            // c
            // c     iprint is an INTEGER variable that must be set by the user.
            // c       It controls the frequency and type of output generated:
            // c        iprint<0    no output is generated;
            // c        iprint=0    print only one line at the last iteration;
            // c        0<iprint<99 print also f and |proj g| every iprint iterations;
            // c        iprint=99   print details of every iteration except n-vectors;
            // c        iprint=100  print also the changes of active set and final x;
            // c        iprint>100  print details of every iteration including x and g;
            // c       When iprint > 0, the file iterate.dat will be created to
            // c                        summarize the iteration.
            // c
            // c     csave is a working string of characters of length 60.
            // c
            // c     lsave is a logical working array of dimension 4.
            // c
            // c     isave is an integer working array of dimension 23.
            // c
            // c     dsave is a double precision working array of dimension 29.
            // c
            // c
            // c     Subprograms called
            // c
            // c       L-BFGS-B Library ... cauchy, subsm, lnsrlb, formk,
            // c
            // c        errclb, prn1lb, prn2lb, prn3lb, active, projgr,
            // c
            // c        freev, cmprlb, matupd, formt.
            // c
            // c       Minpack2 Library ... timer, dpmeps.
            // c
            // c       Linpack Library ... dcopy, ddot.
            // c
            // c
            // c     References:
            // c
            // c       [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
            // c       memory algorithm for bound constrained optimization'',
            // c       SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
            // c
            // c       [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
            // c       Subroutines for Large Scale Bound Constrained Optimization''
            // c       Tech. Report, NAM-11, EECS Department, Northwestern University,
            // c       1994.
            // c
            // c       [3] R. Byrd, J. Nocedal and R. Schnabel "Representations of
            // c       Quasi-Newton Matrices and their use in Limited Memory Methods'',
            // c       Mathematical Programming 63 (1994), no. 4, pp. 129-156.
            // c
            // c       (Postscript files of these papers are available via anonymous
            // c        ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************



            #endregion


            #region Body

            if (TASK == BFGSTask.START)
            {
                this._timer.Run(ref TIME1);

                // c        Generate the current machine precision.

                EPSMCH = this._dpmeps.Run();

                // c        Initialize counters and scalars when task='START'.

                // c           for the limited memory BFGS matrices:
                COL    = 0;
                HEAD   = 1;
                THETA  = ONE;
                IUPDAT = 0;
                UPDATD = false;

                // c           for operation counts:
                ITER   = 0;
                NFGV   = 0;
                NINT   = 0;
                NINTOL = 0;
                NSKIP  = 0;
                NFREE  = N;

                // c           for stopping tolerance:
                TOL = FACTR * EPSMCH;

                // c           for measuring running time:
                CACHYT = 0;
                SBTIME = 0;
                LNSCHT = 0;

                // c           'word' records the status of subspace solutions.
                WORD = BFGSWord.aaa;

                // c           'info' records the termination information.
                INFO = 0;

                if (IPRINT >= 1)
                {
                    // c                                open a summary file 'iterate.dat'
                    //ERROR-ERROR            OPEN (8, FILE = 'iterate.dat', STATUS = 'unknown');
                    ITFILE = 8;
                }

                // c        Check the input arguments for errors.

                this._errclb.Run(N, M, FACTR, L, offset_l, U, offset_u, NBD, offset_nbd
                                 , ref TASK, ref INFO, ref K);
                if (TASK == BFGSTask.ERROR)
                {
                    this._prn3lb.Run(N, X, offset_x, F, TASK, IPRINT, INFO
                                     , ITFILE, ITER, NFGV, NINTOL, NSKIP, NACT
                                     , SBGNRM, ZERO, NINT, WORD, IBACK, STP
                                     , XSTEP, K, CACHYT, SBTIME, LNSCHT);
                    return;
                }

                this._prn1lb.Run(N, M, L, offset_l, U, offset_u, X, offset_x, IPRINT
                                 , ITFILE, EPSMCH);

                // c        Initialize iwhere & project x onto the feasible set.

                this._active.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, ref X, offset_x, ref IWHERE, offset_iwhere
                                 , IPRINT, ref PRJCTD, ref CNSTND, ref BOXED);

                // c        The end of the initialization.
            }
            else
            {
                // c          restore local variables.

                PRJCTD = LSAVE[1 + o_lsave];
                CNSTND = LSAVE[2 + o_lsave];
                BOXED  = LSAVE[3 + o_lsave];
                UPDATD = LSAVE[4 + o_lsave];

                NINTOL = ISAVE[1 + o_isave];
                ITFILE = ISAVE[3 + o_isave];
                IBACK  = ISAVE[4 + o_isave];
                NSKIP  = ISAVE[5 + o_isave];
                HEAD   = ISAVE[6 + o_isave];
                COL    = ISAVE[7 + o_isave];
                ITAIL  = ISAVE[8 + o_isave];
                ITER   = ISAVE[9 + o_isave];
                IUPDAT = ISAVE[10 + o_isave];
                NINT   = ISAVE[12 + o_isave];
                NFGV   = ISAVE[13 + o_isave];
                INFO   = ISAVE[14 + o_isave];
                IFUN   = ISAVE[15 + o_isave];
                IWORD  = ISAVE[16 + o_isave];
                NFREE  = ISAVE[17 + o_isave];
                NACT   = ISAVE[18 + o_isave];
                ILEAVE = ISAVE[19 + o_isave];
                NENTER = ISAVE[20 + o_isave];

                THETA  = DSAVE[1 + o_dsave];
                FOLD   = DSAVE[2 + o_dsave];
                TOL    = DSAVE[3 + o_dsave];
                DNORM  = DSAVE[4 + o_dsave];
                EPSMCH = DSAVE[5 + o_dsave];
                CPU1   = DSAVE[6 + o_dsave];
                CACHYT = DSAVE[7 + o_dsave];
                SBTIME = DSAVE[8 + o_dsave];
                LNSCHT = DSAVE[9 + o_dsave];
                TIME1  = DSAVE[10 + o_dsave];
                GD     = DSAVE[11 + o_dsave];
                STPMX  = DSAVE[12 + o_dsave];
                SBGNRM = DSAVE[13 + o_dsave];
                STP    = DSAVE[14 + o_dsave];
                GDOLD  = DSAVE[15 + o_dsave];
                DTD    = DSAVE[16 + o_dsave];

                // c        After returning from the driver go to the point where execution
                // c        is to resume.

                if (TASK == BFGSTask.FG_LNSRCH)
                {
                    goto LABEL666;
                }
                if (TASK == BFGSTask.NEW_X)
                {
                    goto LABEL777;
                }
                if (TASK == BFGSTask.FG_ST || TASK == BFGSTask.FG_START)
                {
                    goto LABEL111;
                }
                if (TASK == BFGSTask.STOP)
                {
                    if (TASK == BFGSTask.CPU)
                    {
                        // c                                          restore the previous iterate.
                        this._dcopy.Run(N, T, offset_t, 1, ref X, offset_x, 1);
                        this._dcopy.Run(N, R, offset_r, 1, ref G, offset_g, 1);
                        F = FOLD;
                    }
                    goto LABEL999;
                }
            }

            // c     Compute f0 and g0.

            TASK = BFGSTask.FG_START;
            // c          return to the driver to calculate f and g; reenter at 111.
            goto LABEL1000;
            LABEL111 :;
            NFGV = 1;

            // c     Compute the infinity norm of the (-) projected gradient.

            this._projgr.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, X, offset_x, G, offset_g
                             , ref SBGNRM);

            if (IPRINT >= 1)
            {
                //ERROR-ERROR         WRITE (6,1002) ITER,F,SBGNRM;
                //ERROR-ERROR         WRITE (ITFILE,1003) ITER,NFGV,SBGNRM,F;
            }
            if (SBGNRM <= PGTOL)
            {
                // c                                terminate the algorithm.
                TASK = BFGSTask.CONV;
                goto LABEL999;
            }

            // c ----------------- the beginning of the loop --------------------------

            LABEL222 :;
            if (IPRINT >= 99)
            {
                ;              //ERROR-ERRORWRITE(6,1001)ITER+1
            }
            IWORD = -1;
            // c
            if (!CNSTND && COL > 0)
            {
                // c                                            skip the search for GCP.
                this._dcopy.Run(N, X, offset_x, 1, ref Z, offset_z, 1);
                WRK  = UPDATD;
                NINT = 0;
                goto LABEL333;
            }

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Compute the Generalized Cauchy Point (GCP).
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            this._timer.Run(ref CPU1);
            this._cauchy.Run(N, X, offset_x, L, offset_l, U, offset_u, NBD, offset_nbd, G, offset_g
                             , ref INDX2, offset_indx2, ref IWHERE, offset_iwhere, ref T, offset_t, ref D, offset_d, ref Z, offset_z, M
                             , WY, offset_wy, WS, offset_ws, SY, offset_sy, WT, offset_wt, THETA, COL
                             , HEAD, ref WA, 1 + o_wa, ref WA, 2 * M + 1 + o_wa, ref WA, 4 * M + 1 + o_wa, ref WA, 6 * M + 1 + o_wa, ref NINT
                             , SG, offset_sg, YG, offset_yg, IPRINT, SBGNRM, ref INFO, EPSMCH);
            if (INFO != 0)
            {
                // c         singular triangular system detected; refresh the lbfgs memory.
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,1005)
                }
                INFO   = 0;
                COL    = 0;
                HEAD   = 1;
                THETA  = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                CACHYT += CPU2 - CPU1;
                goto LABEL222;
            }
            this._timer.Run(ref CPU2);
            CACHYT += CPU2 - CPU1;
            NINTOL += NINT;

            // c     Count the entering and leaving variables for iter > 0;
            // c     find the index set of free and active variables at the GCP.

            this._freev.Run(N, ref NFREE, ref INDEX, offset_index, ref NENTER, ref ILEAVE, ref INDX2, offset_indx2
                            , IWHERE, offset_iwhere, ref WRK, UPDATD, CNSTND, IPRINT, ITER);

            NACT = N - NFREE;

            LABEL333 :;

            // c     If there are no free variables or B=theta*I, then
            // c                                        skip the subspace minimization.

            if (NFREE == 0 || COL == 0)
            {
                goto LABEL555;
            }

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Subspace minimization.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            this._timer.Run(ref CPU1);

            // c     Form  the LEL^T factorization of the indefinite
            // c       matrix    K = [-D -Y'ZZ'Y/theta     L_a'-R_z'  ]
            // c                     [L_a -R_z           theta*S'AA'S ]
            // c       where     E = [-I  0]
            // c                     [ 0  I]

            if (WRK)
            {
                this._formk.Run(N, NFREE, INDEX, offset_index, NENTER, ILEAVE, INDX2, offset_indx2
                                , IUPDAT, UPDATD, ref WN, offset_wn, ref SND, offset_snd, M, WS, offset_ws
                                , WY, offset_wy, SY, offset_sy, THETA, COL, HEAD, ref INFO);
            }
            if (INFO != 0)
            {
                // c          nonpositive definiteness in Cholesky factorization;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,1006)
                }
                INFO   = 0;
                COL    = 0;
                HEAD   = 1;
                THETA  = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                SBTIME += CPU2 - CPU1;
                goto LABEL222;
            }

            // c        compute r=-Z'B(xcp-xk)-Z'g (using wa(2m+1)=W'(xcp-x)
            // c                                                   from 'cauchy').
            this._cmprlb.Run(N, M, X, offset_x, G, offset_g, WS, offset_ws, WY, offset_wy
                             , SY, offset_sy, WT, offset_wt, Z, offset_z, ref R, offset_r, ref WA, offset_wa, INDEX, offset_index
                             , THETA, COL, HEAD, NFREE, CNSTND, ref INFO);
            if (INFO != 0)
            {
                goto LABEL444;
            }
            // c       call the direct method.
            this._subsm.Run(N, M, NFREE, INDEX, offset_index, L, offset_l, U, offset_u
                            , NBD, offset_nbd, ref Z, offset_z, ref R, offset_r, WS, offset_ws, WY, offset_wy, THETA
                            , COL, HEAD, ref IWORD, ref WA, offset_wa, WN, offset_wn, IPRINT
                            , ref INFO);
            LABEL444 :;
            if (INFO != 0)
            {
                // c          singular triangular system detected;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,1005)
                }
                INFO   = 0;
                COL    = 0;
                HEAD   = 1;
                THETA  = ONE;
                IUPDAT = 0;
                UPDATD = false;
                this._timer.Run(ref CPU2);
                SBTIME += CPU2 - CPU1;
                goto LABEL222;
            }

            this._timer.Run(ref CPU2);
            SBTIME += CPU2 - CPU1;
            LABEL555 :;

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Line search and optimality tests.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            // c     Generate the search direction d:=z-x.

            for (I = 1; I <= N; I++)
            {
                D[I + o_d] = Z[I + o_z] - X[I + o_x];
            }
            this._timer.Run(ref CPU1);
            LABEL666 :;
            this._lnsrlb.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, ref X, offset_x, F
                             , ref FOLD, ref GD, ref GDOLD, G, offset_g, D, offset_d, ref R, offset_r
                             , ref T, offset_t, Z, offset_z, ref STP, ref DNORM, ref DTD, ref XSTEP
                             , ref STPMX, ITER, ref IFUN, ref IBACK, ref NFGV, ref INFO
                             , ref TASK, BOXED, CNSTND, ref CSAVE, ref ISAVE, 22 + o_isave, ref DSAVE, 17 + o_dsave);
            if (INFO != 0 || IBACK >= 20)
            {
                // c          restore the previous iterate.
                this._dcopy.Run(N, T, offset_t, 1, ref X, offset_x, 1);
                this._dcopy.Run(N, R, offset_r, 1, ref G, offset_g, 1);
                F = FOLD;
                if (COL == 0)
                {
                    // c             abnormal termination.
                    if (INFO == 0)
                    {
                        INFO = -9;
                        // c                restore the actual number of f and g evaluations etc.
                        NFGV  -= 1;
                        IFUN  -= 1;
                        IBACK -= 1;
                    }
                    TASK  = BFGSTask.ABNO;
                    ITER += 1;
                    goto LABEL999;
                }
                else
                {
                    // c             refresh the lbfgs memory and restart the iteration.
                    if (IPRINT >= 1)
                    {
                        ;             //ERROR-ERRORWRITE(6,1008)
                    }
                    if (INFO == 0)
                    {
                        NFGV -= 1;
                    }
                    INFO   = 0;
                    COL    = 0;
                    HEAD   = 1;
                    THETA  = ONE;
                    IUPDAT = 0;
                    UPDATD = false;
                    TASK   = BFGSTask.RESTART;
                    this._timer.Run(ref CPU2);
                    LNSCHT += CPU2 - CPU1;
                    goto LABEL222;
                }
            }
            else
            {
                if (TASK == BFGSTask.FG_LNSRCH)
                {
                    // c          return to the driver for calculating f and g; reenter at 666.
                    goto LABEL1000;
                }
                else
                {
                    // c          calculate and print out the quantities related to the new X.
                    this._timer.Run(ref CPU2);
                    LNSCHT += CPU2 - CPU1;
                    ITER   += 1;

                    // c        Compute the infinity norm of the projected (-)gradient.

                    this._projgr.Run(N, L, offset_l, U, offset_u, NBD, offset_nbd, X, offset_x, G, offset_g
                                     , ref SBGNRM);

                    // c        Print iteration information.

                    this._prn2lb.Run(N, X, offset_x, F, G, offset_g, IPRINT, ITFILE
                                     , ITER, NFGV, NACT, SBGNRM, NINT, ref WORD
                                     , IWORD, IBACK, STP, XSTEP);
                    goto LABEL1000;
                }
            }
            LABEL777 :;

            // c     Test for termination.

            if (SBGNRM <= PGTOL)
            {
                // c                                terminate the algorithm.
                TASK = BFGSTask.CONV;
                goto LABEL999;
            }

            DDUM = Math.Max(Math.Abs(FOLD), Math.Max(Math.Abs(F), ONE));
            if ((FOLD - F) <= TOL * DDUM)
            {
                // c                                        terminate the algorithm.
                TASK = BFGSTask.CONV;
                if (IBACK >= 10)
                {
                    INFO = -5;
                }
                // c           i.e., to issue a warning if iback>10 in the line search.
                goto LABEL999;
            }

            // c     Compute d=newx-oldx, r=newg-oldg, rr=y'y and dr=y's.

            for (I = 1; I <= N; I++)
            {
                R[I + o_r] = G[I + o_g] - R[I + o_r];
            }
            RR = this._ddot.Run(N, R, offset_r, 1, R, offset_r, 1);
            if (STP == ONE)
            {
                DR   = GD - GDOLD;
                DDUM = -GDOLD;
            }
            else
            {
                DR = (GD - GDOLD) * STP;
                this._dscal.Run(N, STP, ref D, offset_d, 1);
                DDUM = -GDOLD * STP;
            }

            if (DR <= EPSMCH * DDUM)
            {
                // c                            skip the L-BFGS update.
                NSKIP += 1;
                UPDATD = false;
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,1004)DR,DDUM
                }
                goto LABEL888;
            }

            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
            // c
            // c     Update the L-BFGS matrix.
            // c
            // cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc

            UPDATD  = true;
            IUPDAT += 1;

            // c     Update matrices WS and WY and form the middle matrix in B.

            this._matupd.Run(N, M, ref WS, offset_ws, ref WY, offset_wy, ref SY, offset_sy, ref SS, offset_ss
                             , D, offset_d, R, offset_r, ref ITAIL, IUPDAT, ref COL, ref HEAD
                             , ref THETA, RR, DR, STP, DTD);

            // c     Form the upper half of the pds T = theta*SS + L*D^(-1)*L';
            // c        Store T in the upper triangular of the array wt;
            // c        Cholesky factorize T to J*J' with
            // c           J' stored in the upper triangular of wt.

            this._formt.Run(M, ref WT, offset_wt, SY, offset_sy, SS, offset_ss, COL, THETA
                            , ref INFO);

            if (INFO != 0)
            {
                // c          nonpositive definiteness in Cholesky factorization;
                // c          refresh the lbfgs memory and restart the iteration.
                if (IPRINT >= 1)
                {
                    ;             //ERROR-ERRORWRITE(6,1007)
                }
                INFO   = 0;
                COL    = 0;
                HEAD   = 1;
                THETA  = ONE;
                IUPDAT = 0;
                UPDATD = false;
                goto LABEL222;
            }

            // c     Now the inverse of the middle matrix in B is

            // c       [  D^(1/2)      O ] [ -D^(1/2)  D^(-1/2)*L' ]
            // c       [ -L*D^(-1/2)   J ] [  0        J'          ]

            LABEL888 :;

            // c -------------------- the end of the loop -----------------------------

            goto LABEL222;
            LABEL999 :;
            this._timer.Run(ref TIME2);
            TIME = TIME2 - TIME1;
            this._prn3lb.Run(N, X, offset_x, F, TASK, IPRINT, INFO
                             , ITFILE, ITER, NFGV, NINTOL, NSKIP, NACT
                             , SBGNRM, TIME, NINT, WORD, IBACK, STP
                             , XSTEP, K, CACHYT, SBTIME, LNSCHT);
            LABEL1000 :;

            // c     Save local variables.

            LSAVE[1 + o_lsave] = PRJCTD;
            LSAVE[2 + o_lsave] = CNSTND;
            LSAVE[3 + o_lsave] = BOXED;
            LSAVE[4 + o_lsave] = UPDATD;

            ISAVE[1 + o_isave]  = NINTOL;
            ISAVE[3 + o_isave]  = ITFILE;
            ISAVE[4 + o_isave]  = IBACK;
            ISAVE[5 + o_isave]  = NSKIP;
            ISAVE[6 + o_isave]  = HEAD;
            ISAVE[7 + o_isave]  = COL;
            ISAVE[8 + o_isave]  = ITAIL;
            ISAVE[9 + o_isave]  = ITER;
            ISAVE[10 + o_isave] = IUPDAT;
            ISAVE[12 + o_isave] = NINT;
            ISAVE[13 + o_isave] = NFGV;
            ISAVE[14 + o_isave] = INFO;
            ISAVE[15 + o_isave] = IFUN;
            ISAVE[16 + o_isave] = IWORD;
            ISAVE[17 + o_isave] = NFREE;
            ISAVE[18 + o_isave] = NACT;
            ISAVE[19 + o_isave] = ILEAVE;
            ISAVE[20 + o_isave] = NENTER;

            DSAVE[1 + o_dsave]  = THETA;
            DSAVE[2 + o_dsave]  = FOLD;
            DSAVE[3 + o_dsave]  = TOL;
            DSAVE[4 + o_dsave]  = DNORM;
            DSAVE[5 + o_dsave]  = EPSMCH;
            DSAVE[6 + o_dsave]  = CPU1;
            DSAVE[7 + o_dsave]  = CACHYT;
            DSAVE[8 + o_dsave]  = SBTIME;
            DSAVE[9 + o_dsave]  = LNSCHT;
            DSAVE[10 + o_dsave] = TIME1;
            DSAVE[11 + o_dsave] = GD;
            DSAVE[12 + o_dsave] = STPMX;
            DSAVE[13 + o_dsave] = SBGNRM;
            DSAVE[14 + o_dsave] = STP;
            DSAVE[15 + o_dsave] = GDOLD;
            DSAVE[16 + o_dsave] = DTD;


            return;


            #endregion
        }
Example #12
0
        public void Run(int N, double[] X, int offset_x, double F, BFGSTask TASK, int IPRINT, int INFO
            , int ITFILE, int ITER, int NFGV, int NINTOL, int NSKIP, int NACT
            , double SBGNRM, double TIME, int NINT, BFGSWord WORD, int IBACK, double STP
            , double XSTEP, int K, double CACHYT, double SBTIME, double LNSCHT)
        {
            #region Variables

            int I = 0;

            #endregion

            #region Array Index Correction

             int o_x = -1 + offset_x;

            #endregion

            #region Prolog

            // c     ************
            // c
            // c     Subroutine prn3lb
            // c
            // c     This subroutine prints out information when either a built-in
            // c       convergence test is satisfied or when an error message is
            // c       generated.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     ************

            #endregion

            #region Body

            if (TASK == BFGSTask.ERROR) goto LABEL999;

            if (IPRINT >= 0)
            {
                //ERROR-ERROR         WRITE (6,3003);
                //ERROR-ERROR         WRITE (6,3004);
                //ERROR-ERROR         WRITE(6,3005) N,ITER,NFGV,NINTOL,NSKIP,NACT,SBGNRM,F;
                if (IPRINT >= 100)
                {
                    //ERROR-ERROR            WRITE (6,1004) 'X =',(X(I),I = 1,N);
                }
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,*)' F =',F
            }
            LABEL999:;
            if (IPRINT >= 0)
            {
                //ERROR-ERROR         WRITE (6,3009) TASK;
                if (INFO != 0)
                {
                    if (INFO ==  - 1) ;//ERROR-ERRORWRITE(6,9011)
                    if (INFO ==  - 2) ;//ERROR-ERRORWRITE(6,9012)
                    if (INFO ==  - 3) ;//ERROR-ERRORWRITE(6,9013)
                    if (INFO ==  - 4) ;//ERROR-ERRORWRITE(6,9014)
                    if (INFO ==  - 5) ;//ERROR-ERRORWRITE(6,9015)
                    if (INFO ==  - 6) ;//ERROR-ERRORWRITE(6,*)' Input nbd(',K,') is invalid.'
                    if (INFO ==  - 7) ;//ERROR-ERRORWRITE(6,*)' l(',K,') > u(',K,').  No feasible solution.'
                    if (INFO ==  - 8) ;//ERROR-ERRORWRITE(6,9018)
                    if (INFO ==  - 9) ;//ERROR-ERRORWRITE(6,9019)
                }
                if (IPRINT >= 1) ;//ERROR-ERRORWRITE(6,3007)CACHYT,SBTIME,LNSCHT
                //ERROR-ERROR         WRITE (6,3008) TIME;
                if (IPRINT >= 1)
                {
                    if (INFO ==  - 4 || INFO ==  - 9)
                    {
                        //ERROR-ERROR               WRITE (ITFILE,3002)ITER,NFGV,NINT,NACT,WORD,IBACK,STP,XSTEP;
                    }
                    //ERROR-ERROR            WRITE (ITFILE,3009) TASK;
                    if (INFO != 0)
                    {
                        if (INFO ==  - 1) ;//ERROR-ERRORWRITE(ITFILE,9011)
                        if (INFO ==  - 2) ;//ERROR-ERRORWRITE(ITFILE,9012)
                        if (INFO ==  - 3) ;//ERROR-ERRORWRITE(ITFILE,9013)
                        if (INFO ==  - 4) ;//ERROR-ERRORWRITE(ITFILE,9014)
                        if (INFO ==  - 5) ;//ERROR-ERRORWRITE(ITFILE,9015)
                        if (INFO ==  - 8) ;//ERROR-ERRORWRITE(ITFILE,9018)
                        if (INFO ==  - 9) ;//ERROR-ERRORWRITE(ITFILE,9019)
                    }
                    //ERROR-ERROR            WRITE (ITFILE,3008) TIME;
                }
            }

            return;

            #endregion
        }
Example #13
0
        public void Run(int N, double[] L, int offset_l, double[] U, int offset_u, int[] NBD, int offset_nbd, ref double[] X, int offset_x, double F
                        , ref double FOLD, ref double GD, ref double GDOLD, double[] G, int offset_g, double[] D, int offset_d, ref double[] R, int offset_r
                        , ref double[] T, int offset_t, double[] Z, int offset_z, ref double STP, ref double DNORM, ref double DTD, ref double XSTEP
                        , ref double STPMX, int ITER, ref int IFUN, ref int IBACK, ref int NFGV, ref int INFO
                        , ref BFGSTask TASK, bool BOXED, bool CNSTND, ref BFGSTask CSAVE, ref int[] ISAVE, int offset_isave, ref double[] DSAVE, int offset_dsave)
        {
            #region Variables

            int I = 0; double DDOT = 0; double A1 = 0; double A2 = 0;

            #endregion


            #region Array Index Correction

            int o_l = -1 + offset_l;  int o_u = -1 + offset_u;  int o_nbd = -1 + offset_nbd;  int o_x = -1 + offset_x;
            int o_g = -1 + offset_g; int o_d = -1 + offset_d;  int o_r = -1 + offset_r;  int o_t = -1 + offset_t;
            int o_z = -1 + offset_z; int o_isave = -1 + offset_isave;  int o_dsave = -1 + offset_dsave;

            #endregion



            #region Prolog


            // c     **********
            // c
            // c     Subroutine lnsrlb
            // c
            // c     This subroutine calls subroutine dcsrch from the Minpack2 library
            // c       to perform the line search.  Subroutine dscrch is safeguarded so
            // c       that all trial points lie within the feasible region.
            // c
            // c     Subprograms called:
            // c
            // c       Minpack2 Library ... dcsrch.
            // c
            // c       Linpack ... dtrsl, ddot.
            // c
            // c
            // c                           *  *  *
            // c
            // c     NEOS, November 1994. (Latest revision June 1996.)
            // c     Optimization Technology Center.
            // c     Argonne National Laboratory and Northwestern University.
            // c     Written by
            // c                        Ciyou Zhu
            // c     in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal.
            // c
            // c
            // c     **********



            #endregion


            #region Body

            if (TASK == BFGSTask.FG_LNSRCH)
            {
                goto LABEL556;
            }

            DTD   = this._ddot.Run(N, D, offset_d, 1, D, offset_d, 1);
            DNORM = Math.Sqrt(DTD);

            // c     Determine the maximum step length.

            STPMX = BIG;
            if (CNSTND)
            {
                if (ITER == 0)
                {
                    STPMX = ONE;
                }
                else
                {
                    for (I = 1; I <= N; I++)
                    {
                        A1 = D[I + o_d];
                        if (NBD[I + o_nbd] != 0)
                        {
                            if (A1 < ZERO && NBD[I + o_nbd] <= 2)
                            {
                                A2 = L[I + o_l] - X[I + o_x];
                                if (A2 >= ZERO)
                                {
                                    STPMX = ZERO;
                                }
                                else
                                {
                                    if (A1 * STPMX < A2)
                                    {
                                        STPMX = A2 / A1;
                                    }
                                }
                            }
                            else
                            {
                                if (A1 > ZERO && NBD[I + o_nbd] >= 2)
                                {
                                    A2 = U[I + o_u] - X[I + o_x];
                                    if (A2 <= ZERO)
                                    {
                                        STPMX = ZERO;
                                    }
                                    else
                                    {
                                        if (A1 * STPMX > A2)
                                        {
                                            STPMX = A2 / A1;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (ITER == 0 && !BOXED)
            {
                STP = Math.Min(ONE / DNORM, STPMX);
            }
            else
            {
                STP = ONE;
            }

            this._dcopy.Run(N, X, offset_x, 1, ref T, offset_t, 1);
            this._dcopy.Run(N, G, offset_g, 1, ref R, offset_r, 1);
            FOLD  = F;
            IFUN  = 0;
            IBACK = 0;
            CSAVE = BFGSTask.START;
            LABEL556 :;
            GD = this._ddot.Run(N, G, offset_g, 1, D, offset_d, 1);
            if (IFUN == 0)
            {
                GDOLD = GD;
                if (GD >= ZERO)
                {
                    // c                               the directional derivative >=0.
                    // c                               Line search is impossible.
                    INFO = -4;
                    return;
                }
            }

            this._dcsrch.Run(F, GD, ref STP, FTOL, GTOL, XTOL
                             , ZERO, STPMX, ref CSAVE, ref ISAVE, offset_isave, ref DSAVE, offset_dsave);

            XSTEP = STP * DNORM;
            if (CSAVE != BFGSTask.CONV && CSAVE != BFGSTask.WARNING)
            {
                TASK  = BFGSTask.FG_LNSRCH;
                IFUN += 1;
                NFGV += 1;
                IBACK = IFUN - 1;
                if (STP == ONE)
                {
                    this._dcopy.Run(N, Z, offset_z, 1, ref X, offset_x, 1);
                }
                else
                {
                    for (I = 1; I <= N; I++)
                    {
                        X[I + o_x] = STP * D[I + o_d] + T[I + o_t];
                    }
                }
            }
            else
            {
                TASK = BFGSTask.NEW_X;
            }

            return;


            #endregion
        }