## ## Utility functions for this chapter. ## exchange_two_rows = function(W, row_idx1, row_idx2){ row_copy = W[row_idx1, ] W[row_idx1, ] = W[row_idx2, ] W[row_idx2, ] = row_copy W } extract_U_matrix = function(W, n, ps, qs){ U = matrix(0, nrow=n, ncol=n) for(ii in 1:n){ for(jj in ii:n){ U[ii, jj] = W[ps[ii], qs[jj]] } } U } extract_L_matrix = function(W, n, ps, qs){ L = matrix(0, nrow=n, ncol=n) for(ii in 1:n){ for(jj in 1:ii){ if( jjtol || eigenvector_error>tol ){ lambda_est = lambda_next eigenvector_est = u }else{ results = list('max_eigenvalue'=lambda_est[1], 'max_eigenvector'=u, 'n_iterations'=iter, 'max_iter'=max_iter) break } } } if( !exists('results') ){ print(sprintf('ERROR: power method did not converge; iter= %d; max_iter= %d; lambda_error= %f; eigenvector_error= %f', iter, max_iter, lambda_error, eigenvector_error) ) results = NULL } results } determinant_from_GE = function(A){ ## ## Uses Gaussian elimination to compute the determinant of the matrix A ## if( FALSE ){ det = det(A) ## for debugging }else{ res = GE_w_scaled_partial_pivoting(A, rep(1, dim(A)[1])) ##res = GE_w_total_pivoting(A, rep(1, dim(A)[1])) det = (-1)^res$IFLAG * prod(diag(res$U)) } det } householder_reduction = function(A, verbose=FALSE){ ## ## Performs Householder reflections to reduce A to upper Hessenberg form. ## ## This code is designed to be easy to understand and not necessarily the most efficient. ## ## Returns upper Hessenberg matrix H and unitary P such that H = P * A * P' (with P'* P = I) ## n = dim(A)[1] H = A P = diag(n) for(kk in 1:(n-2)){ ## Tranform the kkth column: x_col = H[, kk] y = rep(0, n) y[(kk+1):n] = x_col[(kk+1):n] beta = sign(x_col[kk+1])*norm(x_col[(kk+1):n], '2') y[kk+1] = y[kk+1] + beta if( abs(beta*y[kk+1])>1.e-6 ){ ## avoid "divide by zero" alpha = 1/(beta*y[kk+1]) }else{ alpha = 1/(sign(beta*y[kk+1])*1.e-6) } R = diag(n) - alpha * y %*% t(y) ##print(round(R %*% R, 2)) ## should equal I P = R %*% P H = R %*% H %*% R if( verbose ){ print(sprintf('kk= %5d; y[kk+1]= %10.6e; beta= %10.6e; alpha= %10.6e', kk, y[kk+1], beta, alpha)) print(round(H, 3)) } } results = list('P'=P, 'H'=H) results } evaluate_symmetric_tridiagonal_characteristic_polynomial = function(lambda, as, bs, verbose=FALSE){ ## ## Evaluates the characteristic polynomial p(lambda) of a symmetric tridiagonal matrix. ## ## as= diagonal elements ## bs= sup/super diagonal elements ## ## ps[n+1] = p_n(lambda) ## pprimes[n+1] = p_n'(lambda) ## n = length(as) stopifnot(length(bs)==(n-1)) ps = rep(NA, n+1) pprimes = rep(NA, n+1) ps[1] = 1 ## p_0(lambda) ps[2] = as[1]-lambda ## p_1(lambda) pprimes[1] = 0 pprimes[2] = -1 for(jj in 3:(n+1)){ ps[jj] = (as[jj-1] - lambda)*ps[jj-1] - (bs[jj-2]^2)*ps[jj-2] pprimes[jj] = -ps[jj-1] + (as[jj-1] - lambda)*pprimes[jj-1] - (bs[jj-2]^2)*pprimes[jj-2] } result = list('ps'=ps, 'pprimes'=pprimes) result }