From 5e7a603a2d08eebb295d11745c3237d8972ec0ae Mon Sep 17 00:00:00 2001 From: uditgulati Date: Sat, 24 Aug 2019 22:55:54 +0530 Subject: [PATCH 1/4] Partially implement qr --- lib/nmatrix/lapack.rb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/nmatrix/lapack.rb b/lib/nmatrix/lapack.rb index 09e642f..29f4644 100644 --- a/lib/nmatrix/lapack.rb +++ b/lib/nmatrix/lapack.rb @@ -106,9 +106,26 @@ def self.qr(matrix, mode: "full", pivoting: false) end m, n = matrix.shape - if pivoting == false + if pivoting == true + + else qr, tau = NumRuby::Lapack.geqrf(matrix) + end + + # calc R here for both pivot true & false + + if mode == 'r' + + elsif mode == 'raw' return [qr, tau] end + + if m < n + q = NumRuby::Lapack.orgqr(qr[0...m, 0...m], tau) + else + q = NumRuby::Lapack.orgqr(qr, tau) + end + + return q end end \ No newline at end of file From b8feec00d2566959114c49e06b2a8ef145bb978b Mon Sep 17 00:00:00 2001 From: uditgulati Date: Mon, 26 Aug 2019 11:07:45 +0530 Subject: [PATCH 2/4] Implement qr decomposition --- lib/nmatrix/lapack.rb | 45 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/nmatrix/lapack.rb b/lib/nmatrix/lapack.rb index 29f4644..1298165 100644 --- a/lib/nmatrix/lapack.rb +++ b/lib/nmatrix/lapack.rb @@ -60,11 +60,9 @@ def self.lu_solve(matrix, rhs_val) end - # Computes the QR decomposition of matrix. + # Computes the SVD decomposition of matrix. # Args: # - input matrix, type: NMatrix - # - mode, type: String - # - pivoting, type: Boolean def self.svd(matrix) end @@ -89,11 +87,24 @@ def self.cholesky_solve(matrix) end - # Computes the QR decomposition of matrix. + # Computes QR decomposition of a matrix. + # + # Calculates the decomposition A = Q*R where Q is unitary/orthogonal and R is upper triangular. + # # Args: - # - input matrix, type: NMatrix + # - matrix, type: NMatrix + # Matrix to be decomposed # - mode, type: String + # Determines what information is to be returned: either both Q and R + # ('full', default), only R ('r') or both Q and R but computed in + # economy-size ('economic', see Notes). The final option 'raw' + # (added in Scipy 0.11) makes the function return two matrices + # (Q, TAU) in the internal format used by LAPACK. # - pivoting, type: Boolean + # Whether or not factorization should include pivoting for rank-revealing + # qr decomposition. If pivoting, compute the decomposition + # A*P = Q*R as above, but where P is chosen such that the diagonal + # of R is non-increasing. def self.qr(matrix, mode: "full", pivoting: false) if not ['full', 'r', 'economic', 'raw'].include?(mode.downcase) raise("Invalid mode. Should be one of ['full', 'r', 'economic', 'raw']") @@ -107,25 +118,41 @@ def self.qr(matrix, mode: "full", pivoting: false) m, n = matrix.shape if pivoting == true - + qr, tau, jpvt = NumRuby::Lapack.geqp3(matrix) + jpvt -= 1 else qr, tau = NumRuby::Lapack.geqrf(matrix) end - # calc R here for both pivot true & false + # calculate R here for both pivot true & false - if mode == 'r' + if ['economic', 'raw'].include?(mode.downcase) or m < n + r = NumRuby.triu(matrix) + else + r = NumRuby.triu(matrix[0...n, 0...n]) + end + if pivoting == true + rj = r, jpvt + else + rj = r + end + + if mode == 'r' + return rj elsif mode == 'raw' return [qr, tau] end if m < n q = NumRuby::Lapack.orgqr(qr[0...m, 0...m], tau) + elsif mode == 'economic' + q = NumRuby::Lapack.orgqr(qr, tau) else + # TODO: Implement slice view and set slice q = NumRuby::Lapack.orgqr(qr, tau) end - return q + return q, rj end end \ No newline at end of file From 5569f62dbeade1b3aa0d908990e51de7b562cb6c Mon Sep 17 00:00:00 2001 From: uditgulati Date: Mon, 26 Aug 2019 14:14:35 +0530 Subject: [PATCH 3/4] Implement solve and det in Linalg --- .vscode/c_cpp_properties.json | 16 ++++++++++++++++ lib/nmatrix/lapack.rb | 34 ++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..0b0eed0 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/lib/nmatrix/lapack.rb b/lib/nmatrix/lapack.rb index 1298165..7065cb6 100644 --- a/lib/nmatrix/lapack.rb +++ b/lib/nmatrix/lapack.rb @@ -1,8 +1,20 @@ module NumRuby::Linalg - def self.inv(obj) - if obj.is_a?(NMatrix) - return obj.invert + def self.inv(matrix) + if not matrix.is_a?(NMatrix) + raise("Invalid matrix. Not of type NMatrix.") + end + if matrix.dim != 2 + raise("Invalid shape of matrix. Should be 2.") end + if matrix.shape[0] != matrix.shape[1] + raise("Invalid shape. Expected square matrix.") + end + m, n = matrix.shape + + lu, ipiv = NumRuby::Lapack.getrf(matrix) + inv_a = NumRuby::Lapack.getri(lu, ipiv) + + return inv_a end def self.dot(lha, rha) @@ -13,12 +25,22 @@ def self.norm end - def self.solve - + def self.solve(a, b, sym_pos: False, lower: False, assume_a: "gen", transposed: False) + # TODO: implement this and remove NMatrix.solve end - def self.det + def self.det(matrix) + if not matrix.is_a?(NMatrix) + raise("Invalid matrix. Not of type NMatrix.") + end + if matrix.dim != 2 + raise("Invalid shape of matrix. Should be 2.") + end + if matrix.shape[0] != matrix.shape[1] + raise("Invalid shape. Expected square matrix.") + end + return matrix.det end def self.least_square From 4e4daf2d24529860a598458f1edecfb330226c62 Mon Sep 17 00:00:00 2001 From: uditgulati Date: Mon, 26 Aug 2019 14:34:40 +0530 Subject: [PATCH 4/4] lu, lu_factor, lu_solve --- .gitignore | 4 +++- .vscode/c_cpp_properties.json | 16 ---------------- lib/nmatrix/lapack.rb | 30 ++++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 19 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json diff --git a/.gitignore b/.gitignore index 6310525..881286d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ Gemfile.lock /.yardoc .rake_tasks~ -*.so \ No newline at end of file +*.so +.vscode + diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 0b0eed0..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "configurations": [ - { - "name": "Linux", - "includePath": [ - "${workspaceFolder}/**" - ], - "defines": [], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "clang-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/lib/nmatrix/lapack.rb b/lib/nmatrix/lapack.rb index 7065cb6..9779c63 100644 --- a/lib/nmatrix/lapack.rb +++ b/lib/nmatrix/lapack.rb @@ -70,16 +70,42 @@ def self.eigvalsh # Matrix Decomposition - def self.lu(matrix) + def self.lu(matrix, permute_l: False) + if not matrix.is_a?(NMatrix) + raise("Invalid matrix. Not of type NMatrix.") + end + if matrix.dim != 2 + raise("Invalid shape of matrix. Should be 2.") + end + + lu, ipiv = NumRuby::Linalg.getrf(matrix) + # TODO: calulate p, l, u end def self.lu_factor(matrix) + if not matrix.is_a?(NMatrix) + raise("Invalid matrix. Not of type NMatrix.") + end + if matrix.dim != 2 + raise("Invalid shape of matrix. Should be 2.") + end + if matrix.shape[0] != matrix.shape[1] + raise("Invalid shape. Expected square matrix.") + end + lu, ipiv = NumRuby::Linalg.getrf(matrix) + + return [lu, ipiv] end - def self.lu_solve(matrix, rhs_val) + def self.lu_solve(lu, ipiv, b, trans: 0) + if lu.shape[0] != b.shape[0] + raise("Incompatibel dimensions.") + end + x = NumRuby::Lapack.getrs(lu, ipiv, b, trans) + return x end # Computes the SVD decomposition of matrix.