def compute_qr_factorization(mat: Matrix) -> (Matrix, Matrix): # Do not overwrite original matrix mat = mat.copy() householders = [] # store householder transformations iterations = min(mat.num_rows(), mat.num_cols()) for iteration in range(iterations): col = mat.get_col(iteration) # Zero out the entries below the diagonal hh = Householder(col[iteration:]) householders.append((iteration, hh)) mat = hh.multiply_left(mat, pad_top=iteration) # Accumulate the householder transformations q_mat = Matrix.identity(mat.num_rows()) for iteration, hh in householders[::-1]: q_mat = hh.multiply_left(q_mat, pad_top=iteration) return (q_mat, mat)
def reduce_to_bidiagonal( mat: Matrix) -> (Matrix, List[Householder], List[Householder]): mat = mat.copy() if mat.num_rows() != mat.num_cols(): raise ValueError("Matrix should be square") iterations = mat.num_rows() - 1 acc_left = [] acc_right = [] for iteration in range(iterations): # clear zeroes below diagonal col = mat.get_col(iteration)[iteration:] householder_left = Householder(col) mat = householder_left.multiply_left(mat, pad_top=iteration) acc_left.append(householder_left) if iteration != iterations - 1: # clear zeroes above superdiagonal row = mat.get_row(iteration)[iteration + 1:] householder_right = Householder(row) mat = householder_right.multiply_right(mat, pad_top=iteration + 1) acc_right.append(householder_right) return mat, acc_left, acc_right