inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> wishart_rng(const double nu, const Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>& S, RNG& rng) { static const char* function = "stan::prob::wishart_rng(%1%)"; using stan::math::check_size_match; using stan::math::check_positive; check_positive(function,nu,"degrees of freedom",(double*)0); check_size_match(function, S.rows(), "Rows of scale parameter", S.cols(), "columns of scale parameter", (double*)0); Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> B(S.rows(), S.cols()); B.setZero(); for(int i = 0; i < S.cols(); i++) { B(i,i) = std::sqrt(chi_square_rng(nu - i, rng)); for(int j = 0; j < i; j++) B(j,i) = normal_rng(0,1,rng); } return stan::math::multiply_lower_tri_self_transpose(S.llt().matrixL() * B); }
inline Eigen::Matrix<typename return_type<T1, T2>::type, Eigen::Dynamic, Eigen::Dynamic> append_col(const Eigen::Matrix<T1, R1, C1>& A, const Eigen::Matrix<T2, R2, C2>& B) { using Eigen::Dynamic; using Eigen::Matrix; using stan::math::check_size_match; int Arows = A.rows(); int Brows = B.rows(); int Acols = A.cols(); int Bcols = B.cols(); check_size_match("append_col", "rows of A", Arows, "rows of B", Brows); Matrix<typename return_type<T1, T2>::type, Dynamic, Dynamic> result(Arows, Acols+Bcols); for (int j = 0; j < Acols; j++) for (int i = 0; i < Arows; i++) result(i, j) = A(i, j); for (int j = Acols, k = 0; k < Bcols; j++, k++) for (int i = 0; i < Arows; i++) result(i, j) = B(i, k); return result; }
inline Eigen::Matrix<fvar<T>,R1,C2> mdivide_right(const Eigen::Matrix<fvar<T>,R1,C1> &A, const Eigen::Matrix<double,R2,C2> &b) { using stan::math::multiply; using stan::math::mdivide_right; stan::math::check_square("mdivide_right(%1%)",b,"b",(double*)0); stan::math::check_multiplicable("mdivide_right(%1%)",A,"A", b,"b",(double*)0); Eigen::Matrix<T,R2,C2> deriv_b_mult_inv_b(b.rows(),b.cols()); Eigen::Matrix<T,R1,C1> val_A(A.rows(),A.cols()); Eigen::Matrix<T,R1,C1> deriv_A(A.rows(),A.cols()); for (int j = 0; j < A.cols(); j++) { for(int i = 0; i < A.rows(); i++) { val_A(i,j) = A(i,j).val_; deriv_A(i,j) = A(i,j).d_; } } return stan::agrad::to_fvar(mdivide_right(val_A, b), mdivide_right(deriv_A, b)); }
inline bool check_corr_matrix(const char* function, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y, const char* name, T_result* result, const Policy&) { if (!check_size_match(function, y.rows(), "Rows of correlation matrix", y.cols(), "columns of correlation matrix", result, Policy())) return false; if (!check_positive(function, y.rows(), "rows", result, Policy())) return false; if (!check_symmetric(function, y, "y", result, Policy())) return false; for (typename Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>::size_type k = 0; k < y.rows(); ++k) { if (fabs(y(k,k) - 1.0) > CONSTRAINT_TOLERANCE) { std::ostringstream message; message << name << " is not a valid correlation matrix. " << name << "(" << k << "," << k << ") is %1%, but should be near 1.0"; T_result tmp = policies::raise_domain_error<T_y>(function, message.str().c_str(), y(k,k), Policy()); if (result != 0) *result = tmp; return false; } } if (!check_pos_definite(function, y, "y", result, Policy())) return false; return true; }
inline fvar<T> determinant(const Eigen::Matrix<fvar<T>, R, C>& m) { using stan::math::multiply; using stan::math::inverse; stan::math::check_square("determinant", "m", m); Eigen::Matrix<T,R,C> m_deriv(m.rows(), m.cols()); Eigen::Matrix<T,R,C> m_val(m.rows(), m.cols()); for(size_type i = 0; i < m.rows(); i++) { for(size_type j = 0; j < m.cols(); j++) { m_deriv(i,j) = m(i,j).d_; m_val(i,j) = m(i,j).val_; } } Eigen::Matrix<T,R,C> m_inv = inverse<T>(m_val); m_deriv = multiply(m_inv, m_deriv); fvar<T> result; result.val_ = m_val.determinant(); result.d_ = result.val_ * m_deriv.trace(); // FIXME: I think this will overcopy compared to retur fvar<T>(...); return result; }
inline int categorical_rng(const Eigen::Matrix<double, Eigen::Dynamic, 1>& theta, RNG& rng) { using boost::variate_generator; using boost::uniform_01; static const char* function("categorical_rng"); check_simplex(function, "Probabilities parameter", theta); variate_generator<RNG&, uniform_01<> > uniform01_rng(rng, uniform_01<>()); Eigen::VectorXd index(theta.rows()); index.setZero(); for (int i = 0; i < theta.rows(); i++) { for (int j = i; j < theta.rows(); j++) index(j) += theta(i, 0); } double c = uniform01_rng(); int b = 0; while (c > index(b, 0)) b++; return b + 1; }
typename boost::math::tools::promote_args<T_prob,T_prior_sample_size>::type dirichlet_log(const Eigen::Matrix<T_prob,Eigen::Dynamic,1>& theta, const Eigen::Matrix<T_prior_sample_size,Eigen::Dynamic,1>& alpha) { static const char* function = "stan::prob::dirichlet_log(%1%)"; using boost::math::lgamma; using boost::math::tools::promote_args; using stan::math::check_consistent_sizes; using stan::math::check_positive; using stan::math::check_simplex; using stan::math::multiply_log; typename promote_args<T_prob,T_prior_sample_size>::type lp(0.0); check_consistent_sizes(function, theta, alpha, "probabilities", "prior sample sizes", &lp); check_positive(function, alpha, "prior sample sizes", &lp); check_simplex(function, theta, "probabilities", &lp); if (include_summand<propto,T_prior_sample_size>::value) { lp += lgamma(alpha.sum()); for (int k = 0; k < alpha.rows(); ++k) lp -= lgamma(alpha[k]); } if (include_summand<propto,T_prob,T_prior_sample_size>::value) for (int k = 0; k < theta.rows(); ++k) lp += multiply_log(alpha[k]-1, theta[k]); return lp; }
inline typename boost::disable_if_c<boost::is_same<I1, index_uni>::value || boost::is_same<I2, index_uni>::value, void>::type assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, const cons_index_list<I1, cons_index_list<I2, nil_index_list> >& idxs, const Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic>& y, const char* name = "ANON", int depth = 0) { int x_idxs_rows = rvalue_index_size(idxs.head_, x.rows()); int x_idxs_cols = rvalue_index_size(idxs.tail_.head_, x.cols()); math::check_size_match("matrix[multi,multi] assign sizes", "lhs", x_idxs_rows, name, y.rows()); math::check_size_match("matrix[multi,multi] assign sizes", "lhs", x_idxs_cols, name, y.cols()); for (int j = 0; j < y.cols(); ++j) { int n = rvalue_at(j, idxs.tail_.head_); math::check_range("matrix[multi,multi] assign range", name, x.cols(), n); for (int i = 0; i < y.rows(); ++i) { int m = rvalue_at(i, idxs.head_); math::check_range("matrix[multi,multi] assign range", name, x.rows(), m); x(m - 1, n - 1) = y(i, j); } } }
inline bool check_corr_matrix(const std::string& function, const std::string& name, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y) { using Eigen::Dynamic; using Eigen::Matrix; using stan::math::index_type; typedef typename index_type<Matrix<T_y,Dynamic,Dynamic> >::type size_t; check_size_match(function, "Rows of correlation matrix", y.rows(), "columns of correlation matrix", y.cols()); check_positive(function, "rows", y.rows()); check_symmetric(function, "y", y); for (size_t k = 0; k < y.rows(); ++k) { if (!(fabs(y(k,k) - 1.0) <= CONSTRAINT_TOLERANCE)) { std::ostringstream msg; msg << "is not a valid correlation matrix. " << name << "(" << stan::error_index::value + k << "," << stan::error_index::value + k << ") is "; ; dom_err(function, name, y(k,k), msg.str(), ", but should be near 1.0"); return false; } } stan::error_handling::check_pos_definite(function, "y", y); return true; }
void expect_matrix_eq(const Eigen::Matrix<T1,Eigen::Dynamic,Eigen::Dynamic>& a, const Eigen::Matrix<T2,Eigen::Dynamic,Eigen::Dynamic>& b) { EXPECT_EQ(a.rows(), b.rows()); EXPECT_EQ(a.cols(), b.cols()); for (int i = 0; i < a.rows(); ++i) for (int j = 0; j < a.cols(); ++j) EXPECT_FLOAT_EQ(value_of(a(i,j)), value_of(b(i,j))); }
void vector_test(const Eigen::Matrix<Real, NbRows, NbCols>& A, const Eigen::Matrix<Real, NbRows, NbCols>& B, Accumulator& Result) { for(int i = 0, k = 0; i != A.rows() && k != B.rows(); ++i, ++k) for(int j = 0, l = 0; j != A.cols() && l != B.cols(); ++j, ++l) test(A(i, j), B(k, l), Result); Result.exact(A.rows() == B.rows() && A.cols() == B.cols()); };
inline Eigen::Matrix<fvar<T>,R,1> rows_dot_self(const Eigen::Matrix<fvar<T>,R,C>& x) { Eigen::Matrix<fvar<T>,R,1> ret(x.rows(),1); for (size_type i = 0; i < x.rows(); i++) { Eigen::Matrix<fvar<T>,1,C> crow = x.row(i); ret(i,0) = dot_self(crow); } return ret; }
inline Eigen::Matrix<fvar<T>,R,C> divide(const Eigen::Matrix<fvar<T>, R,C>& v, const fvar<T>& c) { Eigen::Matrix<fvar<T>,R,C> res(v.rows(),v.cols()); for(int i = 0; i < v.rows(); i++) { for(int j = 0; j < v.cols(); j++) res(i,j) = v(i,j) / c; } return res; }
inline Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R,C> divide(const Eigen::Matrix<T1, R,C>& v, const fvar<T2>& c) { Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R,C> res(v.rows(),v.cols()); for(int i = 0; i < v.rows(); i++) { for(int j = 0; j < v.cols(); j++) res(i,j) = to_fvar(v(i,j)) / c; } return res; }
inline Eigen::Matrix<fvar<T>,R1,C1> multiply(const Eigen::Matrix<fvar<T>, R1, C1>& m, const fvar<T>& c) { Eigen::Matrix<fvar<T>,R1,C1> res(m.rows(),m.cols()); for(int i = 0; i < m.rows(); i++) { for(int j = 0; j < m.cols(); j++) res(i,j) = c * m(i,j); } return res; }
inline Eigen::Matrix<double, R1, 1> rows_dot_product(const Eigen::Matrix<double, R1, C1>& v1, const Eigen::Matrix<double, R2, C2>& v2) { validate_matching_sizes(v1,v2,"rows_dot_product"); Eigen::Matrix<double, R1, 1> ret(v1.rows(),1); for (size_type j = 0; j < v1.rows(); ++j) { ret(j) = v1.row(j).dot(v2.row(j)); } return ret; }
inline Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>, R2, C2> multiply(const Eigen::Matrix<fvar<T1>, R2, C2>& m, const T2& c) { Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R2,C2> res(m.rows(),m.cols()); for(int i = 0; i < m.rows(); i++) { for(int j = 0; j < m.cols(); j++) res(i,j) = to_fvar(c) * m(i,j); } return res; }
void validate_row_index(const Eigen::Matrix<T,R,C>& m, size_t i, const char* msg) { if (i > 0 && i <= static_cast<size_t>(m.rows())) return; std::stringstream ss; ss << "require 0 < row index <= number of rows in" << msg; ss << " found rows()=" << m.rows() << "; index i=" << i; throw std::domain_error(ss.str()); }
inline Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R1,C1> multiply(const Eigen::Matrix<T1, R1, C1>& m, const fvar<T2>& c) { Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R1,C1> res(m.rows(),m.cols()); for(int i = 0; i < m.rows(); i++) { for(int j = 0; j < m.cols(); j++) res(i,j) = c * to_fvar(m(i,j)); } return res; }
inline bool check_cov_matrix(const std::string& function, const std::string& name, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y) { check_size_match(function, "Rows of covariance matrix", y.rows(), "columns of covariance matrix", y.cols()); check_positive(function, "rows", y.rows()); check_symmetric(function, name, y); check_pos_definite(function, name, y); return true; }
inline Eigen::Matrix<T,Eigen::Dynamic,1> segment(const Eigen::Matrix<T,Eigen::Dynamic,1>& v, size_t i, size_t n) { stan::math::check_greater("segment(%1%)",i,0.0,"n",(double*)0); stan::math::check_less_or_equal("segment(%1%)",i,static_cast<size_t>(v.rows()),"n",(double*)0); if (n != 0) { stan::math::check_greater("segment(%1%)",i+n-1,0.0,"n",(double*)0); stan::math::check_less_or_equal("segment(%1%)",i+n-1,static_cast<size_t>(v.rows()),"n",(double*)0); } return v.segment(i-1,n); }
Eigen::Matrix<fvar<T>,Eigen::Dynamic,Eigen::Dynamic> qr_Q(const Eigen::Matrix<fvar<T>,Eigen::Dynamic,Eigen::Dynamic>& m) { typedef Eigen::Matrix<fvar<T>,Eigen::Dynamic,Eigen::Dynamic> matrix_fwd_t; stan::math::check_nonzero_size("qr_Q", "m", m); stan::math::check_greater_or_equal("qr_Q", "m.rows()", m.rows(), m.cols()); Eigen::HouseholderQR< matrix_fwd_t > qr(m.rows(), m.cols()); qr.compute(m); matrix_fwd_t Q = qr.householderQ(); for (int i=0; i<m.cols(); i++) if (qr.matrixQR()(i,i) < 0.0) Q.col(i) *= -1.0; return Q; }
inline bool check_cov_matrix(const char* function, const Eigen::Matrix<T_y,Eigen::Dynamic,Eigen::Dynamic>& y, const char* name, T_result* result) { check_size_match(function, y.rows(), "Rows of covariance matrix", y.cols(), "columns of covariance matrix", result); check_positive(function, y.rows(), "rows", result); check_symmetric(function, y, name, result); check_pos_definite(function, y, name, result); return true; }
std::string Gaussian<ScalarType>::toJSONString(bool styledWriter) const { DEBUG_OUT("saving gaussian as JSON", 40); //uses Jsoncpp as library. Jsoncpp is licensed as MIT, so we may use it without restriction. Json::Value root; Json::Writer* writer=NULL; if (styledWriter) writer = new Json::StyledWriter(); else writer = new Json::FastWriter(); //output the weight root["weight"] = getWeight(); //output the mean as array of doubles Json::Value mean(Json::arrayValue); Eigen::Matrix<ScalarType, Eigen::Dynamic, 1> gMean = getMean(); for (int i=0; i<gMean.size(); i++) mean.append(Json::Value(gMean[i])); root["mean"] = mean; //output the variance as array of double. only save the lower //triangular, as the other values are mirrored. Json::Value variance(Json::arrayValue); Eigen::Matrix<ScalarType, Eigen::Dynamic, Eigen::Dynamic> gVariance = getCovarianceMatrix(); if (isDiagonal(gVariance)) { DEBUG_OUT("save as diagonal covariance matrix", 45); for (int i=0; i<gVariance.rows(); i++) { variance.append(Json::Value(gVariance(i, i))); } } else { DEBUG_OUT("save as full covariance matrix", 45); for (int i=0; i<gVariance.rows(); i++) { for (int j=i; j<gVariance.cols(); j++) { variance.append(Json::Value(gVariance(i, j))); } } } root["covariance"] = variance; std::string str = writer->write(root); delete writer; return str; }
inline var log_determinant_spd(const Eigen::Matrix<var,R,C>& m) { using stan::math::domain_error; using Eigen::Matrix; math::check_square("log_determinant_spd", "m", m); Matrix<double,R,C> m_d(m.rows(),m.cols()); for (int i = 0; i < m.size(); ++i) m_d(i) = m(i).val(); Eigen::LDLT<Matrix<double,R,C> > ldlt(m_d); if (ldlt.info() != Eigen::Success) { double y = 0; domain_error("log_determinant_spd", "matrix argument", y, "failed LDLT factorization"); } // compute the inverse of A (needed for the derivative) m_d.setIdentity(m.rows(), m.cols()); ldlt.solveInPlace(m_d); if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) { double y = 0; domain_error("log_determinant_spd", "matrix argument", y, "matrix is negative definite"); } double val = ldlt.vectorD().array().log().sum(); if (!boost::math::isfinite(val)) { double y = 0; domain_error("log_determinant_spd", "matrix argument", y, "log determininant is infinite"); } vari** operands = ChainableStack::memalloc_ .alloc_array<vari*>(m.size()); for (int i = 0; i < m.size(); ++i) operands[i] = m(i).vi_; double* gradients = ChainableStack::memalloc_ .alloc_array<double>(m.size()); for (int i = 0; i < m.size(); ++i) gradients[i] = m_d(i); return var(new precomputed_gradients_vari(val,m.size(),operands,gradients)); }
inline void check_pos_definite(const char* function, const char* name, const Eigen::Matrix<T_y, -1, -1>& y) { check_symmetric(function, name, y); check_positive_size(function, name, "rows", y.rows()); if (y.rows() == 1 && !(y(0, 0) > CONSTRAINT_TOLERANCE)) domain_error(function, name, "is not positive definite.", ""); Eigen::LDLT<Eigen::MatrixXd> cholesky = value_of_rec(y).ldlt(); if (cholesky.info() != Eigen::Success || !cholesky.isPositive() || (cholesky.vectorD().array() <= 0.0).any()) domain_error(function, name, "is not positive definite.", ""); check_not_nan(function, name, y); }
inline Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> append_col(const Eigen::Matrix<T, R1, C1>& A, const Eigen::Matrix<T, R2, C2>& B) { using Eigen::Matrix; using Eigen::Dynamic; check_size_match("append_col", "rows of A", A.rows(), "rows of B", B.rows()); Matrix<T, Dynamic, Dynamic> result(A.rows(), A.cols()+B.cols()); result << A, B; return result; }
inline Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R1,C2> multiply(const Eigen::Matrix<fvar<T1>,R1,C1>& m1, const Eigen::Matrix<T2,R2,C2>& m2) { stan::math::validate_multiplicable(m1,m2,"multiply"); Eigen::Matrix<fvar<typename stan::return_type<T1,T2>::type>,R1,C2> result(m1.rows(),m2.cols()); for (size_type i = 0; i < m1.rows(); i++) { Eigen::Matrix<fvar<T1>,1,C1> crow = m1.row(i); for (size_type j = 0; j < m2.cols(); j++) { Eigen::Matrix<T2,R2,1> ccol = m2.col(j); result(i,j) = stan::agrad::dot_product(crow,ccol); } } return result; }
void write_stan(const Eigen::Matrix<double, Eigen::Dynamic,Eigen::Dynamic>& x) { typedef Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>::Index Index; out_ << "structure(c("; std::vector<double> vals; for (Index m = 0; m < x.cols(); ++m) { for (Index n = 0; n < x.rows(); ++n) { if (m > 0 || n > 0) out_ << ", "; write_val(x(m,n)); } } out_ << "), .Dim = c("; out_ << x.rows() << ", " << x.cols(); out_ << "))"; }
void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst ) { if( !(src.Flags & Eigen::RowMajorBit) ) { Mat _src(src.cols(), src.rows(), DataType<_Tp>::type, (void*)src.data(), src.stride()*sizeof(_Tp)); transpose(_src, dst); } else { Mat _src(src.rows(), src.cols(), DataType<_Tp>::type, (void*)src.data(), src.stride()*sizeof(_Tp)); _src.copyTo(dst); } }