Exemplo n.º 1
0
        /**
         * Find a new point x in the direction p from a point xold at which the
         * value of the function has decreased sufficiently, the positive 
         * definiteness of B matrix (approximation of the inverse of the Hessian)
         * is preserved and no bound constraints are violated.  Details see "Numerical 
         * Methods for Unconstrained Optimization and Nonlinear Equations".
         * "Numeric Recipes in C" was also consulted.
         *
         * @param xold old x value 
         * @param gradient gradient at that point
         * @param direct direction vector
         * @param stpMax Maximum step .Length
         * @param isFixed indicating whether a variable has been fixed
         * @param nwsBounds non-working set bounds.  Means these variables are free and
         *                  subject to the bound constraints in this step
         * @param wsBdsIndx index of variables that has working-set bounds.  Means
         *                  these variables are already fixed and no longer subject to
         *                  the constraints
         * @return new value along direction p from xold, null if no step was taken
         * @throws Exception if an error occurs
         */
        public double[] lnsrch(double[] xold, double[] gradient,
                   double[] direct, double stpMax,
                   bool[] isFixed, double[,] nwsBounds,
                   DynamicIntArray wsBdsIndx)
        {
            int i, k, len = xold.Length,
            fixedOne = -1; // idx of variable to be fixed
            double alam, alaMin; // lambda to be found, and its lower bound

            // For convergence and bound test
            double temp, test, alpha = Double.PositiveInfinity, fold = m_f, sum;

            // For cubic interpolation
            double a, alam2 = 0, b, disc = 0, Maxalam = 1.0, rhs1, rhs2, tmplam;

            double[] x = new double[len]; // New variable values

            // Scale the step 
            for (sum = 0.0, i = 0; i < len; i++)
            {
                if (!isFixed[i]) // For fixed variables, direction = 0
                    sum += direct[i] * direct[i];
            }
            sum = Math.Sqrt(sum);

            if (sum > stpMax)
            {
                for (i = 0; i < len; i++)
                    if (!isFixed[i])
                        direct[i] *= stpMax / sum;
            }
            else
                Maxalam = stpMax / sum;

            // Compute initial rate of decrease, g'*d 
            m_Slope = 0.0;
            for (i = 0; i < len; i++)
            {
                x[i] = xold[i];
                if (!isFixed[i])
                    m_Slope += gradient[i] * direct[i];
            }



            // Slope too small
            if (Math.Abs(m_Slope) <= m_Zero)
            {
                return x;
            }

            // Err: slope > 0

            // Compute LAMBDAMin and upper bound of lambda--alpha
            test = 0.0;
            for (i = 0; i < len; i++)
            {
                if (!isFixed[i])
                {// No need for fixed variables
                    temp = Math.Abs(direct[i]) / Math.Max(Math.Abs(x[i]), 1.0);
                    if (temp > test) test = temp;
                }
            }

            if (test > m_Zero) // Not converge
                alaMin = m_TOLX / test;
            else
            {
                return x;
            }

            // Check whether any non-working-set bounds are "binding"
            for (i = 0; i < len; i++)
            {
                if (!isFixed[i])
                {// No need for fixed variables
                    double alpi;
                    if ((direct[i] < -m_Epsilon) && !Double.IsNaN(nwsBounds[0, i]))
                    {//Not feasible
                        alpi = (nwsBounds[0, i] - xold[i]) / direct[i];
                        if (alpi <= m_Zero)
                        { // Zero
                            x[i] = nwsBounds[0, i];
                            isFixed[i] = true; // Fix this variable
                            alpha = 0.0;
                            nwsBounds[0, i] = Double.NaN; //Add cons. to working set
                            wsBdsIndx.addElement(i);
                        }
                        else if (alpha > alpi)
                        { // Fix one variable in one iteration
                            alpha = alpi;
                            fixedOne = i;
                        }
                    }
                    else if ((direct[i] > m_Epsilon) && !Double.IsNaN(nwsBounds[1, i]))
                    {//Not feasible
                        alpi = (nwsBounds[1, i] - xold[i]) / direct[i];
                        if (alpi <= m_Zero)
                        { // Zero
                            x[i] = nwsBounds[1, i];
                            isFixed[i] = true; // Fix this variable
                            alpha = 0.0;
                            nwsBounds[1, i] = Double.NaN; //Add cons. to working set
                            wsBdsIndx.addElement(i);
                        }
                        else if (alpha > alpi)
                        {
                            alpha = alpi;
                            fixedOne = i;
                        }
                    }
                }
            }



            if (alpha <= m_Zero)
            { // Zero	   
                m_IsZeroStep = true;
                return x;
            }

            alam = alpha; // Always try full feasible newton step 
            if (alam > 1.0)
                alam = 1.0;

            // Iteration of one newton step, if necessary, backtracking is done
            double initF = fold, // Initial function value
                hi = alam, lo = alam, newSlope = 0, fhi = m_f, flo = m_f;// Variables used for beta condition
            double[] newGrad;  // Gradient on the new variable values
            bool control = true;
        kloop:
            for (k = 0; control == true; k++)
            {

                for (i = 0; i < len; i++)
                {
                    if (!isFixed[i])
                    {
                        x[i] = xold[i] + alam * direct[i];  // Compute xnew
                        if (!Double.IsNaN(nwsBounds[0, i]) && (x[i] < nwsBounds[0, i]))
                        {
                            x[i] = nwsBounds[0, i]; //Rounding error	
                        }
                        else if (!Double.IsNaN(nwsBounds[1, i]) && (x[i] > nwsBounds[1, i]))
                        {
                            x[i] = nwsBounds[1, i]; //Rounding error	
                        }
                    }
                }

                m_f = objectiveFunction(x);    // Compute fnew

                while (Double.IsPositiveInfinity(m_f))
                { // Avoid infinity

                    alam *= 0.5; // Shrink by half
                    if (alam <= m_Epsilon)
                    {

                        return x;
                    }

                    for (i = 0; i < len; i++)
                        if (!isFixed[i])
                            x[i] = xold[i] + alam * direct[i];

                    m_f = objectiveFunction(x);

                    initF = Double.PositiveInfinity;
                }

                if (m_f <= fold + m_ALF * alam * m_Slope)
                {// Alpha condition: sufficient function decrease
                    newGrad = evaluateGradient(x);
                    for (newSlope = 0.0, i = 0; i < len; i++)
                        if (!isFixed[i])
                            newSlope += newGrad[i] * direct[i];

                    if (newSlope >= m_BETA * m_Slope)
                    { // Beta condition: ensure pos. defnty.	

                        if ((fixedOne != -1) && (alam >= alpha))
                        { // Has bounds and over
                            if (direct[fixedOne] > 0)
                            {
                                x[fixedOne] = nwsBounds[1, fixedOne]; // Avoid rounding error
                                nwsBounds[1, fixedOne] = Double.NaN; //Add cons. to working set
                            }
                            else
                            {
                                x[fixedOne] = nwsBounds[0, fixedOne]; // Avoid rounding error
                                nwsBounds[0, fixedOne] = Double.NaN; //Add cons. to working set
                            }

                            isFixed[fixedOne] = true; // Fix the variable
                            wsBdsIndx.addElement(fixedOne);
                        }
                        return x;
                    }
                    else if (k == 0)
                    { // First time: increase alam 
                        // Search for the smallest value not complying with alpha condition
                        double upper = Math.Min(alpha, Maxalam);
                        while (!((alam >= upper) || (m_f > fold + m_ALF * alam * m_Slope)))
                        {
                            lo = alam;
                            flo = m_f;
                            alam *= 2.0;
                            if (alam >= upper)  // Avoid rounding errors
                                alam = upper;

                            for (i = 0; i < len; i++)
                                if (!isFixed[i])
                                    x[i] = xold[i] + alam * direct[i];
                            m_f = objectiveFunction(x);

                            newGrad = evaluateGradient(x);
                            for (newSlope = 0.0, i = 0; i < len; i++)
                                if (!isFixed[i])
                                    newSlope += newGrad[i] * direct[i];

                            if (newSlope >= m_BETA * m_Slope)
                            {
                                if ((fixedOne != -1) && (alam >= alpha))
                                { // Has bounds and over
                                    if (direct[fixedOne] > 0)
                                    {
                                        x[fixedOne] = nwsBounds[1, fixedOne]; // Avoid rounding error
                                        nwsBounds[1, fixedOne] = Double.NaN; //Add cons. to working set
                                    }
                                    else
                                    {
                                        x[fixedOne] = nwsBounds[0, fixedOne]; // Avoid rounding error
                                        nwsBounds[0, fixedOne] = Double.NaN; //Add cons. to working set
                                    }

                                    isFixed[fixedOne] = true; // Fix the variable
                                    wsBdsIndx.addElement(fixedOne);
                                }
                                return x;
                            }
                        }
                        hi = alam;
                        fhi = m_f;
                        control = false;
                        goto kloop;
                    }
                    else
                    {
                        hi = alam2; lo = alam; flo = m_f;
                        control = false;
                        goto kloop;
                    }
                }
                else if (alam < alaMin)
                { // No feasible lambda found       
                    if (initF < fold)
                    {
                        alam = Math.Min(1.0, alpha);
                        for (i = 0; i < len; i++)
                            if (!isFixed[i])
                                x[i] = xold[i] + alam * direct[i]; //Still take Alpha

                        if ((fixedOne != -1) && (alam >= alpha))
                        { // Has bounds and over
                            if (direct[fixedOne] > 0)
                            {
                                x[fixedOne] = nwsBounds[1, fixedOne]; // Avoid rounding error
                                nwsBounds[1, fixedOne] = Double.NaN; //Add cons. to working set
                            }
                            else
                            {
                                x[fixedOne] = nwsBounds[0, fixedOne]; // Avoid rounding error
                                nwsBounds[0, fixedOne] = Double.NaN; //Add cons. to working set
                            }

                            isFixed[fixedOne] = true; // Fix the variable
                            wsBdsIndx.addElement(fixedOne);
                        }
                    }
                    else
                    {   // Convergence on delta(x)
                        for (i = 0; i < len; i++)
                            x[i] = xold[i];
                        m_f = fold;
                    }

                    return x;
                }
                else
                { // Backtracking by polynomial interpolation
                    if (k == 0)
                    { // First time backtrack: quadratic interpolation
                        if (!Double.IsPositiveInfinity(initF))
                            initF = m_f;
                        // lambda = -g'(0)/(2*g''(0))
                        tmplam = -0.5 * alam * m_Slope / ((m_f - fold) / alam - m_Slope);
                    }
                    else
                    {    // Subsequent backtrack: cubic interpolation 
                        rhs1 = m_f - fold - alam * m_Slope;
                        rhs2 = fhi - fold - alam2 * m_Slope;
                        a = (rhs1 / (alam * alam) - rhs2 / (alam2 * alam2)) / (alam - alam2);
                        b = (-alam2 * rhs1 / (alam * alam) + alam * rhs2 / (alam2 * alam2)) / (alam - alam2);
                        if (a == 0.0) tmplam = -m_Slope / (2.0 * b);
                        else
                        {
                            disc = b * b - 3.0 * a * m_Slope;
                            if (disc < 0.0) disc = 0.0;
                            double numerator = -b + Math.Sqrt(disc);
                            if (numerator >= Double.MaxValue)
                            {
                                numerator = Double.MaxValue;
                            }
                            tmplam = numerator / (3.0 * a);
                        }
                        if (tmplam > 0.5 * alam)
                            tmplam = 0.5 * alam;             // lambda <= 0.5*lambda_old
                    }
                }
                alam2 = alam;
                fhi = m_f;
                alam = Math.Max(tmplam, 0.1 * alam);          // lambda >= 0.1*lambda_old

            } // Endfor(k=0;;k++)

            // Quadratic interpolation between lamda values between lo and hi.
            // If cannot find a value satisfying beta condition, use lo.
            double ldiff = hi - lo, lincr;

            while ((newSlope < m_BETA * m_Slope) && (ldiff >= alaMin))
            {
                lincr = -0.5 * newSlope * ldiff * ldiff / (fhi - flo - newSlope * ldiff);

                if (lincr < 0.2 * ldiff) lincr = 0.2 * ldiff;
                alam = lo + lincr;
                if (alam >= hi)
                { // We cannot go beyond the bounds, so the best we can try is hi
                    alam = hi;
                    lincr = ldiff;
                }
                for (i = 0; i < len; i++)
                    if (!isFixed[i])
                        x[i] = xold[i] + alam * direct[i];
                m_f = objectiveFunction(x);

                if (m_f > fold + m_ALF * alam * m_Slope)
                {
                    // Alpha condition fails, shrink lambda_upper
                    ldiff = lincr;
                    fhi = m_f;
                }
                else
                { // Alpha condition holds	    
                    newGrad = evaluateGradient(x);
                    for (newSlope = 0.0, i = 0; i < len; i++)
                        if (!isFixed[i])
                            newSlope += newGrad[i] * direct[i];

                    if (newSlope < m_BETA * m_Slope)
                    {
                        // Beta condition fails, shrink lambda_lower
                        lo = alam;
                        ldiff -= lincr;
                        flo = m_f;
                    }
                }
            }

            if (newSlope < m_BETA * m_Slope)
            { // Cannot satisfy beta condition, take lo
                alam = lo;
                for (i = 0; i < len; i++)
                    if (!isFixed[i])
                        x[i] = xold[i] + alam * direct[i];
                m_f = flo;
            }

            if ((fixedOne != -1) && (alam >= alpha))
            { // Has bounds and over
                if (direct[fixedOne] > 0)
                {
                    x[fixedOne] = nwsBounds[1, fixedOne]; // Avoid rounding error
                    nwsBounds[1, fixedOne] = Double.NaN; //Add cons. to working set
                }
                else
                {
                    x[fixedOne] = nwsBounds[0, fixedOne]; // Avoid rounding error
                    nwsBounds[0, fixedOne] = Double.NaN; //Add cons. to working set
                }

                isFixed[fixedOne] = true; // Fix the variable
                wsBdsIndx.addElement(fixedOne);
            }

            return x;
        }
