예제 #1
0
        public static MatrixByArr GetHessian(this IList <Mode> modes, ILinAlg la)
        {
            Vector[]    eigvecs = modes.ListEigvec().ToArray();
            Vector      eigvals = modes.ListEigval().ToArray();
            MatrixByArr hess;

            {
                var V = la.ToILMat(eigvecs.ToMatrix());
                var D = la.ToILMat(eigvals).Diag();
                var H = la.Mul(V, D, V.Tr);
                hess = H.ToArray();
                V.Dispose();
                D.Dispose();
                H.Dispose();
            }
            return(hess);
        }
예제 #2
0
        public static MatrixByArr GetHessian(this IList <Mode> modes, IList <double> masses, ILinAlg la)
        {
            /// mode.eigval =             mweigval
            /// mode.eigvec = mass^-0.5 * mweigvec
            ///
            /// W = [mode(1).eigvec, mode(2).eigvec, ... ]
            /// M = masses
            /// D = diag([mode(1).eigval, mode(2).eigval, ...])
            ///
            /// mwH = M^-0.5 H M^-0.5
            /// [V,D] = eig(mwH)
            /// mode.eigval == D
            /// mode.eigvec == M^-0.5 V = W
            ///
            /// W D W' = M^-0.5       V D V       M^-0.5
            ///        = M^-0.5        mwH        M^-0.5
            ///        = M^-0.5 (M^-0.5 H M^-0.5) M^-0.5
            ///        = M^-1           H         M^-1
            /// H = M (M^-1 H M^-1) M
            ///   = M (W    D   W') M
            ///   = (M W)   D   (M W)'
            HDebug.Assert(modes.CheckModeMassReduced(masses.ToArray(), la, 0.000001));

            Vector[] mws = modes.ListEigvec().ToArray();
            for (int iv = 0; iv < mws.Length; iv++)
            {
                for (int i = 0; i < mws[iv].Size; i++)
                {
                    mws[iv][i] = mws[iv][i] * masses[i / 3];
                }
            }
            Vector      ds = modes.ListEigval().ToArray();
            MatrixByArr hess;

            {
                var MW = la.ToILMat(mws.ToMatrix());
                var D  = la.ToILMat(ds).Diag();
                var H  = la.Mul(MW, D, MW.Tr);
                hess = H.ToArray();
                MW.Dispose();
                D.Dispose();
                H.Dispose();
            }
            return(hess);
        }
