diff --git a/qr-decom.py b/qr-decom.py index 774cac7..6a1dd8b 100644 --- a/qr-decom.py +++ b/qr-decom.py @@ -44,3 +44,62 @@ print("Q matrix:") print(Q) print("\nR matrix:") print(R) +print("Multiplied Together:") +print(Q@R) + +def svd_decomposition(A): + """ + Perform Singular Value Decomposition (SVD) from scratch. + + Arguments: + A -- The matrix to be decomposed (m x n). + + Returns: + U -- Orthogonal matrix of left singular vectors (m x m). + Sigma -- Diagonal matrix of singular values (m x n). + Vt -- Orthogonal matrix of right singular vectors (n x n). + """ + # Step 1: Compute A^T A + AtA = np.dot(A.T, A) # A transpose multiplied by A + + # Step 2: Compute the eigenvalues and eigenvectors of A^T A + eigenvalues, V = np.linalg.eig(AtA) + + # Step 3: Sort eigenvalues in descending order and sort V accordingly + sorted_indices = np.argsort(eigenvalues)[::-1] # Indices to sort eigenvalues in descending order + eigenvalues = eigenvalues[sorted_indices] + V = V[:, sorted_indices] + + # Step 4: Compute the singular values (sqrt of eigenvalues) + singular_values = np.sqrt(eigenvalues) + + # Step 5: Construct the Sigma matrix + m, n = A.shape + Sigma = np.zeros((m, n)) # Initialize Sigma as a zero matrix + for i in range(min(m, n)): + Sigma[i, i] = singular_values[i] # Place the singular values on the diagonal + + # Step 6: Compute the U matrix using A * V = U * Sigma + U = np.dot(A, V) # A * V gives us the unnormalized U + # Normalize the columns of U + for i in range(U.shape[1]): + U[:, i] = U[:, i] / singular_values[i] # Normalize each column by the corresponding singular value + + # Step 7: Return U, Sigma, Vt + return U, Sigma, V.T # V.T is the transpose of V + +# Example usage +A = np.array([[12, -51, 4], + [6, 167, -68], + [-4, 24, -41]]) + +U, Sigma, Vt = svd_decomposition(A) + +print("\nSVD DECOMPOSITION\nU matrix:") +print(U) +print("\nSigma matrix:") +print(Sigma) +print("\nVt matrix:") +print(Vt) +print("Multiplied together:") +print(U@Sigma@Vt)