1 #ifndef __STAN__PROB__TRANSFORM_HPP__
2 #define __STAN__PROB__TRANSFORM_HPP__
9 #include <boost/multi_array.hpp>
10 #include <boost/throw_exception.hpp>
11 #include <boost/math/tools/promotion.hpp>
42 Eigen::Array<T,Eigen::Dynamic,1>& sds,
43 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& Sigma) {
45 size_t K = sds.rows();
47 sds = Sigma.diagonal().array();
48 if( (sds <= 0.0).any() )
return false;
51 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
52 D.diagonal() = sds.inverse();
55 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> R = D * Sigma * D;
57 R.diagonal().setOnes();
58 Eigen::LDLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> > ldlt;
60 if( !ldlt.isPositive() )
return false;
61 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> U = ldlt.matrixU();
66 Eigen::Array<T,Eigen::Dynamic,1> temp = U.row(0).tail(pull);
67 CPCs.head(pull) = temp;
69 Eigen::Array<T,Eigen::Dynamic,1> acc(K);
71 acc.tail(pull) = 1.0 - temp.square();
72 for(
size_t i = 1; i < (K - 1); i++) {
75 temp = U.row(i).tail(pull);
76 temp /=
sqrt(acc.tail(pull) / acc(i));
77 CPCs.segment(position, pull) = temp;
78 acc.tail(pull) *= 1.0 - temp.square();
80 CPCs = 0.5 * ( (1.0 + CPCs) / (1.0 - CPCs) ).
log();
107 template <
typename T>
108 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
111 Eigen::Array<T,Eigen::Dynamic,1> temp;
112 Eigen::Array<T,Eigen::Dynamic,1> acc(K-1);
115 Eigen::Array<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
122 L.col(0).tail(pull) = temp = CPCs.head(pull);
123 acc.tail(pull) = 1.0 - temp.square();
124 for(
size_t i = 1; i < (K - 1); i++) {
127 temp = CPCs.segment(position, pull);
128 L(i,i) =
sqrt(acc(i-1));
129 L.col(i).tail(pull) = temp * acc.tail(pull).sqrt();
130 acc.tail(pull) *= 1.0 - temp.square();
132 L(K-1,K-1) =
sqrt(acc(K-2));
149 template <
typename T>
150 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
153 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
155 return L.template triangularView<Eigen::Lower>()
156 * L.matrix().transpose();
185 template <
typename T>
186 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
194 double lead = K - 2.0;
199 for (size_type j = 0;
200 j < (CPCs.rows() - 1);
206 log_prob += lead / 2.0 * log_1cpc2;
235 template <
typename T>
236 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
241 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
243 return L.template triangularView<Eigen::Lower>()
244 * L.matrix().transpose();
257 template <
typename T>
258 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
260 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
262 size_t K = sds.rows();
265 return sds.matrix().asDiagonal() *
read_corr_L(CPCs, K, log_prob);
277 template <
typename T>
278 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
280 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
283 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
285 return L.template triangularView<Eigen::Lower>()
286 * L.matrix().transpose();
297 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
299 const Eigen::Array<T,Eigen::Dynamic,1>& sds) {
301 size_t K = sds.rows();
302 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
304 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
306 return L.template triangularView<Eigen::Lower>()
307 * L.matrix().transpose();
321 const Eigen::Array<T,Eigen::Dynamic,1>
324 Eigen::Array<T,Eigen::Dynamic,1> nu(K * (K - 1) / 2);
326 T alpha = eta + (K - 2.0) / 2.0;
330 T alpha2 = 2.0 * alpha;
333 for (size_type j = 0; j < (K - 1); j++) {
336 size_t counter = K - 1;
337 for (size_type i = 1; i < (K - 1); i++) {
339 alpha2 = 2.0 * alpha;
340 for (size_type j = i + 1; j < K; j++) {
341 nu(counter) = alpha2;
365 template <
typename T>
384 template <
typename T>
401 template <
typename T>
420 template <
typename T>
442 template <
typename T>
465 template <
typename T>
490 template <
typename T,
typename TL>
509 template <
typename T,
typename TL>
511 typename boost::math::tools::promote_args<T,TL>::type
529 template <
typename T,
typename TL>
531 typename boost::math::tools::promote_args<T,TL>::type
534 y, lb,
"Lower bounded variable");
557 template <
typename T,
typename TU>
559 typename boost::math::tools::promote_args<T,TU>::type
584 template <
typename T,
typename TU>
586 typename boost::math::tools::promote_args<T,TU>::type
611 template <
typename T,
typename TU>
613 typename boost::math::tools::promote_args<T,TU>::type
616 y, ub,
"Upper bounded variable");
642 template <
typename T,
typename TL,
typename TU>
644 typename boost::math::tools::promote_args<T,TL,TU>::type
648 s <<
"domain error in lub_constrain; lower bound = " << lb
649 <<
" must be strictly less than upper bound = " << ub;
650 throw std::domain_error(s.str());
654 T exp_minus_x =
exp(-x);
655 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
657 if ((x < std::numeric_limits<double>::infinity())
658 && (inv_logit_x == 1))
659 inv_logit_x = 1 - 1
e-15;
662 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
664 if ((x > -std::numeric_limits<double>::infinity())
665 && (inv_logit_x== 0))
668 return lb + (ub - lb) * inv_logit_x;
704 template <
typename T,
typename TL,
typename TU>
705 typename boost::math::tools::promote_args<T,TL,TU>::type
709 s <<
"domain error in lub_constrain; lower bound = " << lb
710 <<
" must be strictly less than upper bound = " << ub;
711 throw std::domain_error(s.str());
715 T exp_minus_x =
exp(-x);
716 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
717 lp +=
log(ub - lb) - x - 2 *
log1p(exp_minus_x);
719 if ((x < std::numeric_limits<double>::infinity())
720 && (inv_logit_x == 1))
721 inv_logit_x = 1 - 1
e-15;
724 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
725 lp +=
log(ub - lb) + x - 2 *
log1p(exp_x);
727 if ((x > -std::numeric_limits<double>::infinity())
728 && (inv_logit_x== 0))
731 return lb + (ub - lb) * inv_logit_x;
756 template <
typename T,
typename TL,
typename TU>
758 typename boost::math::tools::promote_args<T,TL,TU>::type
762 y, lb, ub,
"Bounded variable");
763 return logit((y - lb) / (ub - lb));
782 template <
typename T>
810 template <
typename T>
816 lp +=
log(inv_logit_x) +
log1m(inv_logit_x);
834 template <
typename T>
839 y, 0, 1,
"Probability variable");
858 template <
typename T>
876 template <
typename T>
881 lp +=
log1m(tanh_x * tanh_x);
901 template <
typename T>
905 y, -1, 1,
"Correlation variable");
925 template <
typename T>
926 Eigen::Matrix<T,Eigen::Dynamic,1>
934 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
936 for (size_type k = 0; k < Km1; ++k) {
938 x(k) = stick_len * z_k;
958 template <
typename T>
959 Eigen::Matrix<T,Eigen::Dynamic,1>
968 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
970 for (size_type k = 0; k < Km1; ++k) {
971 double eq_share = -
log(Km1 - k);
972 T adj_y_k(y(k) + eq_share);
974 x(k) = stick_len * z_k;
975 lp +=
log(stick_len);
998 template <
typename T>
999 Eigen::Matrix<T,Eigen::Dynamic,1>
1004 int Km1 = x.size() - 1;
1005 Eigen::Matrix<T,Eigen::Dynamic,1> y(Km1);
1006 T stick_len(x(Km1));
1007 for (size_type k = Km1; --k >= 0; ) {
1009 T z_k(x(k) / stick_len);
1028 template <
typename T>
1029 Eigen::Matrix<T,Eigen::Dynamic,1>
1032 size_type k = x.size();
1033 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1037 for (size_type i = 1;
1040 y[i] = y[i-1] +
exp(x[i]);
1056 template <
typename T>
1058 Eigen::Matrix<T,Eigen::Dynamic,1>
1061 for (size_type i = 1; i < x.size(); ++i)
1081 template <
typename T>
1082 Eigen::Matrix<T,Eigen::Dynamic,1>
1085 y,
"Ordered variable");
1087 size_type k = y.size();
1088 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1092 for (size_type i = 1; i < k; ++i)
1093 x[i] =
log(y[i] - y[i-1]);
1109 template <
typename T>
1110 Eigen::Matrix<T,Eigen::Dynamic,1>
1113 size_type k = x.size();
1114 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1118 for (size_type i = 1;
1121 y[i] = y[i-1] +
exp(x[i]);
1137 template <
typename T>
1139 Eigen::Matrix<T,Eigen::Dynamic,1>
1142 for (size_type i = 0; i < x.size(); ++i)
1162 template <
typename T>
1163 Eigen::Matrix<T,Eigen::Dynamic,1>
1166 y,
"Positive ordered variable");
1168 size_type k = y.size();
1169 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1173 for (size_type i = 1; i < k; ++i)
1174 x[i] =
log(y[i] - y[i-1]);
1204 template <
typename T>
1205 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1209 size_type k_choose_2 = (k * (k - 1)) / 2;
1210 if (k_choose_2 != x.size())
1211 throw std::invalid_argument (
"x is not a valid correlation matrix");
1212 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1213 for (size_type i = 0; i < k_choose_2; ++i)
1237 template <
typename T>
1238 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1243 size_type k_choose_2 = (k * (k - 1)) / 2;
1244 if (k_choose_2 != x.size())
1245 throw std::invalid_argument (
"x is not a valid correlation matrix");
1247 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1248 for (size_type i = 0; i < k_choose_2; ++i)
1273 template <
typename T>
1274 Eigen::Matrix<T,Eigen::Dynamic,1>
1278 size_type k = y.rows();
1280 throw std::domain_error(
"y is not a square matrix");
1282 throw std::domain_error(
"y has no elements");
1283 size_type k_choose_2 = (k * (k-1)) / 2;
1284 Eigen::Array<T,Eigen::Dynamic,1> x(k_choose_2);
1285 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1288 throw std::runtime_error(
"factor_cov_matrix failed on y");
1289 for (size_type i = 0; i < k; ++i) {
1292 std::stringstream s;
1293 s <<
"all standard deviations must be zero."
1294 <<
" found log(sd[" << i <<
"])=" << sds[i] << std::endl;
1295 BOOST_THROW_EXCEPTION(std::runtime_error(s.str()));
1316 template <
typename T>
1317 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1322 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1323 if (x.size() != (K * (K + 1)) / 2)
1324 throw std::domain_error(
"x.size() != K + (K choose 2)");
1326 for (size_type m = 0; m < K; ++m) {
1327 for (
int n = 0; n < m; ++n)
1329 L(m,m) =
exp(x(i++));
1330 for (size_type n = m + 1; n < K; ++n)
1333 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> M = L * L.transpose();
1334 return L * L.transpose();
1350 template <
typename T>
1351 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1357 if (x.size() != (K * (K + 1)) / 2)
1358 throw std::domain_error(
"x.size() != K + (K choose 2)");
1359 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1361 for (size_type m = 0; m < K; ++m) {
1362 for (size_type n = 0; n < m; ++n)
1364 L(m,m) =
exp(x(i++));
1365 for (size_type n = m + 1; n < K; ++n)
1370 for (
int k = 0; k < K; ++k)
1371 lp += (K - k + 1) *
log(L(k,k));
1372 return L * L.transpose();
1398 template <
typename T>
1399 Eigen::Matrix<T,Eigen::Dynamic,1>
1404 throw std::domain_error(
"y is not a square matrix");
1406 throw std::domain_error(
"y has no elements");
1407 for (
int k = 0; k < K; ++k)
1408 if (!(y(k,k) > 0.0))
1409 throw std::domain_error(
"y has non-positive diagonal");
1410 Eigen::Matrix<T,Eigen::Dynamic,1> x((K * (K + 1)) / 2);
1413 Eigen::LLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> >
1416 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L = llt.matrixL();
1418 for (
int m = 0; m < K; ++m) {
1419 for (
int n = 0; n < m; ++n)
1421 x(i++) =
log(L(m,m));
1445 template <
typename T>
1446 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1449 size_t k_choose_2 = (k * (k - 1)) / 2;
1450 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1452 for (
size_t i = 0; i < k_choose_2; ++i)
1454 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1455 for (
size_t i = 0; i < k; ++i)
1484 template <
typename T>
1485 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1489 size_t k_choose_2 = (k * (k - 1)) / 2;
1490 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1492 for (
size_t i = 0; i < k_choose_2; ++i)
1494 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1495 for (
size_t i = 0; i < k; ++i)
1518 template <
typename T>
1519 Eigen::Matrix<T,Eigen::Dynamic,1>
1521 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& y) {
1524 size_type k = y.rows();
1526 throw std::domain_error(
"y is not a square matrix");
1528 throw std::domain_error(
"y has no elements");
1529 size_type k_choose_2 = (k * (k-1)) / 2;
1530 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1531 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1534 throw std::runtime_error (
"factor_cov_matrix failed on y");
1535 Eigen::Matrix<T,Eigen::Dynamic,1> x(k_choose_2 + k);
1537 for (size_type i = 0; i < k_choose_2; ++i)
1539 for (size_type i = 0; i < k; ++i)