예제 #3
0
        public static Matrix OverlapSigned(IList <Mode> modes1, double[] mass1, double[] mass2, IList <Mode> modes2, ILinAlg ila, bool bResetUnitVector)
        {
            Matrix mat1;
            Matrix mat2;
            string mat12opt = "memory-save";

            switch (mat12opt)
            {
            case "initial":
            {
                Vector[] eigvecs1 = new Vector[modes1.Count]; for (int i = 0; i < modes1.Count; i++)
                {
                    eigvecs1[i] = modes1[i].eigvec.Clone();
                }
                Vector[] eigvecs2 = new Vector[modes2.Count]; for (int i = 0; i < modes2.Count; i++)
                {
                    eigvecs2[i] = modes2[i].eigvec.Clone();
                }
                {
                    // 1. Hess
                    // 2. mwHess <- M^-0.5 * H * M^-0.5
                    // 3. [V,D]  <- eig(mwHess)
                    // 4. mrMode <- M^-0.5 * V
                    //
                    // overlap: vi . vj
                    // 1. vi <- M^0.5 * mrMode_i
                    // 2. vj <- M^0.5 * mrMode_j
                    // 3. vi.vj <- dot(vi,vj)
                    //
                    //         [ 2           ]   [4]   [2*4]   [ 8]
                    //         [   2         ]   [5]   [2*5]   [10]
                    // M * v = [     2       ] * [6] = [2*6] = [12]
                    //         [       3     ]   [7]   [3*7]   [21]
                    //         [         3   ]   [8]   [3*8]   [24]
                    //         [           3 ]   [9]   [3*9]   [27]
                    //
                    // V1 <- sqrt(M1) * V1
                    // V2 <- sqrt(M2) * V2
                    //                           1. get sqrt(mass)          2. for each eigenvector              3 eigveci[j] = eigvec[j] * sqrt_mass[j/3]
                    if (mass1 != null)
                    {
                        double[] mass1sqrt = mass1.HSqrt(); for (int i = 0; i < eigvecs1.Length; i++)
                        {
                            for (int j = 0; j < eigvecs1[i].Size; j++)
                            {
                                eigvecs1[i][j] *= mass1sqrt[j / 3];
                            }
                        }
                    }
                    if (mass2 != null)
                    {
                        double[] mass2sqrt = mass2.HSqrt(); for (int i = 0; i < eigvecs2.Length; i++)
                        {
                            for (int j = 0; j < eigvecs2[i].Size; j++)
                            {
                                eigvecs2[i][j] *= mass2sqrt[j / 3];
                            }
                        }
                    }
                }
                if (bResetUnitVector)
                {
                    for (int i = 0; i < modes1.Count; i++)
                    {
                        eigvecs1[i] = eigvecs1[i].UnitVector();
                    }
                    for (int i = 0; i < modes2.Count; i++)
                    {
                        eigvecs2[i] = eigvecs2[i].UnitVector();
                    }
                }

                mat1 = eigvecs1.ToMatrix(false); HDebug.Assert(mat1.ColSize == eigvecs1.Length); eigvecs1 = null; GC.Collect(0);
                mat2 = eigvecs2.ToMatrix(true); HDebug.Assert(mat2.RowSize == eigvecs2.Length); eigvecs2 = null; GC.Collect(0);
            }
            break;

            case "memory-save":
            {
                int vecsize = modes1[0].eigvec.Size;
                HDebug.Exception(vecsize == modes1[0].eigvec.Size);
                HDebug.Exception(vecsize == modes2[0].eigvec.Size);

                //Vector[] eigvecs1 = new Vector[modes1.Count]; for(int i=0; i<modes1.Count; i++) eigvecs1[i] = modes1[i].eigvec.Clone();
                //if(mass1 != null) { double[] mass1sqrt = mass1.HSqrt(); for(int i=0; i<modes1.Count; i++) for(int j=0; j<eigvecs1[i].Size; j++) eigvecs1[i][j] *= mass1sqrt[j/3]; }
                //if(bResetUnitVector) for(int i=0; i<modes1.Count; i++) eigvecs1[i] = eigvecs1[i].UnitVector();
                //mat1 = eigvecs1.ToMatrix(false); HDebug.Assert(mat1.ColSize == modes1.Count); eigvecs1 = null; GC.Collect(0);
                mat1 = Matrix.Zeros(modes1.Count, vecsize);
                double[] mass1sqrt = null; if (mass1 != null)
                {
                    mass1sqrt = mass1.HSqrt();
                }
                for (int i = 0; i < modes1.Count; i++)
                {
                    Vector eigvecs1i = modes1[i].eigvec.Clone();
                    if (mass1 != null)
                    {
                        for (int j = 0; j < eigvecs1i.Size; j++)
                        {
                            eigvecs1i[j] *= mass1sqrt[j / 3];
                        }
                    }
                    if (bResetUnitVector)
                    {
                        eigvecs1i = eigvecs1i.UnitVector();
                    }
                    for (int j = 0; j < eigvecs1i.Size; j++)
                    {
                        mat1[i, j] = eigvecs1i[j];
                    }
                }
                HDebug.Assert(mat1.ColSize == modes1.Count);
                GC.Collect(0);

                //Vector[] eigvecs2 = new Vector[modes2.Count]; for(int i=0; i<modes2.Count; i++) eigvecs2[i] = modes2[i].eigvec.Clone();
                //if(mass2 != null) { double[] mass2sqrt = mass2.HSqrt(); for(int i=0; i<modes2.Count; i++) for(int j=0; j<eigvecs2[i].Size; j++) eigvecs2[i][j] *= mass2sqrt[j/3]; }
                //if(bResetUnitVector) for(int i=0; i<modes2.Count; i++) eigvecs2[i] = eigvecs2[i].UnitVector();
                //mat2 = eigvecs2.ToMatrix(true ); HDebug.Assert(mat2.RowSize == modes2.Count); eigvecs2 = null; GC.Collect(0);
                mat2 = Matrix.Zeros(vecsize, modes2.Count);
                double[] mass2sqrt = null; if (mass2 != null)
                {
                    mass2sqrt = mass2.HSqrt();
                }
                for (int i = 0; i < modes2.Count; i++)
                {
                    Vector eigvecs2i = modes2[i].eigvec.Clone();
                    if (mass2 != null)
                    {
                        for (int j = 0; j < eigvecs2i.Size; j++)
                        {
                            eigvecs2i[j] *= mass2sqrt[j / 3];
                        }
                    }
                    if (bResetUnitVector)
                    {
                        eigvecs2i = eigvecs2i.UnitVector();
                    }
                    for (int j = 0; j < eigvecs2i.Size; j++)
                    {
                        mat2[j, i] = eigvecs2i[j];
                    }
                }
                HDebug.Assert(mat2.RowSize == modes2.Count);
                GC.Collect(0);
            }
            break;

            default:
                throw new NotImplementedException();
            }

            HDebug.Assert(mat1.RowSize == mat2.ColSize);
            Matrix overlap = null;

            if (ila != null)
            {
                overlap = ila.Mul(mat1, mat2);
            }
            else
            {
                overlap = Matlab.ila.Mul(mat1, mat2);
            }
            mat1 = mat2 = null;
            GC.Collect(0);
            //overlap.UpdateAbs();

            if (HDebug.IsDebuggerAttached)
            {
                double[] sum_c2 = new double[overlap.ColSize];
                double[] sum_r2 = new double[overlap.RowSize];
                for (int c = 0; c < overlap.ColSize; c++)
                {
                    for (int r = 0; r < overlap.RowSize; r++)
                    {
                        double v  = overlap[c, r];
                        double v2 = v * v;
                        HDebug.Assert(v2 <= 1.00000000001);
                        sum_c2[c] += v2;
                        sum_r2[r] += v2;
                    }
                }
                for (int c = 0; c < overlap.ColSize; c++)
                {
                    HDebug.AssertTolerance(0.00001, sum_c2[c] - 1.0);
                }
                for (int r = 0; r < overlap.RowSize; r++)
                {
                    HDebug.AssertTolerance(0.00001, sum_r2[r] - 1.0);
                }
            }

            return(overlap);
        }
