コード例 #1
0
ファイル: optimization.cs プロジェクト: orlovk/PtProject
        /*************************************************************************
        This function prepares exact low-rank 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, positive semidefinite

        This preconditioner is exact but relatively slow -  it  requires  O(N*K^2)
        time to be prepared and O(N*K) time to be applied. It is  calculated  with
        the help of Woodbury matrix identity.

        It should be used as follows:
        * PrepareLowRankPreconditioner() call PREPARES data structure
        * subsequent calls to ApplyLowRankPreconditioner() APPLY preconditioner to
          user-specified search direction.

          -- ALGLIB --
             Copyright 30.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void preparelowrankpreconditioner(double[] d,
            double[] c,
            double[,] w,
            int n,
            int k,
            precbuflowrank buf)
        {
            int i = 0;
            int j = 0;
            double v = 0;
            bool b = new bool();

            
            //
            // Check inputs
            //
            alglib.ap.assert(n>0, "PrepareLowRankPreconditioner: N<=0");
            alglib.ap.assert(k>=0, "PrepareLowRankPreconditioner: N<=0");
            for(i=0; i<=n-1; i++)
            {
                alglib.ap.assert((double)(d[i])>(double)(0), "PrepareLowRankPreconditioner: D[]<=0");
            }
            for(i=0; i<=k-1; i++)
            {
                alglib.ap.assert((double)(c[i])>=(double)(0), "PrepareLowRankPreconditioner: C[]<0");
            }
            
            //
            // Prepare buffer structure; skip zero entries of update.
            //
            apserv.rvectorsetlengthatleast(ref buf.d, n);
            apserv.rmatrixsetlengthatleast(ref buf.v, k, n);
            apserv.rvectorsetlengthatleast(ref buf.bufc, k);
            apserv.rmatrixsetlengthatleast(ref buf.bufw, k+1, n);
            buf.n = n;
            buf.k = 0;
            for(i=0; i<=k-1; i++)
            {
                
                //
                // Estimate magnitude of update row; skip zero rows (either W or C are zero)
                //
                v = 0.0;
                for(j=0; j<=n-1; j++)
                {
                    v = v+w[i,j]*w[i,j];
                }
                v = v*c[i];
                if( (double)(v)==(double)(0) )
                {
                    continue;
                }
                alglib.ap.assert((double)(v)>(double)(0), "PrepareLowRankPreconditioner: internal error");
                
                //
                // Copy non-zero update to buffer
                //
                buf.bufc[buf.k] = c[i];
                for(j=0; j<=n-1; j++)
                {
                    buf.v[buf.k,j] = w[i,j];
                    buf.bufw[buf.k,j] = w[i,j];
                }
                apserv.inc(ref buf.k);
            }
            
            //
            // Reset K (for convenience)
            //
            k = buf.k;
            
            //
            // Prepare diagonal factor; quick exit for K=0
            //
            for(i=0; i<=n-1; i++)
            {
                buf.d[i] = 1/d[i];
            }
            if( k==0 )
            {
                return;
            }
            
            //
            // Use Woodbury matrix identity
            //
            apserv.rmatrixsetlengthatleast(ref buf.bufz, k, k);
            for(i=0; i<=k-1; i++)
            {
                for(j=0; j<=k-1; j++)
                {
                    buf.bufz[i,j] = 0.0;
                }
            }
            for(i=0; i<=k-1; i++)
            {
                buf.bufz[i,i] = 1/buf.bufc[i];
            }
            for(j=0; j<=n-1; j++)
            {
                buf.bufw[k,j] = 1/Math.Sqrt(d[j]);
            }
            for(i=0; i<=k-1; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    buf.bufw[i,j] = buf.bufw[i,j]*buf.bufw[k,j];
                }
            }
            ablas.rmatrixgemm(k, k, n, 1.0, buf.bufw, 0, 0, 0, buf.bufw, 0, 0, 1, 1.0, buf.bufz, 0, 0);
            b = trfac.spdmatrixcholeskyrec(ref buf.bufz, 0, k, true, ref buf.tmp);
            alglib.ap.assert(b, "PrepareLowRankPreconditioner: internal error (Cholesky failure)");
            ablas.rmatrixlefttrsm(k, n, buf.bufz, 0, 0, true, false, 1, buf.v, 0, 0);
            for(i=0; i<=k-1; i++)
            {
                for(j=0; j<=n-1; j++)
                {
                    buf.v[i,j] = buf.v[i,j]*buf.d[j];
                }
            }
        }
コード例 #2
0
ファイル: optimization.cs プロジェクト: orlovk/PtProject
        /*************************************************************************
        This function apply exact low-rank preconditioner prepared by
        PrepareLowRankPreconditioner function (see its comments for more information).

          -- ALGLIB --
             Copyright 30.06.2014 by Bochkanov Sergey
        *************************************************************************/
        public static void applylowrankpreconditioner(double[] s,
            precbuflowrank buf)
        {
            int n = 0;
            int k = 0;
            int i = 0;
            int j = 0;
            double v = 0;

            n = buf.n;
            k = buf.k;
            apserv.rvectorsetlengthatleast(ref buf.tmp, n);
            for(j=0; j<=n-1; j++)
            {
                buf.tmp[j] = buf.d[j]*s[j];
            }
            for(i=0; i<=k-1; i++)
            {
                v = 0.0;
                for(j=0; j<=n-1; j++)
                {
                    v = v+buf.v[i,j]*s[j];
                }
                for(j=0; j<=n-1; j++)
                {
                    buf.tmp[j] = buf.tmp[j]-v*buf.v[i,j];
                }
            }
            for(i=0; i<=n-1; i++)
            {
                s[i] = buf.tmp[i];
            }
        }
コード例 #3
0
ファイル: optimization.cs プロジェクト: orlovk/PtProject
 public override alglib.apobject make_copy()
 {
     precbuflowrank _result = new precbuflowrank();
     _result.n = n;
     _result.k = k;
     _result.d = (double[])d.Clone();
     _result.v = (double[,])v.Clone();
     _result.bufc = (double[])bufc.Clone();
     _result.bufz = (double[,])bufz.Clone();
     _result.bufw = (double[,])bufw.Clone();
     _result.tmp = (double[])tmp.Clone();
     return _result;
 }