Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
b5ed86e
Added generalized_inverse files
spinkney Dec 1, 2020
16698b2
finished genealized_inverse test
spinkney Dec 1, 2020
5939422
added generalized_inverse in fun.hpp
spinkney Dec 1, 2020
d3337c2
fixed docs on generalized_inverse
spinkney Dec 1, 2020
fdc6c1b
update
Dec 2, 2020
1c8a51e
Added generalized_inverse files
spinkney Dec 1, 2020
172f7e9
finished genealized_inverse test
spinkney Dec 1, 2020
32ec517
added generalized_inverse in fun.hpp
spinkney Dec 1, 2020
270dde6
fixed docs on generalized_inverse
spinkney Dec 1, 2020
037ca41
update
Dec 2, 2020
b28f7a8
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 2, 2020
21cbcc1
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
aeb78b5
Fixed function doc
spinkney Dec 2, 2020
2192b90
Update test/unit/math/prim/fun/generalized_inverse_test.cpp
spinkney Dec 2, 2020
bc58200
Changed -1 to Eigen::Dynamic
spinkney Dec 2, 2020
5ce3276
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
a862f36
Using chol2inv adds a bit more numerical stability
spinkney Dec 2, 2020
48fbbf2
resolved merge conflict
spinkney Dec 2, 2020
fedfd8a
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
0e6a898
fixed small typo
spinkney Dec 2, 2020
01e97fa
resolved merge conflict
spinkney Dec 2, 2020
e2fc0f9
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
5601b00
optimizing the algebra
spinkney Dec 2, 2020
9066a94
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
86d67ec
Added jitter alias and extra test
spinkney Dec 2, 2020
cd1e20e
Merge commit '089db8e9b3ebc2ae65ef4321ebd0652205f31b82' into HEAD
yashikno Dec 2, 2020
664c4fa
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 2, 2020
0b77326
typos
spinkney Dec 2, 2020
2792baa
test fix
spinkney Dec 2, 2020
9788f2a
fixed test matrix
spinkney Dec 2, 2020
836ba0e
clean up docs
spinkney Dec 3, 2020
6718fe2
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 3, 2020
37269e6
adding mix test
spinkney Dec 3, 2020
9253b7c
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 3, 2020
73dd639
Merge commit 'e98bfbdb70d66f3b28148d400ef197219b0a467b' into HEAD
yashikno Dec 3, 2020
192f4e2
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 3, 2020
248d33f
typo
spinkney Dec 3, 2020
cbb6ace
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 3, 2020
26d018e
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 3, 2020
a1024b6
Merge remote-tracking branch 'origin/feature/ginv' into feature/ginv
spinkney Dec 3, 2020
5a21f25
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 3, 2020
ec2be99
updated mix test
spinkney Dec 3, 2020
61a193d
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 3, 2020
99cd3e7
simplified diagonal add
spinkney Dec 4, 2020
c2120e0
using object reference
spinkney Dec 6, 2020
882e177
Merge commit '9be1788b0848360557c84cb50d2fd9d8b7eddcfe' into HEAD
yashikno Dec 6, 2020
1b62d5e
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
90b95d8
add reverse mode differentiation
spinkney Dec 6, 2020
fa74e62
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 6, 2020
53544c0
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
30fdbc2
fixed typo
spinkney Dec 6, 2020
d4f400f
add whitespace
spinkney Dec 6, 2020
cdebea9
make lines <= 80 char
spinkney Dec 6, 2020
e9f25e8
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
2467a87
one more try at <= 80 chars
spinkney Dec 6, 2020
ee7f8ce
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
351e0b0
again
spinkney Dec 6, 2020
9e6e692
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
113efb3
keep name of input the same
spinkney Dec 6, 2020
810b357
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 6, 2020
29dabbd
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
bf572d6
fixed merge conflict
spinkney Dec 6, 2020
e1ba5c2
fixed header
spinkney Dec 6, 2020
454a50f
more header fix
spinkney Dec 6, 2020
4af6787
:(
spinkney Dec 6, 2020
9f71335
cleanup
spinkney Dec 6, 2020
6378410
more cleanup
spinkney Dec 6, 2020
5866d88
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
27c31ed
fix reverse_pass_callback
spinkney Dec 6, 2020
e2145be
fix merge
spinkney Dec 6, 2020
cc21e24
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 6, 2020
e9365fa
Added tests for jittered function
spinkney Dec 7, 2020
4aa0c9a
Merge commit 'd1a1d7e8d2e43ac6aef9ac3708841a882919b8d3' into HEAD
yashikno Dec 7, 2020
6adb8ac
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 7, 2020
b1d7c4f
Update stan/math/rev/fun/generalized_inverse.hpp
spinkney Dec 13, 2020
f1efc6c
Update stan/math/prim/fun/generalized_inverse.hpp
spinkney Dec 13, 2020
d2ef3ce
fixed derivative
spinkney Dec 14, 2020
ace0138
Merge commit '7f3792baa9e91438e79a2cf6594a38d105c9b24e' into HEAD
yashikno Dec 14, 2020
2f32b8d
fixed doc and include
spinkney Dec 14, 2020
ee29e91
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
d93620e
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 14, 2020
88a8262
changed rev template from EigMat to VarMat
spinkney Dec 14, 2020
8d4e39c
incorporating Steve's rev compile fixes
spinkney Dec 14, 2020
709f1df
cleanup
spinkney Dec 14, 2020
5f8f09b
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
483d527
val to val_op for bug in Eigen's CWiseUnaryView
spinkney Dec 14, 2020
2c349df
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
873c1f3
more _op changes
spinkney Dec 14, 2020
e3f14c2
flip rows/cols inline
spinkney Dec 14, 2020
f56b9c5
small fix remove n, m using .rows()/.cols()
spinkney Dec 14, 2020
e768431
small fix
spinkney Dec 14, 2020
2b3ab6f
more fixes
spinkney Dec 14, 2020
76b5536
more fixes
spinkney Dec 14, 2020
2e3e69c
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
a118eaa
more cleanup
spinkney Dec 14, 2020
149c8f3
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 14, 2020
9a9be26
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
a37536d
fixed merge conflict
spinkney Dec 14, 2020
1ca34c0
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 14, 2020
6b136cd
comment out equal tests
spinkney Dec 14, 2020
27b688a
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
29d536e
test
spinkney Dec 14, 2020
e7af4fc
fix
spinkney Dec 14, 2020
9e0fef2
Merge branch 'feature/ginv' of https://github.com/spinkney/math into …
spinkney Dec 14, 2020
b3534f5
Update generalized_inverse_test.cpp
spinkney Dec 14, 2020
9c8f0b9
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 14, 2020
438bbf3
Finished tests!
spinkney Dec 15, 2020
95e53a1
Merge commit '7946558172cf3d3fb60e7b117ad6ac909c2519ec' into HEAD
yashikno Dec 15, 2020
ec80ff1
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 15, 2020
d1c1d2b
Update doc for reverse specialization
spinkney Dec 15, 2020
0a1b7e0
Merge remote-tracking branch 'origin/feature/ginv' into feature/ginv
spinkney Dec 15, 2020
b25eb0a
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 15, 2020
361d583
updates using ldlt
spinkney Dec 17, 2020
fd31404
Merge commit '3616f7195adc95ef8e719a2af845d61102bc9272' into HEAD
yashikno Dec 17, 2020
18fb94f
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 17, 2020
7fe4f9c
newline for test
spinkney Dec 17, 2020
866e9ea
new line for test
spinkney Dec 17, 2020
1817807
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 17, 2020
c80f212
Removed unnecessary test
spinkney Dec 18, 2020
393bcea
Merge commit '3d03131bdcbb2d33878f4117c857ac6404c7e10e' into HEAD
yashikno Dec 18, 2020
a8b1287
[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.0…
stan-buildbot Dec 18, 2020
20742a8
prim test for singular
spinkney Dec 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions stan/math/prim/fun.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
#include <stan/math/prim/fun/fmod.hpp>
#include <stan/math/prim/fun/gamma_p.hpp>
#include <stan/math/prim/fun/gamma_q.hpp>
#include <stan/math/prim/fun/generalized_inverse.hpp>
#include <stan/math/prim/fun/get.hpp>
#include <stan/math/prim/fun/get_base1.hpp>
#include <stan/math/prim/fun/get_base1_lhs.hpp>
Expand Down
54 changes: 54 additions & 0 deletions stan/math/prim/fun/generalized_inverse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP
#define STAN_MATH_PRIM_FUN_GENERALIZED_INVERSE_HPP

#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/fun/inverse.hpp>

namespace stan {
namespace math {

/**
* Returns the Moore-Penrose generalized inverse of the specified matrix.
*
* The method is based on the Cholesky computation of the transform as specified
* in
*
* <ul><li> Courrieu, Pierre. 2008. Fast Computation of Moore-Penrose Inverse
Matrices.
* <i>arXiv</i> <b>0804.4809</b> </li></ul>
*
* @tparam EigMat type of the matrix (must be derived from `Eigen::MatrixBase`)
*
* @param G specified matrix
* @return Generalized inverse of the matrix (an empty matrix if the specified
* matrix has size zero).
*/
template <typename EigMat, require_eigen_t<EigMat>* = nullptr,
require_not_vt_var<EigMat>* = nullptr>
inline Eigen::Matrix<value_type_t<EigMat>, EigMat::ColsAtCompileTime,
EigMat::RowsAtCompileTime>
generalized_inverse(const EigMat& G) {
using value_t = value_type_t<EigMat>;

if (G.size() == 0)
return {};

if (G.rows() == G.cols())
return inverse(G);

const auto& G_ref = to_ref(G);

if (G.rows() < G.cols()) {
return (G_ref * G_ref.transpose()).ldlt().solve(G_ref).transpose();
} else {
return (G_ref.transpose() * G_ref).ldlt().solve(G_ref.transpose());
}
}

} // namespace math
} // namespace stan

#endif
1 change: 1 addition & 0 deletions stan/math/rev/fun.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <stan/math/rev/fun/from_var_value.hpp>
#include <stan/math/rev/fun/gamma_p.hpp>
#include <stan/math/rev/fun/gamma_q.hpp>
#include <stan/math/rev/fun/generalized_inverse.hpp>
#include <stan/math/rev/fun/gp_periodic_cov.hpp>
#include <stan/math/rev/fun/grad.hpp>
#include <stan/math/rev/fun/grad_inc_beta.hpp>
Expand Down
93 changes: 93 additions & 0 deletions stan/math/rev/fun/generalized_inverse.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#ifndef STAN_MATH_REV_FUN_GENERALIZED_INVERSE_HPP
#define STAN_MATH_REV_FUN_GENERALIZED_INVERSE_HPP

#include <stan/math/rev/core.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/rev/fun/inverse.hpp>

namespace stan {
namespace math {

namespace internal {
/*
* Reverse mode specialization of calculating the generalized inverse of a
* matrix.
* <ul><li> Golub, G.H. and Pereyra, V. The Differentiation of Pseudo-Inverses
* and Nonlinear Least Squares Problems Whose Variables Separate. <i>SIAM
* Journal on Numerical Analysis</i>, Vol. 10, No. 2 (Apr., 1973), pp.
* 413-432</li></ul>
*/
template <typename T1, typename T2>
inline auto generalized_inverse_lambda(T1& G_arena, T2& inv_G) {
return [G_arena, inv_G]() mutable {
G_arena.adj()
+= -(inv_G.val_op().transpose() * inv_G.adj_op()
* inv_G.val_op().transpose())
+ (-G_arena.val_op() * inv_G.val_op()
+ Eigen::MatrixXd::Identity(G_arena.rows(), inv_G.cols()))
* inv_G.adj_op().transpose() * inv_G.val_op()
* inv_G.val_op().transpose()
+ inv_G.val_op().transpose() * inv_G.val_op()
* inv_G.adj_op().transpose()
* (-inv_G.val_op() * G_arena.val_op()
+ Eigen::MatrixXd::Identity(inv_G.rows(), G_arena.cols()));
};
}
} // namespace internal

/*
* Reverse mode specialization of calculating the generalized inverse of a
* matrix.
*
* @param G specified matrix
* @return Generalized inverse of the matrix (an empty matrix if the specified
* matrix has size zero).
*
* @note For the derivatives of this function to exist the matrix must be
* of constant rank.
* Reverse mode differentiation algorithm reference:
*
* <ul><li> Golub, G.H. and Pereyra, V. The Differentiation of Pseudo-Inverses
* and Nonlinear Least Squares Problems Whose Variables Separate. <i>SIAM
* Journal on Numerical Analysis</i>, Vol. 10, No. 2 (Apr., 1973), pp.
* 413-432</li></ul>
*
* Equation 4.12 in the paper
*
* See also
* http://mathoverflow.net/questions/25778/analytical-formula-for-numerical-derivative-of-the-matrix-pseudo-inverse
*
*/
template <typename VarMat, require_rev_matrix_t<VarMat>* = nullptr>
inline auto generalized_inverse(const VarMat& G) {
using value_t = value_type_t<VarMat>;
using ret_type = promote_var_matrix_t<VarMat, VarMat>;

if (G.size() == 0)
return ret_type(G);

if (G.rows() == G.cols())
return ret_type(inverse(G));

if (G.rows() < G.cols()) {
arena_t<VarMat> G_arena(G);
arena_t<ret_type> inv_G((G_arena.val_op() * G_arena.val_op().transpose())
.ldlt()
.solve(G_arena.val_op())
.transpose());
reverse_pass_callback(internal::generalized_inverse_lambda(G_arena, inv_G));
return ret_type(inv_G);
} else {
arena_t<VarMat> G_arena(G);
arena_t<ret_type> inv_G((G_arena.val_op().transpose() * G_arena.val_op())
.ldlt()
.solve(G_arena.val_op().transpose()));
reverse_pass_callback(internal::generalized_inverse_lambda(G_arena, inv_G));
return ret_type(inv_G);
}
}

} // namespace math
} // namespace stan
#endif
54 changes: 54 additions & 0 deletions test/unit/math/mix/fun/generalized_inverse_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <test/unit/math/test_ad.hpp>
#include <vector>
#include <gtest/gtest.h>

TEST(mathMixMatFun, ad_tests) {
using stan::test::expect_ad;
using stan::test::expect_ad_matvar;

auto f = [](const auto& G) { return stan::math::generalized_inverse(G); };

Eigen::MatrixXd t(0, 0);
expect_ad(f, t);
expect_ad_matvar(f, t);

Eigen::MatrixXd u(1, 1);
u << 2;
expect_ad(f, u);
expect_ad_matvar(f, u);

Eigen::MatrixXd v(2, 3);
v << 1, 3, 5, 2, 4, 6;
expect_ad(f, v);
expect_ad_matvar(f, v);

v << 1.9, 1.3, 2.5, 0.4, 1.7, 0.1;
expect_ad(f, v);
expect_ad_matvar(f, v);

Eigen::MatrixXd s(2, 4);
s << 3.4, 2, 5, 1.2, 2, 1, 3.2, 3.1;
expect_ad(f, s);
expect_ad_matvar(f, s);

// issues around zero require looser tolerances for hessians
stan::test::ad_tolerances tols;
tols.hessian_hessian_ = 2.0;
tols.hessian_fvar_hessian_ = 2.0;

Eigen::MatrixXd w(3, 4);
w << 2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 27, 29;
expect_ad(tols, f, w);
expect_ad_matvar(f, w);

Eigen::MatrixXd z(2, 2);
z << 1, 2, 5, std::numeric_limits<double>::quiet_NaN();
EXPECT_NO_THROW(stan::math::generalized_inverse(z));

// autodiff throws, so following fails (throw behavior must match to pass)

Eigen::MatrixXd a(2, 2);
a << 1.9, 0.3, 0.3, std::numeric_limits<double>::infinity();
expect_ad(f, a);
expect_ad_matvar(f, a);
}
47 changes: 47 additions & 0 deletions test/unit/math/prim/fun/generalized_inverse_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <stan/math/prim.hpp>
#include <test/unit/util.hpp>
#include <gtest/gtest.h>

TEST(MathMatrixPrim, Zero) {
stan::math::matrix_d m0(0, 0);
stan::math::matrix_d ginv = stan::math::generalized_inverse(m0);
EXPECT_EQ(0, ginv.rows());
EXPECT_EQ(0, ginv.cols());
}

TEST(MathMatrixPrim, Singular) {
using stan::math::generalized_inverse;

stan::math::matrix_d m1(2, 3);
m1 << 1, 2, 1, 2, 4, 2;

stan::math::matrix_d m2 = m1 * generalized_inverse(m1) * m1;
EXPECT_MATRIX_NEAR(m1, m2, 1e-9);
}

TEST(MathMatrixPrim, Equal1) {
using stan::math::generalized_inverse;

stan::math::matrix_d m1(2, 3);
m1 << 1, 3, 5, 2, 4, 6;

stan::math::matrix_d m2(2, 2);
m2 << 1, 0, 0, 1;

stan::math::matrix_d m3 = m1 * generalized_inverse(m1);
EXPECT_MATRIX_NEAR(m2, m3, 1e-9);
}

TEST(MathMatrixPrim, Equal2) {
using stan::math::generalized_inverse;

stan::math::matrix_d m1(3, 2);
m1 << 1, 2, 2, 4, 1, 2;

stan::math::matrix_d m2(3, 3);
m2 << 1.0 / 6.0, 1.0 / 3.0, 1.0 / 6.0, 1.0 / 3.0, 2.0 / 3.0, 1.0 / 3.0,
1.0 / 6.0, 1.0 / 3.0, 1.0 / 6.0;

stan::math::matrix_d m3 = m1 * generalized_inverse(m1);
EXPECT_MATRIX_NEAR(m2, m3, 1e-9);
}