예제 #4
0
        static HessMatrix GetMulImpl(HessMatrix left, HessMatrix right, ILinAlg ila, bool warning)
        {
            if (HDebug.Selftest())
            {
                Matrix h1 = new double[, ] {
                    { 0, 1, 2, 3, 4, 5 }
                    , { 1, 2, 3, 4, 5, 6 }
                    , { 2, 3, 4, 5, 6, 7 }
                    , { 3, 4, 5, 6, 7, 8 }
                    , { 4, 5, 6, 7, 8, 9 }
                    , { 5, 6, 7, 8, 9, 0 }
                };
                HessMatrix h2    = HessMatrixSparse.FromMatrix(h1);
                Matrix     h11   = Matrix.GetMul(h1, h1);
                HessMatrix h22   = HessMatrix.GetMulImpl(h2, h2, null, false);
                Matrix     hdiff = h11 - h22;
                HDebug.AssertToleranceMatrix(0, hdiff);
            }
            if ((left is HessMatrixDense) && (right is HessMatrixDense))
            {
                if (ila != null)
                {
                    return(new HessMatrixDense {
                        hess = ila.Mul(left, right)
                    });
                }
                if (warning)
                {
                    HDebug.ToDo("Check (HessMatrixDense * HessMatrixDense) !!!");
                }
            }

            Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > > left_ic_rows = new Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > >();

            foreach (var ic_row in left.EnumRowBlocksAll())
            {
                left_ic_rows.Add(ic_row.Item1, ic_row.Item2.HToDictionaryWithKeyItem2());
            }

            Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > > right_ir_cols = new Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > >();

            foreach (var ir_col in right.EnumColBlocksAll())
            {
                right_ir_cols.Add(ir_col.Item1, ir_col.Item2.HToDictionaryWithKeyItem1());
            }

            HessMatrix mul = null;

            if ((left is HessMatrixDense) && (right is HessMatrixDense))
            {
                mul = HessMatrixDense.ZerosDense(left.ColSize, right.RowSize);
            }
            else
            {
                mul = HessMatrixSparse.ZerosSparse(left.ColSize, right.RowSize);
            }
            for (int ic = 0; ic < left.ColBlockSize; ic++)
            {
                var left_row = left_ic_rows[ic];
                if (left_row.Count == 0)
                {
                    continue;
                }
                for (int ir = 0; ir < right.RowBlockSize; ir++)
                {
                    var right_col = right_ir_cols[ir];
                    if (right_col.Count == 0)
                    {
                        continue;
                    }
                    foreach (var left_ck in left_row)
                    {
                        int ik = left_ck.Key;
                        HDebug.Assert(ic == left_ck.Value.Item1);
                        HDebug.Assert(ik == left_ck.Value.Item2);
                        if (right_col.ContainsKey(ik))
                        {
                            var right_kr = right_col[ik];
                            HDebug.Assert(ik == right_kr.Item1);
                            HDebug.Assert(ir == right_kr.Item2);
                            MatrixByArr mul_ckr = mul.GetBlock(ic, ir) + left_ck.Value.Item3 * right_kr.Item3;
                            mul.SetBlock(ic, ir, mul_ckr);
                        }
                    }
                }
            }

            return(mul);
        }