Exemplo n.º 2
0
        /**
         * Main algorithm.  Descriptions see "Practical Optimization"
         *
         * @param initX initial point of x, assuMing no value's on the bound!
         * @param constraints the bound constraints of each variable
         *                    constraints[0] is the lower bounds and 
         *                    constraints[1] is the upper bounds
         * @return the solution of x, null if number of iterations not enough
         * @throws Exception if an error occurs
         */
        public double[] findArgMin(double[] initX, double[,] constraints)
        {
            int l = initX.Length;

            // Initially all variables are free, all bounds are constraints of
            // non-working-set constraints
            bool[] isFixed = new bool[l];
            double[,] nwsBounds = new double[2, l];
            // Record indice of fixed variables, simply for efficiency
            DynamicIntArray wsBdsIndx = new DynamicIntArray(constraints.Length);
            // Vectors used to record the variable indices to be freed 	
            DynamicIntArray toFree = null, oldToFree = null;

            // Initial value of obj. function, gradient and inverse of the Hessian
            m_f = objectiveFunction(initX);

            double sum = 0;
            double[] grad = evaluateGradient(initX), oldGrad, oldX,
                     deltaGrad = new double[l], deltaX = new double[l],
                     direct = new double[l], x = new double[l];
            Matrix L = new Matrix(l, l);  // Lower triangle of Cholesky factor 
            double[] D = new double[l];   // Diagonal of Cholesky factor
            for (int i = 0; i < l; i++)
            {
                L.setRow(i, new double[l]);
                L.setElement(i, i, 1.0);
                D[i] = 1.0;
                direct[i] = -grad[i];
                sum += grad[i] * grad[i];
                x[i] = initX[i];
                nwsBounds[0, i] = constraints[0, i];
                nwsBounds[1, i] = constraints[1, i];
                isFixed[i] = false;
            }
            double stpMax = m_STPMX * Math.Max(Math.Sqrt(sum), l);

        iterates:
            for (int step = 0; step < m_MaxITS; step++)
            {

                // Try at most one feasible newton step, i.e. 0<lamda<=alpha
                oldX = x;
                oldGrad = grad;

                // Also update grad
                m_IsZeroStep = false;
                x = lnsrch(x, grad, direct, stpMax,
                     isFixed, nwsBounds, wsBdsIndx);


                if (m_IsZeroStep)
                { // Zero step, simply delete rows/cols of D and L
                    for (int f = 0; f < wsBdsIndx.msize(); f++)
                    {
                        int idx = wsBdsIndx.elementAt(f);
                        L.setRow(idx, new double[l]);
                        L.setColumn(idx, new double[l]);
                        D[idx] = 0.0;
                    }
                    grad = evaluateGradient(x);
                    step--;
                }
                else
                {
                    // Check converge on x
                    bool finish = false;
                    double test = 0.0;
                    for (int h = 0; h < l; h++)
                    {
                        deltaX[h] = x[h] - oldX[h];
                        double tmp = Math.Abs(deltaX[h]) /
                        Math.Max(Math.Abs(x[h]), 1.0);
                        if (tmp > test) test = tmp;
                    }
                    if (test < m_Zero)
                    {

                        finish = true;
                    }

                    // Check zero gradient	    
                    grad = evaluateGradient(x);
                    test = 0.0;
                    double denom = 0.0, dxSq = 0.0, dgSq = 0.0, newlyBounded = 0.0;
                    for (int g = 0; g < l; g++)
                    {
                        if (!isFixed[g])
                        {
                            deltaGrad[g] = grad[g] - oldGrad[g];
                            // Calculate the denoMinators			    
                            denom += deltaX[g] * deltaGrad[g];
                            dxSq += deltaX[g] * deltaX[g];
                            dgSq += deltaGrad[g] * deltaGrad[g];
                        }
                        else // Only newly bounded variables will be non-zero
                            newlyBounded += deltaX[g] * (grad[g] - oldGrad[g]);

                        // Note: CANNOT use projected gradient for testing 
                        // convergence because of newly bounded variables
                        double tmp = Math.Abs(grad[g]) *
                        Math.Max(Math.Abs(direct[g]), 1.0) /
                        Math.Max(Math.Abs(m_f), 1.0);
                        if (tmp > test) test = tmp;
                    }

                    if (test < m_Zero)
                    {
                        finish = true;
                    }

                    // dg'*dx could be < 0 using inexact lnsrch
                    // dg'*dx = 0
                    if (Math.Abs(denom + newlyBounded) < m_Zero)
                        finish = true;

                    int size = wsBdsIndx.msize();
                    bool isUpdate = true;  // Whether to update BFGS formula	    
                    // Converge: check whether release any current constraints
                    if (finish)
                    {

                        if (toFree != null)
                            oldToFree = (DynamicIntArray)toFree.copy();
                        toFree = new DynamicIntArray(wsBdsIndx.msize());

                        for (int m = size - 1; m >= 0; m--)
                        {
                            int index = wsBdsIndx.elementAt(m);
                            double[] hessian = evaluateHessian(x, index);
                            double deltaL = 0.0;
                            if (hessian != null)
                            {
                                for (int mm = 0; mm < hessian.Length; mm++)
                                    if (!isFixed[mm]) // Free variable
                                        deltaL += hessian[mm] * direct[mm];
                            }

                            // First and second order Lagrangian multiplier estimate
                            // If user didn't provide Hessian, use first-order only
                            double L1 = 0, L2 = 0;
                            if (x[index] >= constraints[1, index]) // Upper bound
                            {
                                L1 = -grad[index];
                            }
                            else
                            {
                                if (x[index] <= constraints[0, index])// Lower bound
                                {
                                    L1 = grad[index];
                                }
                            }

                            // L2 = L1 + deltaL
                            L2 = L1 + deltaL;

                            //Check validity of Lagrangian multiplier estimate
                            bool isConverge =
                                (2.0 * Math.Abs(deltaL)) < Math.Min(Math.Abs(L1),
                                                  Math.Abs(L2));
                            if ((L1 * L2 > 0.0) && isConverge)
                            { //Same sign and converge: valid
                                if (L2 < 0.0)
                                {// Negative Lagrangian: feasible
                                    toFree.addElement(index);
                                    wsBdsIndx.removeElementAt(m);
                                    finish = false; // Not optimal, cannot finish
                                }
                            }

                            // Although hardly happen, better check it
                            // If the first-order Lagrangian multiplier estimate is wrong,
                            // avoid zigzagging
                            if ((hessian == null) && (toFree != null) && toFree.Equal(oldToFree))
                                finish = true;
                        }

                        if (finish)
                        {// Min. found

                            m_f = objectiveFunction(x);

                            return x;
                        }

                        // Free some variables
                        for (int mmm = 0; mmm < toFree.msize(); mmm++)
                        {
                            int freeIndx = toFree.elementAt(mmm);
                            isFixed[freeIndx] = false; // Free this variable
                            if (x[freeIndx] <= constraints[0, freeIndx])
                            {// Lower bound
                                nwsBounds[0, freeIndx] = constraints[0, freeIndx];

                            }
                            else
                            { // Upper bound
                                nwsBounds[1, freeIndx] = constraints[1, freeIndx];

                            }
                            L.setElement(freeIndx, freeIndx, 1.0);
                            D[freeIndx] = 1.0;
                            isUpdate = false;
                        }
                    }

                    if (denom < Math.Max(m_Zero * Math.Sqrt(dxSq) * Math.Sqrt(dgSq), m_Zero))
                    {

                        isUpdate = false; // Do not update		    
                    }
                    // If Hessian will be positive definite, update it
                    if (isUpdate)
                    {

                        // modify once: dg*dg'/(dg'*dx)	
                        double coeff = 1.0 / denom; // 1/(dg'*dx)	
                        updateCholeskyFactor(L, D, deltaGrad, coeff, isFixed);

                        // modify twice: g*g'/(g'*p)	
                        coeff = 1.0 / m_Slope; // 1/(g'*p)
                        updateCholeskyFactor(L, D, oldGrad, coeff, isFixed);
                    }
                }

                // Find new direction 
                Matrix LD = new Matrix(l, l); // L*D
                double[] b = new double[l];

                for (int k = 0; k < l; k++)
                {
                    if (!isFixed[k]) b[k] = -grad[k];
                    else b[k] = 0.0;

                    for (int j = k; j < l; j++)
                    { // Lower triangle	
                        if (!isFixed[j] && !isFixed[k])
                            LD.setElement(j, k, L.getElement(j, k) * D[k]);
                    }
                }

                // Solve (LD)*y = -g, where y=L'*direct
                double[] LDIR = solveTriangle(LD, b, true, isFixed);
                LD = null;

                // Solve L'*direct = y
                direct = solveTriangle(L, LDIR, false, isFixed);

                //System.gc();
            }

            m_X = x;
            return null;
        }
