def QR_algorithm(A): """The straight QR algorithm for finding eigenvalues. N_POLYPOINTS.B. Has very slow convergence. Use shifted versions instead. .. code-block:: matlab function [myeig tmvec] = QRalgorithm(A) %------ Phase 1 ------ T = mytridiag(A); %------ Phase 2 ------ m = length(A); myeig = zeros(m,1); % Size of tmvec is not known in advance. % Estimating an initial size. tmvec = zeros(m^2,1); counter = 0; while (m > 1) counter = counter + 1; [Q,R] = myQR(T); T = R*Q; tmvec(counter) = abs(T(m,m-1)); if (tmvec(counter) < 1e-8) myeig(m) = T(m,m); m = m - 1; T = T(1:m,1:m); end end myeig(1) = T; tmvec = tmvec(1:counter); end :param A: A square matrix to find eigenvalues in. :type A: :py:class:`numpy.ndarray` :return: The eigenvalues. :rtype: list """ # First, tridiagonalize the input matrix to a Hessenberg matrix. T = ma.convert_to_Hessenberg_double(A.copy()) m, n = T.shape if n != m: raise np.linalg.LinAlgError("Array must be square.") convergence_measure = [] eigenvalues = np.zeros((n, ), dtype='float') n -= 1 while n > 0: # Perform QR decomposition. Q, R = ma.QR_factorisation_Householder_double(T) # Multiply R and Q. T = np.dot(R, Q) # Add convergence information and extract eigenvalue if close enough. convergence_measure.append(np.abs(T[n, n - 1])) if convergence_measure[-1] < QR_ALGORITHM_TOLERANCE: eigenvalues[n] = T[n, n] T = T[:n, :n] n -= 1 eigenvalues[0] = T return eigenvalues, convergence_measure
def QR_algorithm_Wilkinson_shift(A): """The QR algorithm with Wilkinson shift for finding eigenvalues. .. code-block:: matlab function [myeig tmvec] = QRwilkinson(A) %------ Phase 1 ------ T = mytridiag(A); %------ Phase 2 ------ m = length(A); myeig = zeros(m,1); % Size of tmvec is not known in advance. % Estimating an initial size. tmvec = zeros(m*8,1); mu = 0; counter = 0; while (m > 1) counter = counter + 1; muMat = diag(mu * ones(m,1)); [Q,R] = myQR(T - muMat); T = R*Q + muMat; tmvec(counter) = abs(T(m,m-1)); delta = (T(m-1,m-1) - T(m,m)) / 2; mu = T(m,m) - sign(delta) * T(m,m-1) / ... (abs(delta) + norm([delta T(m,m-1)])); if (tmvec(counter) < 1e-8) myeig(m) = T(m,m); m = m - 1; T = T(1:m,1:m); end end myeig(1) = T; tmvec = tmvec(1:counter); end :param A: The matrix to find eigenvalues in. :type A: :py:class:`numpy.ndarray` :return: The eigenvalues. :rtype: list """ # First, tridiagonalize the input matrix to a Hessenberg matrix. T = ma.convert_to_Hessenberg_double(A.copy()) m, n = T.shape convergence_measure = [] eigenvalues = np.zeros((m, ), dtype='float') m -= 1 mu = 0 while m > 0: mu_matrix = np.eye(T.shape[0]) * mu Q, R = ma.QR_factorisation_Householder_double(T - mu_matrix) T = np.dot(R, Q) + mu_matrix convergence_measure.append(np.abs(T[m, m - 1])) delta = (T[m - 1, m - 1] - T[m, m]) / 2 mu = T[m, m] - np.sign(delta) * T[m, m - 1] / \ (np.abs(delta) + np.linalg.norm([delta, T[m, m - 1]])) if convergence_measure[-1] < QR_ALGORITHM_TOLERANCE: eigenvalues[m] = T[m, m] T = T[:m, :m] m -= 1 eigenvalues[0] = T return eigenvalues, convergence_measure
def QR_algorithm_shift(A): """The QR algorithm with largest value shift for finding eigenvalues. Using Householder reflection QR decomposition for finding RQ. .. code-block:: matlab function [myeig tmvec] = QRshift(A) %------ Phase 1 ------ T = mytridiag(A); %------ Phase 2 ------ m = length(A); myeig = zeros(m,1); % Size of tmvec is not known in advance. % Estimating an initial size. tmvec = zeros(m*8,1); mu = 0; counter = 0; while (m > 1) counter = counter + 1; muMat = diag(mu * ones(m,1)); [Q,R] = myQR(T - muMat); T = R*Q + muMat; tmvec(counter) = abs(T(m,m-1)); mu = T(m,m) if (tmvec(counter) < 1e-8) myeig(m) = T(m,m); m = m - 1; T = T(1:m,1:m); end end myeig(1) = T; tmvec = tmvec(1:counter); end :param A: :type A: :return: The eigenvalues. :rtype: list """ # First, tridiagonalize the input matrix to a Hessenberg matrix. T = ma.convert_to_Hessenberg_double(A.copy()) m, n = T.shape if n != m: raise np.linalg.LinAlgError("Array must be square.") convergence_measure = [] eigenvalues = np.zeros((n, ), dtype='float') n -= 1 while n > 0: # Obtain the shift from the lower right corner of the matrix. mu_matrix = np.eye(T.shape[0]) * T[n, n] # Perform QR decomposition on the shifted matrix. Q, R = ma.QR_factorisation_Householder_double(T - mu_matrix) # Multiply R and Q and shift the matrix back. T = np.dot(R, Q) + mu_matrix # Add convergence information and extract eigenvalue if close enough. convergence_measure.append(np.abs(T[n, n - 1])) if convergence_measure[-1] < QR_ALGORITHM_TOLERANCE: eigenvalues[n] = T[n, n] T = T[:n, :n] n -= 1 eigenvalues[0] = T return eigenvalues, convergence_measure