def orthonormalize(matrix): # this function expects an already orthogonal matrix and thus does not check for the same Tmatrix = g.transpose(matrix) cols, rows = g.shape(Tmatrix) M = [] for col in range(cols): col_v = vector.orthonormal(vector.transform_to_column_vector(Tmatrix[col])) M.append(vector.transform_to_row_vector(col_v)) return g.transpose(M)
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 gram_schmidt_orthonormalize(matrix): Tmatrix = g.transpose(matrix) # no. of cols in 'matrix' are no. of rows in 'Tmatrix' # and no. of rows in 'matrix' are no. of cols in 'Tmatrix' cols, rows = g.shape(Tmatrix) M = [] M.append(Tmatrix[0]) for col in range(1, cols): col_v = vector.transform_to_column_vector(Tmatrix[col]) for m_col in range(len(M)): m_col_v = vector.transform_to_column_vector(M[m_col]) col_v = g.subtract(col_v, vector.projection(col_v, m_col_v)) M.append(vector.transform_to_row_vector(col_v)) return orthonormalize(g.transpose(M))
def eig(matrix, algo='householder'): # works only for real eigenvalues and eigenvectors # returns a row vector of eigenvalues and a matrix having eigenvectors along its columns # if can not converge eigenvalues it returns ev = -1 and ew = [[0]] size = check_for_square(matrix) if size == -1: print("can not find eigenvalues and eigenvectors of a non-square matrix") return ev = eigenvalues(matrix, algo) # ev is a row vector of eigenvalues if ev is None: # return 0 eigenvector return -1, [[0]] ew = [] # ew is the matrix that has eigenvectors in its column for i in range(len(ev)): M = g.subtract(matrix, g.multiply_by_scalar(identity_matrix(size), ev[i])) _add_column_of_zeros(M) M = reduced_row_echelon_form(M) x = gauss_elimination(M) # x is one eigen vector corrosponding to ev[i] x = vector.orthonormal(vector.transform_to_column_vector(x)) # making x a unit vector ew.append(vector.transform_to_row_vector(x)) ew = g.transpose(ew) return ev, ew
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 _get_householder_vectors(matrix, col): Tmatrix = g.transpose(matrix) _, rows = g.shape(Tmatrix) u = vector.transform_to_column_vector([Tmatrix[col][u_i] for u_i in range(col, rows)]) v = vector.transform_to_column_vector([vector.norm(u) if v_i == 0 else 0 for v_i in range(len(u))]) return u, v
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
def adjoint(matrix): if check_for_square(matrix) == -1: print("can not find adjoint of a non-square matrix") return -1 return g.transpose(cofactor_matrix(matrix))