public static AasenDecomposition LTLDecompose3(SymmetricMatrix M) { // Aasen's method, now with pivoting int n = M.Dimension; double[] a = new double[n]; double[] b = new double[n - 1]; SquareMatrix L = new SquareMatrix(n); for (int i = 0; i < n; i++) L[i, i] = 1.0; // working space for d'th column of H = T L^T double[] h = new double[n]; // first row a[0] = M[0, 0]; if (n > 1) b[0] = M[1, 0]; for (int i = 2; i < n; i++) L[i, 1] = M[i, 0] / b[0]; PrintLTLMatrices(h, a, b, L); // second row if (n > 1) { a[1] = M[1, 1]; if (n > 2) b[1] = M[2, 1] - L[2, 1] * a[1]; for (int i = 3; i < n; i++) L[i, 2] = (M[i, 1] - L[i, 1] * a[1]) / b[1]; } PrintLTLMatrices(h, a, b, L); for (int d = 0; d < n; d++) { Console.WriteLine("d = {0}", d); // compute h (d'th row of T L^T) if (d == 0) { h[0] = M[0, 0]; } else if (d == 1) { h[0] = b[0]; h[1] = M[1, 1]; } else { h[0] = b[0] * L[d, 1]; h[1] = b[1] * L[d, 2] + a[1] * L[d, 1]; h[d] = M[d, d] - L[d, 1] * h[1]; for (int i = 2; i < d; i++) { h[i] = b[i] * L[d, i + 1] + a[i] * L[d, i] + b[i - 1] * L[d, i - 1]; h[d] -= L[d, i] * h[i]; } } // compute alpha (d'th diagonal element of T) if ((d == 0) || (d == 1)) { a[d] = h[d]; } else { a[d] = h[d] - b[d - 1] * L[d, d - 1]; } Console.WriteLine("before pivot"); PrintMatrix(M); PrintMatrix(L); // find the pivot if (d < (n - 1)) { int p = d + 1; double q = M[p, d]; for (int i = d + 2; i < n; i++) { if (Math.Abs(M[i, d]) > Math.Abs(q)) { p = i; q = M[i, d]; } } Console.WriteLine("pivot = {0}", p); // symmetricly permute the pivot element to M[d+1,d] if (p != d + 1) { // symmetricly permute the pivot element to M[d+1, d] // we have to be a bit careful here, because some permutations will be done // automatically by our SymmetricMatrix class due to symmetry for (int i = 0; i < n; i++) { if ((i == p) || (i == d + 1)) continue; double t = M[d + 1, i]; M[d + 1, i] = M[p, i]; M[p, i] = t; } double tt = M[d + 1, d + 1]; M[d + 1, d + 1] = M[p, p]; M[p, p] = tt; // also reorder the affected previously computed elements of L for (int i = 1; i <= d; i++) { double t = L[d + 1, i]; L[d + 1, i] = L[p, i]; L[p, i] = t; } Console.WriteLine("after pivot"); PrintMatrix(M); PrintMatrix(L); } } // compute beta (d'th subdiagonal element of T) if (d < (n - 1)) { b[d] = M[d + 1, d]; for (int i = 0; i <= d; i++) { Console.WriteLine("n={0} d={1} i={2}", n, d, i); b[d] -= L[d + 1, i] * h[i]; } } // compute (d+1)'th column of L for (int i = d + 2; i < n; i++) { L[i, d + 1] = M[i, d]; for (int j = 0; j <= d; j++) L[i, d + 1] -= L[i, j] * h[j]; L[i, d + 1] = L[i, d + 1] / b[d]; } PrintLTLMatrices(h, a, b, L); } Console.WriteLine("Reconstruct"); SymmetricMatrix T = new SymmetricMatrix(n); for (int i = 0; i < n; i++) { T[i, i] = a[i]; } for (int i = 0; i < (n - 1); i++) { T[i + 1, i] = b[i]; } SquareMatrix A = L * T * L.Transpose(); PrintMatrix(A); SymmetricMatrix D = new SymmetricMatrix(n); for (int i = 0; i < n; i++) { D[i, i] = a[i]; } for (int i = 0; i < (n - 1); i++) { D[i + 1, i] = b[i]; } for (int c = 1; c < (n - 1); c++) { for (int r = c + 1; r < n; r++) { D[r, c - 1] = L[r, c]; } } AasenDecomposition LTL = new AasenDecomposition(D); return (LTL); }
public static AasenDecomposition LTLDecompose3(SymmetricMatrix M) { // Aasen's method, now with pivoting int n = M.Dimension; double[] a = new double[n]; double[] b = new double[n - 1]; SquareMatrix L = new SquareMatrix(n); for (int i = 0; i < n; i++) { L[i, i] = 1.0; } // working space for d'th column of H = T L^T double[] h = new double[n]; // first row a[0] = M[0, 0]; if (n > 1) { b[0] = M[1, 0]; } for (int i = 2; i < n; i++) { L[i, 1] = M[i, 0] / b[0]; } PrintLTLMatrices(h, a, b, L); // second row if (n > 1) { a[1] = M[1, 1]; if (n > 2) { b[1] = M[2, 1] - L[2, 1] * a[1]; } for (int i = 3; i < n; i++) { L[i, 2] = (M[i, 1] - L[i, 1] * a[1]) / b[1]; } } PrintLTLMatrices(h, a, b, L); for (int d = 0; d < n; d++) { Console.WriteLine("d = {0}", d); // compute h (d'th row of T L^T) if (d == 0) { h[0] = M[0, 0]; } else if (d == 1) { h[0] = b[0]; h[1] = M[1, 1]; } else { h[0] = b[0] * L[d, 1]; h[1] = b[1] * L[d, 2] + a[1] * L[d, 1]; h[d] = M[d, d] - L[d, 1] * h[1]; for (int i = 2; i < d; i++) { h[i] = b[i] * L[d, i + 1] + a[i] * L[d, i] + b[i - 1] * L[d, i - 1]; h[d] -= L[d, i] * h[i]; } } // compute alpha (d'th diagonal element of T) if ((d == 0) || (d == 1)) { a[d] = h[d]; } else { a[d] = h[d] - b[d - 1] * L[d, d - 1]; } Console.WriteLine("before pivot"); PrintMatrix(M); PrintMatrix(L); // find the pivot if (d < (n - 1)) { int p = d + 1; double q = M[p, d]; for (int i = d + 2; i < n; i++) { if (Math.Abs(M[i, d]) > Math.Abs(q)) { p = i; q = M[i, d]; } } Console.WriteLine("pivot = {0}", p); // symmetricly permute the pivot element to M[d+1,d] if (p != d + 1) { // symmetricly permute the pivot element to M[d+1, d] // we have to be a bit careful here, because some permutations will be done // automatically by our SymmetricMatrix class due to symmetry for (int i = 0; i < n; i++) { if ((i == p) || (i == d + 1)) { continue; } double t = M[d + 1, i]; M[d + 1, i] = M[p, i]; M[p, i] = t; } double tt = M[d + 1, d + 1]; M[d + 1, d + 1] = M[p, p]; M[p, p] = tt; // also reorder the affected previously computed elements of L for (int i = 1; i <= d; i++) { double t = L[d + 1, i]; L[d + 1, i] = L[p, i]; L[p, i] = t; } Console.WriteLine("after pivot"); PrintMatrix(M); PrintMatrix(L); } } // compute beta (d'th subdiagonal element of T) if (d < (n - 1)) { b[d] = M[d + 1, d]; for (int i = 0; i <= d; i++) { Console.WriteLine("n={0} d={1} i={2}", n, d, i); b[d] -= L[d + 1, i] * h[i]; } } // compute (d+1)'th column of L for (int i = d + 2; i < n; i++) { L[i, d + 1] = M[i, d]; for (int j = 0; j <= d; j++) { L[i, d + 1] -= L[i, j] * h[j]; } L[i, d + 1] = L[i, d + 1] / b[d]; } PrintLTLMatrices(h, a, b, L); } Console.WriteLine("Reconstruct"); SymmetricMatrix T = new SymmetricMatrix(n); for (int i = 0; i < n; i++) { T[i, i] = a[i]; } for (int i = 0; i < (n - 1); i++) { T[i + 1, i] = b[i]; } SquareMatrix A = L * T * L.Transpose(); PrintMatrix(A); SymmetricMatrix D = new SymmetricMatrix(n); for (int i = 0; i < n; i++) { D[i, i] = a[i]; } for (int i = 0; i < (n - 1); i++) { D[i + 1, i] = b[i]; } for (int c = 1; c < (n - 1); c++) { for (int r = c + 1; r < n; r++) { D[r, c - 1] = L[r, c]; } } AasenDecomposition LTL = new AasenDecomposition(D); return(LTL); }