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); }
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); }
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); }
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); }
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); }