Exemplo n.º 3
0
		/// <summary> Find a new point x in the direction p from a point xold at which the
		/// value of the function has decreased sufficiently, the positive 
		/// definiteness of B matrix (approximation of the inverse of the Hessian)
		/// is preserved and no bound constraints are violated.  Details see "Numerical 
		/// Methods for Unconstrained Optimization and Nonlinear Equations".
		/// "Numeric Recipes in C" was also consulted.
		/// 
		/// </summary>
		/// <param name="xold">old x value 
		/// </param>
		/// <param name="gradient">gradient at that point
		/// </param>
		/// <param name="direct">direction vector
		/// </param>
		/// <param name="stpmax">maximum step length
		/// </param>
		/// <param name="isFixed">indicating whether a variable has been fixed
		/// </param>
		/// <param name="nwsBounds">non-working set bounds.  Means these variables are free and
		/// subject to the bound constraints in this step
		/// </param>
		/// <param name="wsBdsIndx">index of variables that has working-set bounds.  Means
		/// these variables are already fixed and no longer subject to
		/// the constraints
		/// </param>
		/// <returns> new value along direction p from xold, null if no step was taken
		/// </returns>
		/// <exception cref="Exception">if an error occurs
		/// </exception>
		public virtual double[] lnsrch(double[] xold, double[] gradient, double[] direct, double stpmax, bool[] isFixed, double[][] nwsBounds, DynamicIntArray wsBdsIndx)
		{
			
			int i, j, k, len = xold.Length, fixedOne = - 1; // idx of variable to be fixed
			double alam, alamin; // lambda to be found, and its lower bound
			
			// For convergence and bound test
			double temp, test, alpha = System.Double.PositiveInfinity, fold = m_f, sum;
			
			// For cubic interpolation
			double a, alam2 = 0, b, disc = 0, maxalam = 1.0, rhs1, rhs2, tmplam;
			
			double[] x = new double[len]; // New variable values
			
			// Scale the step 
			for (sum = 0.0, i = 0; i < len; i++)
			{
				if (!isFixed[i])
				// For fixed variables, direction = 0
					sum += direct[i] * direct[i];
			}
			sum = System.Math.Sqrt(sum);
			
			if (m_Debug)
				System.Console.Error.WriteLine("fold:  " + Utils.doubleToString(fold, 10, 7) + "\n" + "sum:  " + Utils.doubleToString(sum, 10, 7) + "\n" + "stpmax:  " + Utils.doubleToString(stpmax, 10, 7));
			if (sum > stpmax)
			{
				for (i = 0; i < len; i++)
					if (!isFixed[i])
						direct[i] *= stpmax / sum;
			}
			else
				maxalam = stpmax / sum;
			
			// Compute initial rate of decrease, g'*d 
			m_Slope = 0.0;
			for (i = 0; i < len; i++)
			{
				x[i] = xold[i];
				if (!isFixed[i])
					m_Slope += gradient[i] * direct[i];
			}
			
			if (m_Debug)
				System.Console.Error.Write("slope:  " + Utils.doubleToString(m_Slope, 10, 7) + "\n");
			
			// Slope too small
			if (System.Math.Abs(m_Slope) <= m_Zero)
			{
				if (m_Debug)
					System.Console.Error.WriteLine("Gradient and direction orthogonal -- " + "Min. found with current fixed variables" + " (or all variables fixed). Try to release" + " some variables now.");
				return x;
			}
			
			// Err: slope > 0
			if (m_Slope > m_Zero)
			{
				if (m_Debug)
					for (int h = 0; h < x.Length; h++)
						System.Console.Error.WriteLine(h + ": isFixed=" + isFixed[h] + ", x=" + x[h] + ", grad=" + gradient[h] + ", direct=" + direct[h]);
				throw new System.Exception("g'*p positive! -- Try to debug from here: line 327.");
			}
			
			// Compute LAMBDAmin and upper bound of lambda--alpha
			test = 0.0;
			for (i = 0; i < len; i++)
			{
				if (!isFixed[i])
				{
					// No need for fixed variables
					temp = System.Math.Abs(direct[i]) / System.Math.Max(System.Math.Abs(x[i]), 1.0);
					if (temp > test)
						test = temp;
				}
			}
			
			if (test > m_Zero)
			// Not converge
				alamin = m_TOLX / test;
			else
			{
				if (m_Debug)
					System.Console.Error.WriteLine("Zero directions for all free variables -- " + "Min. found with current fixed variables" + " (or all variables fixed). Try to release" + " some variables now.");
				return x;
			}
			
			// Check whether any non-working-set bounds are "binding"
			for (i = 0; i < len; i++)
			{
				if (!isFixed[i])
				{
					// No need for fixed variables
					double alpi;
					if ((direct[i] < - m_Epsilon) && !System.Double.IsNaN(nwsBounds[0][i]))
					{
						//Not feasible
						alpi = (nwsBounds[0][i] - xold[i]) / direct[i];
						if (alpi <= m_Zero)
						{
							// Zero
							if (m_Debug)
								System.Console.Error.WriteLine("Fix variable " + i + " to lower bound " + nwsBounds[0][i] + " from value " + xold[i]);
							x[i] = nwsBounds[0][i];
							isFixed[i] = true; // Fix this variable
							alpha = 0.0;
							nwsBounds[0][i] = System.Double.NaN; //Add cons. to working set
							wsBdsIndx.addElement(i);
						}
						else if (alpha > alpi)
						{
							// Fix one variable in one iteration
							alpha = alpi;
							fixedOne = i;
						}
					}
					else if ((direct[i] > m_Epsilon) && !System.Double.IsNaN(nwsBounds[1][i]))
					{
						//Not feasible
						alpi = (nwsBounds[1][i] - xold[i]) / direct[i];
						if (alpi <= m_Zero)
						{
							// Zero
							if (m_Debug)
								System.Console.Error.WriteLine("Fix variable " + i + " to upper bound " + nwsBounds[1][i] + " from value " + xold[i]);
							x[i] = nwsBounds[1][i];
							isFixed[i] = true; // Fix this variable
							alpha = 0.0;
							nwsBounds[1][i] = System.Double.NaN; //Add cons. to working set
							wsBdsIndx.addElement(i);
						}
						else if (alpha > alpi)
						{
							alpha = alpi;
							fixedOne = i;
						}
					}
				}
			}
			
			if (m_Debug)
			{
				System.Console.Error.WriteLine("alamin: " + Utils.doubleToString(alamin, 10, 7));
				System.Console.Error.WriteLine("alpha: " + Utils.doubleToString(alpha, 10, 7));
			}
			
			if (alpha <= m_Zero)
			{
				// Zero	   
				m_IsZeroStep = true;
				if (m_Debug)
					System.Console.Error.WriteLine("Alpha too small, try again");
				return x;
			}
			
			alam = alpha; // Always try full feasible newton step 
			if (alam > 1.0)
				alam = 1.0;
			
			// Iteration of one newton step, if necessary, backtracking is done
			double initF = fold, hi = alam, lo = alam, newSlope = 0, fhi = m_f, flo = m_f; // Variables used for beta condition
			double[] newGrad; // Gradient on the new variable values
			
			for (k = 0; ; k++)
			{
				if (m_Debug)
					System.Console.Error.WriteLine("\nLine search iteration: " + k);
				
				for (i = 0; i < len; i++)
				{
					if (!isFixed[i])
					{
						x[i] = xold[i] + alam * direct[i]; // Compute xnew
						if (!System.Double.IsNaN(nwsBounds[0][i]) && (x[i] < nwsBounds[0][i]))
						{
							x[i] = nwsBounds[0][i]; //Rounding error	
						}
						else if (!System.Double.IsNaN(nwsBounds[1][i]) && (x[i] > nwsBounds[1][i]))
						{
							x[i] = nwsBounds[1][i]; //Rounding error	
						}
					}
				}
				
				m_f = objectiveFunction(x); // Compute fnew
				if (System.Double.IsNaN(m_f))
					throw new System.Exception("Objective function value is NaN!");
				
				while (System.Double.IsInfinity(m_f))
				{
					// Avoid infinity
					if (m_Debug)
						System.Console.Error.WriteLine("Too large m_f.  Shrink step by half.");
					alam *= 0.5; // Shrink by half
					if (alam <= m_Epsilon)
					{
						if (m_Debug)
							System.Console.Error.WriteLine("Wrong starting points, change them!");
						return x;
					}
					
					for (i = 0; i < len; i++)
						if (!isFixed[i])
							x[i] = xold[i] + alam * direct[i];
					
					m_f = objectiveFunction(x);
					if (System.Double.IsNaN(m_f))
						throw new System.Exception("Objective function value is NaN!");
					
					initF = System.Double.PositiveInfinity;
				}
				
				if (m_Debug)
				{
					System.Console.Error.WriteLine("obj. function: " + Utils.doubleToString(m_f, 10, 7));
					System.Console.Error.WriteLine("threshold: " + Utils.doubleToString(fold + m_ALF * alam * m_Slope, 10, 7));
				}
				
				if (m_f <= fold + m_ALF * alam * m_Slope)
				{
					// Alpha condition: sufficient function decrease
					if (m_Debug)
						System.Console.Error.WriteLine("Sufficient function decrease (alpha condition): ");
					newGrad = evaluateGradient(x);
					for (newSlope = 0.0, i = 0; i < len; i++)
						if (!isFixed[i])
							newSlope += newGrad[i] * direct[i];
					
					if (newSlope >= m_BETA * m_Slope)
					{
						// Beta condition: ensure pos. defnty.	
						if (m_Debug)
							System.Console.Error.WriteLine("Increasing derivatives (beta condition): ");
						
						if ((fixedOne != - 1) && (alam >= alpha))
						{
							// Has bounds and over
							if (direct[fixedOne] > 0)
							{
								x[fixedOne] = nwsBounds[1][fixedOne]; // Avoid rounding error
								nwsBounds[1][fixedOne] = System.Double.NaN; //Add cons. to working set
							}
							else
							{
								x[fixedOne] = nwsBounds[0][fixedOne]; // Avoid rounding error
								nwsBounds[0][fixedOne] = System.Double.NaN; //Add cons. to working set
							}
							
							if (m_Debug)
								System.Console.Error.WriteLine("Fix variable " + fixedOne + " to bound " + x[fixedOne] + " from value " + xold[fixedOne]);
							isFixed[fixedOne] = true; // Fix the variable
							wsBdsIndx.addElement(fixedOne);
						}
						return x;
					}
					else if (k == 0)
					{
						// First time: increase alam 
						// Search for the smallest value not complying with alpha condition
						double upper = System.Math.Min(alpha, maxalam);
						if (m_Debug)
							System.Console.Error.WriteLine("Alpha condition holds, increase alpha... ");
						while (!((alam >= upper) || (m_f > fold + m_ALF * alam * m_Slope)))
						{
							lo = alam;
							flo = m_f;
							alam *= 2.0;
							if (alam >= upper)
							// Avoid rounding errors
								alam = upper;
							
							for (i = 0; i < len; i++)
								if (!isFixed[i])
									x[i] = xold[i] + alam * direct[i];
							m_f = objectiveFunction(x);
							if (System.Double.IsNaN(m_f))
								throw new System.Exception("Objective function value is NaN!");
							
							newGrad = evaluateGradient(x);
							for (newSlope = 0.0, i = 0; i < len; i++)
								if (!isFixed[i])
									newSlope += newGrad[i] * direct[i];
							
							if (newSlope >= m_BETA * m_Slope)
							{
								if (m_Debug)
									System.Console.Error.WriteLine("Increasing derivatives (beta condition): \n" + "newSlope = " + Utils.doubleToString(newSlope, 10, 7));
								
								if ((fixedOne != - 1) && (alam >= alpha))
								{
									// Has bounds and over
									if (direct[fixedOne] > 0)
									{
										x[fixedOne] = nwsBounds[1][fixedOne]; // Avoid rounding error
										nwsBounds[1][fixedOne] = System.Double.NaN; //Add cons. to working set
									}
									else
									{
										x[fixedOne] = nwsBounds[0][fixedOne]; // Avoid rounding error
										nwsBounds[0][fixedOne] = System.Double.NaN; //Add cons. to working set
									}
									
									if (m_Debug)
										System.Console.Error.WriteLine("Fix variable " + fixedOne + " to bound " + x[fixedOne] + " from value " + xold[fixedOne]);
									isFixed[fixedOne] = true; // Fix the variable
									wsBdsIndx.addElement(fixedOne);
								}
								return x;
							}
						}
						hi = alam;
						fhi = m_f;
						//UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
						goto kloop_brk;
					}
					else
					{
						if (m_Debug)
							System.Console.Error.WriteLine("Alpha condition holds.");
						hi = alam2; lo = alam; flo = m_f;
						//UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'"
						goto kloop_brk;
					}
				}
				else if (alam < alamin)
				{
					// No feasible lambda found       
					if (initF < fold)
					{
						alam = System.Math.Min(1.0, alpha);
						for (i = 0; i < len; i++)
							if (!isFixed[i])
								x[i] = xold[i] + alam * direct[i]; //Still take Alpha
						
						if (m_Debug)
							System.Console.Error.WriteLine("No feasible lambda: still take" + " alpha=" + alam);
						
						if ((fixedOne != - 1) && (alam >= alpha))
						{
							// Has bounds and over
							if (direct[fixedOne] > 0)
							{
								x[fixedOne] = nwsBounds[1][fixedOne]; // Avoid rounding error
								nwsBounds[1][fixedOne] = System.Double.NaN; //Add cons. to working set
							}
							else
							{
								x[fixedOne] = nwsBounds[0][fixedOne]; // Avoid rounding error
								nwsBounds[0][fixedOne] = System.Double.NaN; //Add cons. to working set
							}
							
							if (m_Debug)
								System.Console.Error.WriteLine("Fix variable " + fixedOne + " to bound " + x[fixedOne] + " from value " + xold[fixedOne]);
							isFixed[fixedOne] = true; // Fix the variable
							wsBdsIndx.addElement(fixedOne);
						}
					}
					else
					{
						// Convergence on delta(x)
						for (i = 0; i < len; i++)
							x[i] = xold[i];
						m_f = fold;
						if (m_Debug)
							System.Console.Error.WriteLine("Cannot find feasible lambda");
					}
					
					return x;
				}
				else
				{
					// Backtracking by polynomial interpolation
					if (k == 0)
					{
						// First time backtrack: quadratic interpolation
						if (!System.Double.IsInfinity(initF))
							initF = m_f;
						// lambda = -g'(0)/(2*g''(0))
						tmplam = (- 0.5) * alam * m_Slope / ((m_f - fold) / alam - m_Slope);
					}
					else
					{
						// Subsequent backtrack: cubic interpolation 
						rhs1 = m_f - fold - alam * m_Slope;
						rhs2 = fhi - fold - alam2 * m_Slope;
						a = (rhs1 / (alam * alam) - rhs2 / (alam2 * alam2)) / (alam - alam2);
						b = ((- alam2) * rhs1 / (alam * alam) + alam * rhs2 / (alam2 * alam2)) / (alam - alam2);
						if (a == 0.0)
							tmplam = (- m_Slope) / (2.0 * b);
						else
						{
							disc = b * b - 3.0 * a * m_Slope;
							if (disc < 0.0)
								disc = 0.0;
							double numerator = - b + System.Math.Sqrt(disc);
							//UPGRADE_TODO: The equivalent in .NET for field 'java.lang.Double.MAX_VALUE' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
							if (numerator >= System.Double.MaxValue)
							{
								//UPGRADE_TODO: The equivalent in .NET for field 'java.lang.Double.MAX_VALUE' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
								numerator = System.Double.MaxValue;
								if (m_Debug)
									System.Console.Error.Write("-b+sqrt(disc) too large! Set it to MAX_VALUE.");
							}
							tmplam = numerator / (3.0 * a);
						}
						if (m_Debug)
							System.Console.Error.Write("Cubic interpolation: \n" + "a:   " + Utils.doubleToString(a, 10, 7) + "\n" + "b:   " + Utils.doubleToString(b, 10, 7) + "\n" + "disc:   " + Utils.doubleToString(disc, 10, 7) + "\n" + "tmplam:   " + tmplam + "\n" + "alam:   " + Utils.doubleToString(alam, 10, 7) + "\n");
						if (tmplam > 0.5 * alam)
							tmplam = 0.5 * alam; // lambda <= 0.5*lambda_old
					}
				}
				alam2 = alam;
				fhi = m_f;
				alam = System.Math.Max(tmplam, 0.1 * alam); // lambda >= 0.1*lambda_old
				
				if (alam > alpha)
				{
					throw new System.Exception("Sth. wrong in lnsrch:" + "Lambda infeasible!(lambda=" + alam + ", alpha=" + alpha + ", upper=" + tmplam + "|" + ((- alpha) * m_Slope / (2.0 * ((m_f - fold) / alpha - m_Slope))) + ", m_f=" + m_f + ", fold=" + fold + ", slope=" + m_Slope);
				}
			}
			//UPGRADE_NOTE: Label 'kloop_brk' was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1011'"

kloop_brk: ;
			 // Endfor(k=0;;k++)
			
			// Quadratic interpolation between lamda values between lo and hi.
			// If cannot find a value satisfying beta condition, use lo.
			double ldiff = hi - lo, lincr;
			if (m_Debug)
				System.Console.Error.WriteLine("Last stage of searching for beta condition (alam between " + Utils.doubleToString(lo, 10, 7) + " and " + Utils.doubleToString(hi, 10, 7) + ")...\n" + "Quadratic Interpolation(QI):\n" + "Last newSlope = " + Utils.doubleToString(newSlope, 10, 7));
			
			while ((newSlope < m_BETA * m_Slope) && (ldiff >= alamin))
			{
				lincr = (- 0.5) * newSlope * ldiff * ldiff / (fhi - flo - newSlope * ldiff);
				
				if (m_Debug)
					System.Console.Error.WriteLine("fhi = " + fhi + "\n" + "flo = " + flo + "\n" + "ldiff = " + ldiff + "\n" + "lincr (using QI) = " + lincr + "\n");
				
				if (lincr < 0.2 * ldiff)
					lincr = 0.2 * ldiff;
				alam = lo + lincr;
				if (alam >= hi)
				{
					// We cannot go beyond the bounds, so the best we can try is hi
					alam = hi;
					lincr = ldiff;
				}
				for (i = 0; i < len; i++)
					if (!isFixed[i])
						x[i] = xold[i] + alam * direct[i];
				m_f = objectiveFunction(x);
				if (System.Double.IsNaN(m_f))
					throw new System.Exception("Objective function value is NaN!");
				
				if (m_f > fold + m_ALF * alam * m_Slope)
				{
					// Alpha condition fails, shrink lambda_upper
					ldiff = lincr;
					fhi = m_f;
				}
				else
				{
					// Alpha condition holds	    
					newGrad = evaluateGradient(x);
					for (newSlope = 0.0, i = 0; i < len; i++)
						if (!isFixed[i])
							newSlope += newGrad[i] * direct[i];
					
					if (newSlope < m_BETA * m_Slope)
					{
						// Beta condition fails, shrink lambda_lower
						lo = alam;
						ldiff -= lincr;
						flo = m_f;
					}
				}
			}
			
			if (newSlope < m_BETA * m_Slope)
			{
				// Cannot satisfy beta condition, take lo
				if (m_Debug)
					System.Console.Error.WriteLine("Beta condition cannot be satisfied, take alpha condition");
				alam = lo;
				for (i = 0; i < len; i++)
					if (!isFixed[i])
						x[i] = xold[i] + alam * direct[i];
				m_f = flo;
			}
			else if (m_Debug)
				System.Console.Error.WriteLine("Both alpha and beta conditions are satisfied. alam=" + Utils.doubleToString(alam, 10, 7));
			
			if ((fixedOne != - 1) && (alam >= alpha))
			{
				// Has bounds and over
				if (direct[fixedOne] > 0)
				{
					x[fixedOne] = nwsBounds[1][fixedOne]; // Avoid rounding error
					nwsBounds[1][fixedOne] = System.Double.NaN; //Add cons. to working set
				}
				else
				{
					x[fixedOne] = nwsBounds[0][fixedOne]; // Avoid rounding error
					nwsBounds[0][fixedOne] = System.Double.NaN; //Add cons. to working set
				}
				
				if (m_Debug)
					System.Console.Error.WriteLine("Fix variable " + fixedOne + " to bound " + x[fixedOne] + " from value " + xold[fixedOne]);
				isFixed[fixedOne] = true; // Fix the variable
				wsBdsIndx.addElement(fixedOne);
			}
			
			return x;
		}