예제 #5
0
        public static Matrix GetInvSprTensor(Matrix H, Matrix S, ILinAlg ila)
        {
            Matrix invH;
            string optInvH = "EigSymmTol";

            optInvH += ((ila == null) ? "-matlab" : "-ilnum");
            switch (optInvH)
            {
            case "InvSymm-ilnum":
                HDebug.Assert(false);
                invH = ila.InvSymm(H);
                break;

            case "PInv-ilnum":
                invH = ila.PInv(H);
                break;

            case "EigSymm-ilnum":
            {
                var HH   = ila.ToILMat(H);
                var VVDD = ila.EigSymm(HH);
                var VV   = VVDD.Item1;
                for (int i = 0; i < VVDD.Item2.Length; i++)
                {
                    VVDD.Item2[i] = 1 / VVDD.Item2[i];
                }
                for (int i = 0; i < 6; i++)
                {
                    VVDD.Item2[i] = 0;
                }
                var DD    = ila.ToILMat(VVDD.Item2).Diag();
                var invHH = ila.Mul(VV, DD, VV.Tr);
                invH = invHH.ToArray();
                //var check = (H * invH).ToArray();
                GC.Collect();
            }
            break;

            case "EigSymmTol-matlab":
            {
                using (new Matlab.NamedLock(""))
                {
                    Matlab.PutMatrix("invHH.HH", H);
                    Matlab.Execute("invHH.HH = (invHH.HH + invHH.HH')/2;");
                    Matlab.Execute("[invHH.VV, invHH.DD] = eig(invHH.HH);");
                    Matlab.Execute("invHH.DD = diag(invHH.DD);");
                    Matlab.Execute("invHH.DD(abs(invHH.DD)<0.00001) = 0;");
                    Matlab.Execute("invHH.DD = pinv(diag(invHH.DD));");
                    Matlab.Execute("invHH = invHH.VV * invHH.DD * invHH.VV';");
                    invH = Matlab.GetMatrix("invHH");
                    Matlab.Execute("clear invHH;");
                }
                GC.Collect();
            }
            break;

            case "EigSymmTol-ilnum":
            {
                var HH   = ila.ToILMat(H);
                var VVDD = ila.EigSymm(HH);
                var VV   = VVDD.Item1;
                for (int i = 0; i < VVDD.Item2.Length; i++)
                {
                    if (Math.Abs(VVDD.Item2[i]) < 0.00001)
                    {
                        VVDD.Item2[i] = 0;
                    }
                    else
                    {
                        VVDD.Item2[i] = 1 / VVDD.Item2[i];
                    }
                }
                var DD    = ila.ToILMat(VVDD.Item2).Diag();
                var invHH = ila.Mul(VV, DD, VV.Tr);
                invH = invHH.ToArray();
                //var check = (H * invH).ToArray();
                GC.Collect();
            }
            break;

            default:
                throw new NotImplementedException();
            }

            Matrix invkij = 0.5 * (S.Tr() * invH * S);

            //HDebug.Assert(invkij >= 0);

            return(invkij);
        }