Example #1
0
        protected static void lnsrch( int n, double[] xold, double fold, double[] g, double[] p, double[] x, out double f, double stpmax, out int check, BFGSFunctionEval _FunctionEval, object _Params )
        {
            int i;
            double a,alam,alam2 = 0.0,alamin,b,disc,f2 = 0.0,fold2 = 0.0,rhs1,rhs2,slope,sum,temp,test,tmplam;

            check=0;
            for ( sum=0.0,i=1; i <= n; i++ )
                sum += p[i]*p[i];
            sum = Math.Sqrt( sum );

            if ( sum > stpmax )
                for ( i=1; i <= n; i++ )
                    p[i] *= stpmax / sum;

            for ( slope=0.0,i=1; i <= n; i++ )
                slope += g[i] * p[i];

            test = 0.0;
            for ( i=1; i <= n; i++ )
            {
                temp = Math.Abs( p[i] ) / Math.Max( Math.Abs( xold[i] ), 1.0 );
                if ( temp > test )
                    test = temp;
            }

            alamin = TOLY / test;
            alam = 1.0;
            for (;;)
            {
                for ( i=1; i <= n; i++ )
                    x[i] = xold[i] + alam * p[i];

                f = _FunctionEval( x, _Params );
                if ( alam < alamin )
                {
                    for ( i=1; i <= n; i++ )
                        x[i] = xold[i];

                    check = 1;
                    return;
                }
                else if ( f <= fold + ALF * alam * slope )
                    return;
                else
                {
                    if ( alam == 1.0 )
                        tmplam = -slope / (2.0 * (f - fold-slope));
                    else
                    {
                        rhs1 = f-fold-alam*slope;
                        rhs2 = f2-fold2-alam2*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 = -slope/(2.0*b);
                        else
                        {
                            disc = b*b - 3.0 * a * slope;
                            if ( disc < 0.0 )
                                throw new Exception( "Roundoff problem in lnsrch." );
                            else
                                tmplam = (-b + Math.Sqrt( disc ) ) / (3.0 * a);
                        }
                        if ( tmplam > 0.5 * alam )
                            tmplam = 0.5 * alam;
                    }
                }
                alam2=alam;
                f2 = f;
                fold2=fold;
                alam = Math.Max( tmplam, 0.1*alam );
            }
        }
Example #2
0
        /// <summary>
        /// Performs BFGS function minimzation on a quadratic form function evaluated by the provided delegate
        /// </summary>
        /// <param name="_Coefficients">The array of initial coefficients (indexed from 1!!) that will also contain the resulting coefficients when the routine has converged</param>
        /// <param name="_ConvergenceTolerance">The tolerance error to accept as the minimum of the function</param>
        /// <param name="_PerformedIterationsCount">The amount of iterations performed to reach the minimum</param>
        /// <param name="_Minimum">The found minimum</param>
        /// <param name="_FunctionEval">The delegate used to evaluate the function to minimize</param>
        /// <param name="_FunctionGradientEval">The delegate used to evaluate the gradient of the function to minimize</param>
        /// <param name="_Params">Some user params passed to the evaluation functions</param>
        protected static void dfpmin( double[] _Coefficients, double _ConvergenceTolerance, out int _PerformedIterationsCount, out double _Minimum, BFGSFunctionEval _FunctionEval, BFGSFunctionGradientEval _FunctionGradientEval, object _Params )
        {
            int			n = _Coefficients.Length - 1;

            int			check,i,its,j;
            double		den,fac,fad,fae,fp,stpmax,sum=0.0,sumdg,sumxi,temp,test;

            double[]	dg = new double[1+n];
            double[]	g = new double[1+n];
            double[]	hdg = new double[1+n];
            double[][]	hessin = new double[1+n][];
            for ( i=1; i <= n; i++ )
                hessin[i] = new double[1+n];
            double[]	pnew = new double[1+n];
            double[]	xi = new double[1+n];

            // Initialize values
            fp = _FunctionEval( _Coefficients, _Params );
            _FunctionGradientEval( _Coefficients, g, _Params );

            for ( i=1; i <= n; i++ )
            {
                for ( j=1; j <= n; j++ )
                    hessin[i][j]=0.0;

                hessin[i][i] = 1.0;

                xi[i] = -g[i];
                sum += _Coefficients[i]*_Coefficients[i];
            }

            stpmax = STPMX * Math.Max( Math.Sqrt( sum ), n );
            for ( its=1; its <= ITMAX; its++ )
            {
                _PerformedIterationsCount = its;

                // The new function evaluation occurs in lnsrch
                lnsrch( n, _Coefficients, fp, g, xi, pnew, out _Minimum, stpmax, out check, _FunctionEval, _Params );
                fp = _Minimum;

                for ( i=1; i<=n; i++ )
                {
                    xi[i] = pnew[i] - _Coefficients[i];	// Update the line direction
                    _Coefficients[i] = pnew[i];			// as well as the current point
                }

                // Test for convergence on Delta X
                test = 0.0;
                for ( i=1; i <= n; i++ )
                {
                    temp = Math.Abs( xi[i] ) / Math.Max( Math.Abs( _Coefficients[i] ), 1.0 );
                    if ( temp > test )
                        test = temp;
                }

                if ( test < TOLX )
                    return;	// Done!

                // Save the old gradient
                for ( i=1; i <= n; i++ )
                    dg[i] = g[i];

                // Get the new one
                _FunctionGradientEval( _Coefficients, g, _Params );

                // Test for convergence on zero gradient
                test = 0.0;
                den = Math.Max( _Minimum, 1.0 );
                for ( i=1; i <= n; i++ )
                {
                    temp = Math.Abs( g[i] ) * Math.Max( Math.Abs( _Coefficients[i] ), 1.0 ) / den;
                    if ( temp > test )
                        test = temp;
                }

                if ( test < _ConvergenceTolerance )
                    return;	// Done!

                // Compute difference of gradients
                for ( i=1; i <= n ; i++ )
                    dg[i] = g[i]-dg[i];

                // ...and difference times current hessian matrix
                for ( i=1; i <= n; i++ )
                {
                    hdg[i]=0.0;
                    for ( j=1; j <= n; j++ )
                        hdg[i] += hessin[i][j] * dg[j];
                }

                // Calculate dot products for the denominators
                fac = fae = sumdg = sumxi = 0.0;
                for ( i=1; i <= n; i++ )
                {
                    fac += dg[i] * xi[i];
                    fae += dg[i] * hdg[i];
                    sumdg += dg[i] * dg[i];
                    sumxi += xi[i] * xi[i];
                }

                if ( fac * fac > EPS * sumdg * sumxi )
                {
                    fac = 1.0 / fac;
                    fad = 1.0 / fae;

                    // The vector that makes BFGS different from DFP
                    for ( i=1; i <= n; i++ )
                        dg[i] = fac * xi[i] - fad * hdg[i];

                    // BFGS Hessian update formula
                    for ( i=1; i <= n; i++ )
                        for ( j=1; j <= n; j++ )
                            hessin[i][j] += fac * xi[i] * xi[j] -fad * hdg[i] * hdg[j] + fae * dg[i] * dg[j];
                }

                // Now, calculate the next direction to go
                for ( i=1; i <= n; i++ )
                {
                    xi[i] = 0.0;
                    for ( j=1; j <= n; j++ )
                        xi[i] -= hessin[i][j] * g[j];
                }
            }

            throw new Exception( "Too many iterations in dfpmin" );
        }