def qr_householder(matrix): rows, cols = g.shape(matrix) Q = identity_matrix(rows) for i in range(cols): u, v = _get_householder_vectors(matrix, i) if not u or u == v: # 'u' and 'v' may be empty when called for the last column. hint: check for square matrix continue w = g.divide_by_scalar(g.subtract(u, v), vector.norm(g.subtract(u, v))) temp = g.multiply_by_scalar(g.multiply(w, g.transpose(w)), 2) H = g.subtract(identity_matrix(len(w)), temp) H = _add_identity_matrix_to_householder(H, i) Q = g.multiply(H, Q) matrix = g.multiply(H, matrix) return g.transpose(Q), matrix
def eigenvalues(matrix, algo='householder'): # returns a row vector of eigenvalues if algo == 'householder': qr_algo = qr_householder else: qr_algo = qr_gram_schmidt size = check_for_square(matrix) if size == -1: print("can not find eigenvalues of a non-square matrix!") return change = 1 E = diagonal(matrix) steps = 0 while change > 0.00000001: if steps > 50000: # eigenvalues are not converging return None Eold = E Q, R = qr_algo(matrix) matrix = g.multiply(R, Q) E = diagonal(matrix) change = vector.norm(g.subtract(E, Eold)) steps += 1 return vector.transform_to_row_vector(diagonal(matrix))
def tridiagonal(matrix): size = check_for_square(matrix) if size == -1: print("can not tridiagonalize a non-square matrix") return # H = I - w*transpose(w) # w = (u - v)/norm(u - v) # since the matrix is symmetric, we can extract 'u' vector from matrix rows and then transform it to column vector for i in range(size - 2): u = vector.transform_to_column_vector([matrix[i][u_i] for u_i in range(i + 1, size)]) v = vector.transform_to_column_vector([vector.norm(u) if v_i == 0 else 0 for v_i in range(len(u))]) w = g.divide_by_scalar(g.subtract(u, v), vector.norm(g.subtract(u, v))) temp = g.multiply_by_scalar(g.multiply(w, g.transpose(w)), 2) H = g.subtract(identity_matrix(len(w)), temp) H = _add_identity_matrix_to_householder(H, size - len(H)) matrix = g.multiply(H, g.multiply(matrix, H)) return matrix
def dot(v1, v2): return g.multiply(g.transpose(v1), v2)[0][0]
def qr_gram_schmidt(matrix): Q = gram_schmidt_orthonormalize(matrix) R = g.multiply(g.transpose(Q), matrix) # as Q is orthonormal matrix, so, transpose(Q) = inverse(Q) return Q, R