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>
44 Eigen::Array<T,Eigen::Dynamic,1>& sds,
45 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& Sigma) {
47 size_t K = sds.rows();
49 sds = Sigma.diagonal().array();
50 if( (sds <= 0.0).any() )
return false;
53 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
54 D.diagonal() = sds.inverse();
57 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> R = D * Sigma * D;
59 R.diagonal().setOnes();
60 Eigen::LDLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> > ldlt;
62 if (!ldlt.isPositive())
64 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> U = ldlt.matrixU();
69 Eigen::Array<T,1,Eigen::Dynamic> temp = U.row(0).tail(pull);
71 CPCs.head(pull) = temp;
73 Eigen::Array<T,Eigen::Dynamic,1> acc(K);
75 acc.tail(pull) = 1.0 - temp.square();
76 for(
size_t i = 1; i < (K - 1); i++) {
79 temp = U.row(i).tail(pull);
80 temp /=
sqrt(acc.tail(pull) / acc(i));
81 CPCs.segment(position, pull) = temp;
82 acc.tail(pull) *= 1.0 - temp.square();
84 CPCs = 0.5 * ( (1.0 + CPCs) / (1.0 - CPCs) ).
log();
111 template <
typename T>
112 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
115 Eigen::Array<T,Eigen::Dynamic,1> temp;
116 Eigen::Array<T,Eigen::Dynamic,1> acc(K-1);
119 Eigen::Array<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
126 L.col(0).tail(pull) = temp = CPCs.head(pull);
127 acc.tail(pull) = 1.0 - temp.square();
128 for(
size_t i = 1; i < (K - 1); i++) {
131 temp = CPCs.segment(position, pull);
132 L(i,i) =
sqrt(acc(i-1));
133 L.col(i).tail(pull) = temp * acc.tail(pull).sqrt();
134 acc.tail(pull) *= 1.0 - temp.square();
136 L(K-1,K-1) =
sqrt(acc(K-2));
153 template <
typename T>
154 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
157 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
189 template <
typename T>
190 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
198 double lead = K - 2.0;
203 for (size_type j = 0;
204 j < (CPCs.rows() - 1);
210 log_prob += lead / 2.0 * log_1cpc2;
239 template <
typename T>
240 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
245 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
261 template <
typename T>
262 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
264 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
266 size_t K = sds.rows();
269 return sds.matrix().asDiagonal() *
read_corr_L(CPCs, K, log_prob);
281 template <
typename T>
282 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
284 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
287 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
301 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
303 const Eigen::Array<T,Eigen::Dynamic,1>& sds) {
305 size_t K = sds.rows();
306 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
308 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
325 const Eigen::Array<T,Eigen::Dynamic,1>
328 Eigen::Array<T,Eigen::Dynamic,1> nu(K * (K - 1) / 2);
330 T alpha = eta + (K - 2.0) / 2.0;
334 T alpha2 = 2.0 * alpha;
337 for (size_type j = 0; j < (K - 1); j++) {
340 size_t counter = K - 1;
341 for (size_type i = 1; i < (K - 1); i++) {
343 alpha2 = 2.0 * alpha;
344 for (size_type j = i + 1; j < K; j++) {
345 nu(counter) = alpha2;
369 template <
typename T>
388 template <
typename T>
405 template <
typename T>
424 template <
typename T>
446 template <
typename T>
469 template <
typename T>
497 template <
typename T,
typename TL>
500 if (lb == -std::numeric_limits<double>::infinity())
521 template <
typename T,
typename TL>
523 typename boost::math::tools::promote_args<T,TL>::type
525 if (lb == -std::numeric_limits<double>::infinity())
546 template <
typename T,
typename TL>
548 typename boost::math::tools::promote_args<T,TL>::type
550 if (lb == -std::numeric_limits<double>::infinity())
553 y, lb,
"Lower bounded variable");
579 template <
typename T,
typename TU>
581 typename boost::math::tools::promote_args<T,TU>::type
583 if (ub == std::numeric_limits<double>::infinity())
611 template <
typename T,
typename TU>
613 typename boost::math::tools::promote_args<T,TU>::type
615 if (ub == std::numeric_limits<double>::infinity())
643 template <
typename T,
typename TU>
645 typename boost::math::tools::promote_args<T,TU>::type
647 if (ub == std::numeric_limits<double>::infinity())
650 y, ub,
"Upper bounded variable");
684 template <
typename T,
typename TL,
typename TU>
686 typename boost::math::tools::promote_args<T,TL,TU>::type
690 if (lb == -std::numeric_limits<double>::infinity())
692 if (ub == std::numeric_limits<double>::infinity())
697 T exp_minus_x =
exp(-x);
698 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
700 if ((x < std::numeric_limits<double>::infinity())
701 && (inv_logit_x == 1))
702 inv_logit_x = 1 - 1
e-15;
705 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
707 if ((x > -std::numeric_limits<double>::infinity())
708 && (inv_logit_x== 0))
711 return lb + (ub - lb) * inv_logit_x;
755 template <
typename T,
typename TL,
typename TU>
756 typename boost::math::tools::promote_args<T,TL,TU>::type
760 s <<
"domain error in lub_constrain; lower bound = " << lb
761 <<
" must be strictly less than upper bound = " << ub;
762 throw std::domain_error(s.str());
764 if (lb == -std::numeric_limits<double>::infinity())
766 if (ub == std::numeric_limits<double>::infinity())
770 T exp_minus_x =
exp(-x);
771 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
772 lp +=
log(ub - lb) - x - 2 *
log1p(exp_minus_x);
774 if ((x < std::numeric_limits<double>::infinity())
775 && (inv_logit_x == 1))
776 inv_logit_x = 1 - 1
e-15;
779 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
780 lp +=
log(ub - lb) + x - 2 *
log1p(exp_x);
782 if ((x > -std::numeric_limits<double>::infinity())
783 && (inv_logit_x== 0))
786 return lb + (ub - lb) * inv_logit_x;
819 template <
typename T,
typename TL,
typename TU>
821 typename boost::math::tools::promote_args<T,TL,TU>::type
825 y, lb, ub,
"Bounded variable");
826 if (lb == -std::numeric_limits<double>::infinity())
828 if (ub == std::numeric_limits<double>::infinity())
830 return logit((y - lb) / (ub - lb));
849 template <
typename T>
877 template <
typename T>
883 lp +=
log(inv_logit_x) +
log1m(inv_logit_x);
901 template <
typename T>
906 y, 0, 1,
"Probability variable");
925 template <
typename T>
943 template <
typename T>
948 lp +=
log1m(tanh_x * tanh_x);
968 template <
typename T>
972 y, -1, 1,
"Correlation variable");
987 template <
typename T>
988 Eigen::Matrix<T,Eigen::Dynamic,1>
992 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
994 const T half_pi = T(M_PI/2.0);
995 for (size_type k = 1; k <= Km1; ++k) {
996 T yk_1 = y(k-1) + half_pi;
997 T sin_yk_1 =
sin(yk_1);
998 x(k) = x(k-1)*sin_yk_1;
1013 template <
typename T>
1014 Eigen::Matrix<T,Eigen::Dynamic,1>
1018 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
1020 const T half_pi = T(M_PI/2.0);
1021 for (size_type k = 1; k <= Km1; ++k) {
1022 T yk_1 = y(k-1) + half_pi;
1023 T sin_yk_1 =
sin(yk_1);
1024 x(k) = x(k-1)*sin_yk_1;
1025 x(k-1) *=
cos(yk_1);
1027 lp += (Km1 - k)*
log(
fabs(sin_yk_1));
1032 template <
typename T>
1033 Eigen::Matrix<T,Eigen::Dynamic,1>
1037 int Km1 = x.size() - 1;
1038 Eigen::Matrix<T,Eigen::Dynamic,1> y(Km1);
1039 T sumSq = x(Km1)*x(Km1);
1040 const T half_pi = T(M_PI/2.0);
1041 for (size_type k = Km1; --k >= 0; ) {
1042 y(k) =
atan2(
sqrt(sumSq),x(k)) - half_pi;
1063 template <
typename T>
1064 Eigen::Matrix<T,Eigen::Dynamic,1>
1072 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
1074 for (size_type k = 0; k < Km1; ++k) {
1076 x(k) = stick_len * z_k;
1096 template <
typename T>
1097 Eigen::Matrix<T,Eigen::Dynamic,1>
1106 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
1108 for (size_type k = 0; k < Km1; ++k) {
1109 double eq_share = -
log(Km1 - k);
1110 T adj_y_k(y(k) + eq_share);
1112 x(k) = stick_len * z_k;
1113 lp +=
log(stick_len);
1136 template <
typename T>
1137 Eigen::Matrix<T,Eigen::Dynamic,1>
1142 int Km1 = x.size() - 1;
1143 Eigen::Matrix<T,Eigen::Dynamic,1> y(Km1);
1144 T stick_len(x(Km1));
1145 for (size_type k = Km1; --k >= 0; ) {
1147 T z_k(x(k) / stick_len);
1166 template <
typename T>
1167 Eigen::Matrix<T,Eigen::Dynamic,1>
1170 size_type k = x.size();
1171 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1175 for (size_type i = 1;
1178 y[i] = y[i-1] +
exp(x[i]);
1194 template <
typename T>
1196 Eigen::Matrix<T,Eigen::Dynamic,1>
1199 for (size_type i = 1; i < x.size(); ++i)
1219 template <
typename T>
1220 Eigen::Matrix<T,Eigen::Dynamic,1>
1223 y,
"Ordered variable");
1225 size_type k = y.size();
1226 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1230 for (size_type i = 1; i < k; ++i)
1231 x[i] =
log(y[i] - y[i-1]);
1247 template <
typename T>
1248 Eigen::Matrix<T,Eigen::Dynamic,1>
1251 size_type k = x.size();
1252 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1256 for (size_type i = 1;
1259 y[i] = y[i-1] +
exp(x[i]);
1275 template <
typename T>
1277 Eigen::Matrix<T,Eigen::Dynamic,1>
1280 for (size_type i = 0; i < x.size(); ++i)
1300 template <
typename T>
1301 Eigen::Matrix<T,Eigen::Dynamic,1>
1304 y,
"Positive ordered variable");
1306 size_type k = y.size();
1307 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1311 for (size_type i = 1; i < k; ++i)
1312 x[i] =
log(y[i] - y[i-1]);
1342 template <
typename T>
1343 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1347 size_type k_choose_2 = (k * (k - 1)) / 2;
1348 if (k_choose_2 != x.size())
1349 throw std::invalid_argument (
"x is not a valid correlation matrix");
1350 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1351 for (size_type i = 0; i < k_choose_2; ++i)
1375 template <
typename T>
1376 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1381 size_type k_choose_2 = (k * (k - 1)) / 2;
1382 if (k_choose_2 != x.size())
1383 throw std::invalid_argument (
"x is not a valid correlation matrix");
1384 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1385 for (size_type i = 0; i < k_choose_2; ++i)
1410 template <
typename T>
1411 Eigen::Matrix<T,Eigen::Dynamic,1>
1415 size_type k = y.rows();
1417 throw std::domain_error(
"y is not a square matrix");
1419 throw std::domain_error(
"y has no elements");
1420 size_type k_choose_2 = (k * (k-1)) / 2;
1421 Eigen::Array<T,Eigen::Dynamic,1> x(k_choose_2);
1422 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1425 throw std::runtime_error(
"factor_cov_matrix failed on y");
1426 for (size_type i = 0; i < k; ++i) {
1429 std::stringstream s;
1430 s <<
"all standard deviations must be zero."
1431 <<
" found log(sd[" << i <<
"])=" << sds[i] << std::endl;
1432 BOOST_THROW_EXCEPTION(std::runtime_error(s.str()));
1453 template <
typename T>
1454 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1459 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1460 if (x.size() != (K * (K + 1)) / 2)
1461 throw std::domain_error(
"x.size() != K + (K choose 2)");
1463 for (size_type m = 0; m < K; ++m) {
1464 for (
int n = 0; n < m; ++n)
1466 L(m,m) =
exp(x(i++));
1467 for (size_type n = m + 1; n < K; ++n)
1470 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> M = L * L.transpose();
1471 return L * L.transpose();
1487 template <
typename T>
1488 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1494 if (x.size() != (K * (K + 1)) / 2)
1495 throw std::domain_error(
"x.size() != K + (K choose 2)");
1496 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1498 for (size_type m = 0; m < K; ++m) {
1499 for (size_type n = 0; n < m; ++n)
1501 L(m,m) =
exp(x(i++));
1502 for (size_type n = m + 1; n < K; ++n)
1507 for (
int k = 0; k < K; ++k)
1508 lp += (K - k + 1) *
log(L(k,k));
1509 return L * L.transpose();
1535 template <
typename T>
1536 Eigen::Matrix<T,Eigen::Dynamic,1>
1541 throw std::domain_error(
"y is not a square matrix");
1543 throw std::domain_error(
"y has no elements");
1544 for (
int k = 0; k < K; ++k)
1545 if (!(y(k,k) > 0.0))
1546 throw std::domain_error(
"y has non-positive diagonal");
1547 Eigen::Matrix<T,Eigen::Dynamic,1> x((K * (K + 1)) / 2);
1550 Eigen::LLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> >
1553 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L = llt.matrixL();
1555 for (
int m = 0; m < K; ++m) {
1556 for (
int n = 0; n < m; ++n)
1558 x(i++) =
log(L(m,m));
1582 template <
typename T>
1583 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1586 size_t k_choose_2 = (k * (k - 1)) / 2;
1587 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1589 for (
size_t i = 0; i < k_choose_2; ++i)
1591 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1592 for (
size_t i = 0; i < k; ++i)
1621 template <
typename T>
1622 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1626 size_t k_choose_2 = (k * (k - 1)) / 2;
1627 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1629 for (
size_t i = 0; i < k_choose_2; ++i)
1631 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1632 for (
size_t i = 0; i < k; ++i)
1655 template <
typename T>
1656 Eigen::Matrix<T,Eigen::Dynamic,1>
1658 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& y) {
1661 size_type k = y.rows();
1663 throw std::domain_error(
"y is not a square matrix");
1665 throw std::domain_error(
"y has no elements");
1666 size_type k_choose_2 = (k * (k-1)) / 2;
1667 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1668 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1671 throw std::runtime_error (
"factor_cov_matrix failed on y");
1672 Eigen::Matrix<T,Eigen::Dynamic,1> x(k_choose_2 + k);
1674 for (size_type i = 0; i < k_choose_2; ++i)
1676 for (size_type i = 0; i < k; ++i)