static void probC() { Write("Problem C:\n"); var rand = new System.Random(); int n = 5 + rand.Next(3); matrix A = makeRandomMatrix(n, n); A.print("Make a random square matrix of random size: A = "); qr_givens decomp_givens = new qr_givens(A); qr_gs decomp_gs = new qr_gs(A); Write("\nDo the Givens decomposition and store the restult in the matrix G, which cotains the elements of the component R in the upper triangular part, and the angles for the Givens rotations in the relevant sub-diagonal entries. Compare with the R matrix found from the Gramm-Schmitt method:"); decomp_givens.G.print("Givens G: "); decomp_gs.R.print("Gram-Schmitt R: "); Write("The upper triangular parts are the same.\n"); vector b = makeRandomVector(n); b.print("\nMake a random vector b with the same size as A: b = "); Write("\nCompare using the Givens rotations to apply Q^(T) to b, and doing the explicit matrix multiplication with the Q matrix found by the Gramm-Schmitt method:\n"); decomp_givens.applyQT(b).print("Givens: Q^(T)*b = "); (decomp_gs.Q.transpose() * b).print("GS: Q^(T)*b = "); vector x = decomp_givens.solve(b); x.print("\nSolution to A*x=b using Givens: "); (A * x - b).print("\nCheck solution satisfies A*x = b: A*x-b = "); Write("\nFind the inverse of A, and check that A^(-1)*A is the identity matrix:\n"); decomp_givens.inverse().print("A^(-1)"); (decomp_givens.inverse() * A).print("A^(-1)*A = "); }
// Wrapper method to find the lowest eigenvalues faster than the // highest, by going the other way in the application of A; that is // by solving A*v2 = v1 instead of applying A*v1 = v2. public static void iterations_lowest( matrix A, // The input matrix matrix V, // The n x m matrix to contain V matrix T // The m x m matrix to contain the tridiagonal T matrix ) { // We need to solve a number of equations like: // A*x = b // However, this can be simplified by first finding the QR // decomposition of A: qr_givens A_decomp = new qr_givens(A); // Here the "A_decomp" object will be saved in the closure of the // "applyA" anonymous function, and thereby the decomposition is // only calculated once. Func <vector, vector> applyA = (v) => { return(A_decomp.solve(v)); }; iterations(applyA, V, T); }
public static vector newton( Func <vector, vector> f, // Vector function to find root of vector x, // The starting point double epsilon = 1e-3, // The accuracy goal double dx = 1e-7 // finite difference to be used for jacobian ) { //Write("One call to newton()\n"); vector root; vector f_x = f(x); // 1: Calculate Jacobian // Assume f has the same size as x? int n = x.size; matrix J = new matrix(n, n); for (int k = 0; k < n; k++) { vector new_x = x.copy(); new_x[k] += dx; vector diff_f = (f(new_x) - f_x) / dx; for (int i = 0; i < n; i++) { J[i, k] = diff_f[i]; } } // 2: Find delta_x by solving J*delta_x=-f qr_givens Jsolver = new qr_givens(J); vector delta_x = Jsolver.solve(-f_x); // 3: Find actual step by backtracking line search // This loop is hard to read, might have to change. double lambda = 1.0; while ((lambda >= 1.0 / 64) && (f(x + lambda * delta_x).norm() > (1 - lambda / 2) * f_x.norm())) { lambda /= 2; } x = x + lambda * delta_x; // Write($"f(x).norm = {f(x).norm()}\n"); // 4: Check if we are under tolerance // a: If under tolerance: Return value // b: If not under tolerance: Recursive call with new x if (delta_x.norm() < dx) { Error.Write("Step size {delta_x.norm()} is below finite diffrence dx\nStopping itterations and returning best found root..."); root = x; } else if (f(x).norm() < epsilon) { root = x; } else { root = newton(f, x, epsilon, dx); } return(root); }