コード例 #1
0
ファイル: optimization.cs プロジェクト: orlovk/PtProject
        /*************************************************************************
        This function calculates inexact rank-K preconditioner for Hessian  matrix
        H=D+W'*C*W, where:
        * H is a Hessian matrix, which is approximated by D/W/C
        * D is a diagonal matrix with positive entries
        * W is a rank-K correction
        * C is a diagonal factor of rank-K correction

        This preconditioner is inexact but fast - it requires O(N*K)  time  to  be
        applied. Its main purpose - to be  used  in  barrier/penalty/AUL  methods,
        where ill-conditioning is created by combination of two factors:
        * simple bounds on variables => ill-conditioned D
        * general barrier/penalty => correction W  with large coefficient C (makes
          problem ill-conditioned) but W itself is well conditioned.

        Preconditioner P is calculated by artificially constructing a set of  BFGS
        updates which tries to reproduce behavior of H:
        * Sk = Wk (k-th row of W)
        * Yk = (D+Wk'*Ck*Wk)*Sk
        * Yk/Sk are reordered by ascending of C[k]*norm(Wk)^2

        Here we assume that rows of Wk are orthogonal or nearly orthogonal,  which
        allows us to have O(N*K+K^2) update instead of O(N*K^2) one. Reordering of
        updates is essential for having good performance on non-orthogonal problems
        (updates which do not add much of curvature are added first,  and  updates
        which add very large eigenvalues are added last and override effect of the
        first updates).

        On input this function takes direction S and components of H.
        On output it returns inv(H)*S

          -- ALGLIB --
             Copyright 30.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void inexactlbfgspreconditioner(double[] s,
            int n,
            double[] d,
            double[] c,
            double[,] w,
            int k,
            precbuflbfgs buf)
        {
            int idx = 0;
            int i = 0;
            int j = 0;
            double v = 0;
            double v0 = 0;
            double v1 = 0;
            double vx = 0;
            double vy = 0;
            int i_ = 0;

            apserv.rvectorsetlengthatleast(ref buf.norms, k);
            apserv.rvectorsetlengthatleast(ref buf.alpha, k);
            apserv.rvectorsetlengthatleast(ref buf.rho, k);
            apserv.rmatrixsetlengthatleast(ref buf.yk, k, n);
            apserv.ivectorsetlengthatleast(ref buf.idx, k);
            
            //
            // Check inputs
            //
            for(i=0; i<=n-1; i++)
            {
                alglib.ap.assert((double)(d[i])>(double)(0), "InexactLBFGSPreconditioner: D[]<=0");
            }
            for(i=0; i<=k-1; i++)
            {
                alglib.ap.assert((double)(c[i])>=(double)(0), "InexactLBFGSPreconditioner: C[]<0");
            }
            
            //
            // Reorder linear terms according to increase of second derivative.
            // Fill Norms[] array.
            //
            for(idx=0; idx<=k-1; idx++)
            {
                v = 0.0;
                for(i_=0; i_<=n-1;i_++)
                {
                    v += w[idx,i_]*w[idx,i_];
                }
                buf.norms[idx] = v*c[idx];
                buf.idx[idx] = idx;
            }
            tsort.tagsortfasti(ref buf.norms, ref buf.idx, ref buf.bufa, ref buf.bufb, k);
            
            //
            // Apply updates
            //
            for(idx=0; idx<=k-1; idx++)
            {
                
                //
                // Select update to perform (ordered by ascending of second derivative)
                //
                i = buf.idx[idx];
                
                //
                // Calculate YK and Rho
                //
                v = 0.0;
                for(i_=0; i_<=n-1;i_++)
                {
                    v += w[i,i_]*w[i,i_];
                }
                v = v*c[i];
                for(j=0; j<=n-1; j++)
                {
                    buf.yk[i,j] = (d[j]+v)*w[i,j];
                }
                v = 0.0;
                v0 = 0.0;
                v1 = 0.0;
                for(j=0; j<=n-1; j++)
                {
                    vx = w[i,j];
                    vy = buf.yk[i,j];
                    v = v+vx*vy;
                    v0 = v0+vx*vx;
                    v1 = v1+vy*vy;
                }
                if( ((double)(v)>(double)(0) && (double)(v0*v1)>(double)(0)) && (double)(v/Math.Sqrt(v0*v1))>(double)(n*10*math.machineepsilon) )
                {
                    buf.rho[i] = 1/v;
                }
                else
                {
                    buf.rho[i] = 0.0;
                }
            }
            for(idx=k-1; idx>=0; idx--)
            {
                
                //
                // Select update to perform (ordered by ascending of second derivative)
                //
                i = buf.idx[idx];
                
                //
                // Calculate Alpha[] according to L-BFGS algorithm
                // and update S[]
                //
                v = 0.0;
                for(i_=0; i_<=n-1;i_++)
                {
                    v += w[i,i_]*s[i_];
                }
                v = buf.rho[i]*v;
                buf.alpha[i] = v;
                for(i_=0; i_<=n-1;i_++)
                {
                    s[i_] = s[i_] - v*buf.yk[i,i_];
                }
            }
            for(j=0; j<=n-1; j++)
            {
                s[j] = s[j]/d[j];
            }
            for(idx=0; idx<=k-1; idx++)
            {
                
                //
                // Select update to perform (ordered by ascending of second derivative)
                //
                i = buf.idx[idx];
                
                //
                // Calculate Beta according to L-BFGS algorithm
                // and update S[]
                //
                v = 0.0;
                for(i_=0; i_<=n-1;i_++)
                {
                    v += buf.yk[i,i_]*s[i_];
                }
                v = buf.alpha[i]-buf.rho[i]*v;
                for(i_=0; i_<=n-1;i_++)
                {
                    s[i_] = s[i_] + v*w[i,i_];
                }
            }
        }
コード例 #2
0
ファイル: optimization.cs プロジェクト: orlovk/PtProject
 public override alglib.apobject make_copy()
 {
     precbuflbfgs _result = new precbuflbfgs();
     _result.norms = (double[])norms.Clone();
     _result.alpha = (double[])alpha.Clone();
     _result.rho = (double[])rho.Clone();
     _result.yk = (double[,])yk.Clone();
     _result.idx = (int[])idx.Clone();
     _result.bufa = (double[])bufa.Clone();
     _result.bufb = (int[])bufb.Clone();
     return _result;
 }