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>
43 Eigen::Array<T,Eigen::Dynamic,1>& sds,
44 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& Sigma) {
46 size_t K = sds.rows();
48 sds = Sigma.diagonal().array();
49 if( (sds <= 0.0).any() )
return false;
52 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
53 D.diagonal() = sds.inverse();
56 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> R = D * Sigma * D;
58 R.diagonal().setOnes();
59 Eigen::LDLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> > ldlt;
61 if( !ldlt.isPositive() )
return false;
62 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> U = ldlt.matrixU();
67 Eigen::Array<T,Eigen::Dynamic,1> temp = U.row(0).tail(pull);
68 CPCs.head(pull) = temp;
70 Eigen::Array<T,Eigen::Dynamic,1> acc(K);
72 acc.tail(pull) = 1.0 - temp.square();
73 for(
size_t i = 1; i < (K - 1); i++) {
76 temp = U.row(i).tail(pull);
77 temp /=
sqrt(acc.tail(pull) / acc(i));
78 CPCs.segment(position, pull) = temp;
79 acc.tail(pull) *= 1.0 - temp.square();
81 CPCs = 0.5 * ( (1.0 + CPCs) / (1.0 - CPCs) ).
log();
108 template <
typename T>
109 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
112 Eigen::Array<T,Eigen::Dynamic,1> temp;
113 Eigen::Array<T,Eigen::Dynamic,1> acc(K-1);
116 Eigen::Array<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
123 L.col(0).tail(pull) = temp = CPCs.head(pull);
124 acc.tail(pull) = 1.0 - temp.square();
125 for(
size_t i = 1; i < (K - 1); i++) {
128 temp = CPCs.segment(position, pull);
129 L(i,i) =
sqrt(acc(i-1));
130 L.col(i).tail(pull) = temp * acc.tail(pull).sqrt();
131 acc.tail(pull) *= 1.0 - temp.square();
133 L(K-1,K-1) =
sqrt(acc(K-2));
150 template <
typename T>
151 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
154 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
186 template <
typename T>
187 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
195 double lead = K - 2.0;
200 for (size_type j = 0;
201 j < (CPCs.rows() - 1);
207 log_prob += lead / 2.0 * log_1cpc2;
236 template <
typename T>
237 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
242 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
258 template <
typename T>
259 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
261 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
263 size_t K = sds.rows();
266 return sds.matrix().asDiagonal() *
read_corr_L(CPCs, K, log_prob);
278 template <
typename T>
279 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
281 const Eigen::Array<T,Eigen::Dynamic,1>& sds,
284 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
298 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
300 const Eigen::Array<T,Eigen::Dynamic,1>& sds) {
302 size_t K = sds.rows();
303 Eigen::DiagonalMatrix<T,Eigen::Dynamic> D(K);
305 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L
322 const Eigen::Array<T,Eigen::Dynamic,1>
325 Eigen::Array<T,Eigen::Dynamic,1> nu(K * (K - 1) / 2);
327 T alpha = eta + (K - 2.0) / 2.0;
331 T alpha2 = 2.0 * alpha;
334 for (size_type j = 0; j < (K - 1); j++) {
337 size_t counter = K - 1;
338 for (size_type i = 1; i < (K - 1); i++) {
340 alpha2 = 2.0 * alpha;
341 for (size_type j = i + 1; j < K; j++) {
342 nu(counter) = alpha2;
366 template <
typename T>
385 template <
typename T>
402 template <
typename T>
421 template <
typename T>
443 template <
typename T>
466 template <
typename T>
494 template <
typename T,
typename TL>
497 if (lb == -std::numeric_limits<double>::infinity())
518 template <
typename T,
typename TL>
520 typename boost::math::tools::promote_args<T,TL>::type
522 if (lb == -std::numeric_limits<double>::infinity())
543 template <
typename T,
typename TL>
545 typename boost::math::tools::promote_args<T,TL>::type
547 if (lb == -std::numeric_limits<double>::infinity())
550 y, lb,
"Lower bounded variable");
576 template <
typename T,
typename TU>
578 typename boost::math::tools::promote_args<T,TU>::type
580 if (ub == std::numeric_limits<double>::infinity())
608 template <
typename T,
typename TU>
610 typename boost::math::tools::promote_args<T,TU>::type
612 if (ub == std::numeric_limits<double>::infinity())
640 template <
typename T,
typename TU>
642 typename boost::math::tools::promote_args<T,TU>::type
644 if (ub == std::numeric_limits<double>::infinity())
647 y, ub,
"Upper bounded variable");
681 template <
typename T,
typename TL,
typename TU>
683 typename boost::math::tools::promote_args<T,TL,TU>::type
687 if (lb == -std::numeric_limits<double>::infinity())
689 if (ub == std::numeric_limits<double>::infinity())
694 T exp_minus_x =
exp(-x);
695 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
697 if ((x < std::numeric_limits<double>::infinity())
698 && (inv_logit_x == 1))
699 inv_logit_x = 1 - 1
e-15;
702 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
704 if ((x > -std::numeric_limits<double>::infinity())
705 && (inv_logit_x== 0))
708 return lb + (ub - lb) * inv_logit_x;
752 template <
typename T,
typename TL,
typename TU>
753 typename boost::math::tools::promote_args<T,TL,TU>::type
757 s <<
"domain error in lub_constrain; lower bound = " << lb
758 <<
" must be strictly less than upper bound = " << ub;
759 throw std::domain_error(s.str());
761 if (lb == -std::numeric_limits<double>::infinity())
763 if (ub == std::numeric_limits<double>::infinity())
767 T exp_minus_x =
exp(-x);
768 inv_logit_x = 1.0 / (1.0 + exp_minus_x);
769 lp +=
log(ub - lb) - x - 2 *
log1p(exp_minus_x);
771 if ((x < std::numeric_limits<double>::infinity())
772 && (inv_logit_x == 1))
773 inv_logit_x = 1 - 1
e-15;
776 inv_logit_x = 1.0 - 1.0 / (1.0 + exp_x);
777 lp +=
log(ub - lb) + x - 2 *
log1p(exp_x);
779 if ((x > -std::numeric_limits<double>::infinity())
780 && (inv_logit_x== 0))
783 return lb + (ub - lb) * inv_logit_x;
816 template <
typename T,
typename TL,
typename TU>
818 typename boost::math::tools::promote_args<T,TL,TU>::type
822 y, lb, ub,
"Bounded variable");
823 if (lb == -std::numeric_limits<double>::infinity())
825 if (ub == std::numeric_limits<double>::infinity())
827 return logit((y - lb) / (ub - lb));
846 template <
typename T>
874 template <
typename T>
880 lp +=
log(inv_logit_x) +
log1m(inv_logit_x);
898 template <
typename T>
903 y, 0, 1,
"Probability variable");
922 template <
typename T>
940 template <
typename T>
945 lp +=
log1m(tanh_x * tanh_x);
965 template <
typename T>
969 y, -1, 1,
"Correlation variable");
989 template <
typename T>
990 Eigen::Matrix<T,Eigen::Dynamic,1>
998 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
1000 for (size_type k = 0; k < Km1; ++k) {
1002 x(k) = stick_len * z_k;
1022 template <
typename T>
1023 Eigen::Matrix<T,Eigen::Dynamic,1>
1032 Eigen::Matrix<T,Eigen::Dynamic,1> x(Km1 + 1);
1034 for (size_type k = 0; k < Km1; ++k) {
1035 double eq_share = -
log(Km1 - k);
1036 T adj_y_k(y(k) + eq_share);
1038 x(k) = stick_len * z_k;
1039 lp +=
log(stick_len);
1062 template <
typename T>
1063 Eigen::Matrix<T,Eigen::Dynamic,1>
1068 int Km1 = x.size() - 1;
1069 Eigen::Matrix<T,Eigen::Dynamic,1> y(Km1);
1070 T stick_len(x(Km1));
1071 for (size_type k = Km1; --k >= 0; ) {
1073 T z_k(x(k) / stick_len);
1092 template <
typename T>
1093 Eigen::Matrix<T,Eigen::Dynamic,1>
1096 size_type k = x.size();
1097 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1101 for (size_type i = 1;
1104 y[i] = y[i-1] +
exp(x[i]);
1120 template <
typename T>
1122 Eigen::Matrix<T,Eigen::Dynamic,1>
1125 for (size_type i = 1; i < x.size(); ++i)
1145 template <
typename T>
1146 Eigen::Matrix<T,Eigen::Dynamic,1>
1149 y,
"Ordered variable");
1151 size_type k = y.size();
1152 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1156 for (size_type i = 1; i < k; ++i)
1157 x[i] =
log(y[i] - y[i-1]);
1173 template <
typename T>
1174 Eigen::Matrix<T,Eigen::Dynamic,1>
1177 size_type k = x.size();
1178 Eigen::Matrix<T,Eigen::Dynamic,1> y(k);
1182 for (size_type i = 1;
1185 y[i] = y[i-1] +
exp(x[i]);
1201 template <
typename T>
1203 Eigen::Matrix<T,Eigen::Dynamic,1>
1206 for (size_type i = 0; i < x.size(); ++i)
1226 template <
typename T>
1227 Eigen::Matrix<T,Eigen::Dynamic,1>
1230 y,
"Positive ordered variable");
1232 size_type k = y.size();
1233 Eigen::Matrix<T,Eigen::Dynamic,1> x(k);
1237 for (size_type i = 1; i < k; ++i)
1238 x[i] =
log(y[i] - y[i-1]);
1268 template <
typename T>
1269 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1273 size_type k_choose_2 = (k * (k - 1)) / 2;
1274 if (k_choose_2 != x.size())
1275 throw std::invalid_argument (
"x is not a valid correlation matrix");
1276 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1277 for (size_type i = 0; i < k_choose_2; ++i)
1301 template <
typename T>
1302 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1307 size_type k_choose_2 = (k * (k - 1)) / 2;
1308 if (k_choose_2 != x.size())
1309 throw std::invalid_argument (
"x is not a valid correlation matrix");
1311 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1312 for (size_type i = 0; i < k_choose_2; ++i)
1337 template <
typename T>
1338 Eigen::Matrix<T,Eigen::Dynamic,1>
1342 size_type k = y.rows();
1344 throw std::domain_error(
"y is not a square matrix");
1346 throw std::domain_error(
"y has no elements");
1347 size_type k_choose_2 = (k * (k-1)) / 2;
1348 Eigen::Array<T,Eigen::Dynamic,1> x(k_choose_2);
1349 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1352 throw std::runtime_error(
"factor_cov_matrix failed on y");
1353 for (size_type i = 0; i < k; ++i) {
1356 std::stringstream s;
1357 s <<
"all standard deviations must be zero."
1358 <<
" found log(sd[" << i <<
"])=" << sds[i] << std::endl;
1359 BOOST_THROW_EXCEPTION(std::runtime_error(s.str()));
1380 template <
typename T>
1381 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1386 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1387 if (x.size() != (K * (K + 1)) / 2)
1388 throw std::domain_error(
"x.size() != K + (K choose 2)");
1390 for (size_type m = 0; m < K; ++m) {
1391 for (
int n = 0; n < m; ++n)
1393 L(m,m) =
exp(x(i++));
1394 for (size_type n = m + 1; n < K; ++n)
1397 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> M = L * L.transpose();
1398 return L * L.transpose();
1414 template <
typename T>
1415 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1421 if (x.size() != (K * (K + 1)) / 2)
1422 throw std::domain_error(
"x.size() != K + (K choose 2)");
1423 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L(K,K);
1425 for (size_type m = 0; m < K; ++m) {
1426 for (size_type n = 0; n < m; ++n)
1428 L(m,m) =
exp(x(i++));
1429 for (size_type n = m + 1; n < K; ++n)
1434 for (
int k = 0; k < K; ++k)
1435 lp += (K - k + 1) *
log(L(k,k));
1436 return L * L.transpose();
1462 template <
typename T>
1463 Eigen::Matrix<T,Eigen::Dynamic,1>
1468 throw std::domain_error(
"y is not a square matrix");
1470 throw std::domain_error(
"y has no elements");
1471 for (
int k = 0; k < K; ++k)
1472 if (!(y(k,k) > 0.0))
1473 throw std::domain_error(
"y has non-positive diagonal");
1474 Eigen::Matrix<T,Eigen::Dynamic,1> x((K * (K + 1)) / 2);
1477 Eigen::LLT<Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> >
1480 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> L = llt.matrixL();
1482 for (
int m = 0; m < K; ++m) {
1483 for (
int n = 0; n < m; ++n)
1485 x(i++) =
log(L(m,m));
1509 template <
typename T>
1510 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1513 size_t k_choose_2 = (k * (k - 1)) / 2;
1514 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1516 for (
size_t i = 0; i < k_choose_2; ++i)
1518 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1519 for (
size_t i = 0; i < k; ++i)
1548 template <
typename T>
1549 Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>
1553 size_t k_choose_2 = (k * (k - 1)) / 2;
1554 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1556 for (
size_t i = 0; i < k_choose_2; ++i)
1558 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1559 for (
size_t i = 0; i < k; ++i)
1582 template <
typename T>
1583 Eigen::Matrix<T,Eigen::Dynamic,1>
1585 const Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic>& y) {
1588 size_type k = y.rows();
1590 throw std::domain_error(
"y is not a square matrix");
1592 throw std::domain_error(
"y has no elements");
1593 size_type k_choose_2 = (k * (k-1)) / 2;
1594 Eigen::Array<T,Eigen::Dynamic,1> cpcs(k_choose_2);
1595 Eigen::Array<T,Eigen::Dynamic,1> sds(k);
1598 throw std::runtime_error (
"factor_cov_matrix failed on y");
1599 Eigen::Matrix<T,Eigen::Dynamic,1> x(k_choose_2 + k);
1601 for (size_type i = 0; i < k_choose_2; ++i)
1603 for (size_type i = 0; i < k; ++i)