-
-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create Jacobian template parameter overload for constrain functions #2559
Changes from all commits
dfa27aa
ca90f8c
d74af94
661ce32
e9797e1
318dd13
2971378
e4650cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,14 +26,14 @@ namespace math { | |
* @return Cholesky factor | ||
*/ | ||
template <typename T, require_eigen_col_vector_t<T>* = nullptr> | ||
Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cholesky_factor_constrain(const T& x, int M, int N) { | ||
using std::exp; | ||
using T_scalar = value_type_t<T>; | ||
check_greater_or_equal("cholesky_factor_constrain", | ||
"num rows (must be greater or equal to num cols)", M, | ||
N); | ||
check_size_match("cholesky_factor_constrain", "x.size()", x.size(), | ||
check_size_match("cholesky_factor_constrain", "constrain size", x.size(), | ||
"((N * (N + 1)) / 2 + (M - N) * N)", | ||
((N * (N + 1)) / 2 + (M - N) * N)); | ||
Eigen::Matrix<T_scalar, Eigen::Dynamic, Eigen::Dynamic> y(M, N); | ||
|
@@ -58,21 +58,22 @@ cholesky_factor_constrain(const T& x, int M, int N) { | |
/** | ||
* Return the Cholesky factor of the specified size read from the | ||
* specified vector and increment the specified log probability | ||
* reference with the log Jacobian adjustment of the transform. A total | ||
* of (N choose 2) + N + N * (M - N) free parameters are required to read | ||
* an M by N Cholesky factor. | ||
* reference with the log absolute Jacobian determinant adjustment of the | ||
* transform. A total of (N choose 2) + N + N * (M - N) free parameters are | ||
* required to read an M by N Cholesky factor. | ||
* | ||
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase and | ||
* have one compile-time dimension equal to 1) | ||
* @param x Vector of unconstrained values | ||
* @param M number of rows | ||
* @param N number of columns | ||
* @param lp Log probability that is incremented with the log Jacobian | ||
* @param lp Log probability that is incremented with the log absolute Jacobian | ||
* determinant | ||
* @return Cholesky factor | ||
*/ | ||
template <typename T, require_eigen_vector_t<T>* = nullptr> | ||
Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cholesky_factor_constrain(const T& x, int M, int N, value_type_t<T>& lp) { | ||
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cholesky_factor_constrain(const T& x, int M, int N, return_type_t<T>& lp) { | ||
check_size_match("cholesky_factor_constrain", "x.size()", x.size(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [optional] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep just fixed these up to `constrained size'. |
||
"((N * (N + 1)) / 2 + (M - N) * N)", | ||
((N * (N + 1)) / 2 + (M - N) * N)); | ||
|
@@ -85,6 +86,36 @@ cholesky_factor_constrain(const T& x, int M, int N, value_type_t<T>& lp) { | |
return cholesky_factor_constrain(x_ref, M, N); | ||
} | ||
|
||
/** | ||
* Return the Cholesky factor of the specified size read from the specified | ||
* vector. A total of (N choose 2) + N + N * (M - N) free parameters are | ||
* required to read an M by N Cholesky factor. If the `Jacobian` parameter is | ||
* `true`, the log density accumulator is incremented with the log absolute | ||
* Jacobian determinant of the transform. All of the transforms are specified | ||
* with their Jacobians in the *Stan Reference Manual* chapter Constraint | ||
* Transforms. | ||
* | ||
* @tparam Jacobian if `true`, increment log density accumulator with log | ||
* absolute Jacobian determinant of constraining transform | ||
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with | ||
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows | ||
* and 1 column | ||
* @param x Vector of unconstrained values | ||
* @param M number of rows | ||
* @param N number of columns | ||
* @param[in,out] lp log density accumulator | ||
* @return Cholesky factor | ||
*/ | ||
template <bool Jacobian, typename T> | ||
inline auto cholesky_factor_constrain(const T& x, int M, int N, | ||
return_type_t<T>& lp) { | ||
if (Jacobian) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [optional]
if it fits or
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo I like the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. Does the ternary operator not get reduced at compile time if the condition is |
||
return cholesky_factor_constrain(x, M, N, lp); | ||
} else { | ||
return cholesky_factor_constrain(x, M, N); | ||
} | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,7 @@ namespace math { | |
* @return tanh transform | ||
*/ | ||
template <typename T> | ||
inline auto corr_constrain(const T& x) { | ||
inline plain_type_t<T> corr_constrain(const T& x) { | ||
return tanh(x); | ||
} | ||
|
||
|
@@ -49,6 +49,30 @@ inline auto corr_constrain(const T_x& x, T_lp& lp) { | |
return tanh_x; | ||
} | ||
|
||
/** | ||
* Return the result of transforming the specified scalar or container of values | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The doc for all of these needs to mention that the Jacobian is incremented with the log absolute Jacobian determinant of the transform if the template parameter There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes I appended the doc you mention below with all of these so should be good now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good. Thanks. |
||
* to have a valid correlation value between -1 and 1 (inclusive). If the | ||
* `Jacobian` parameter is `true`, the log density accumulator is incremented | ||
* with the log absolute Jacobian determinant of the transform. All of the | ||
* transforms are specified with their Jacobians in the *Stan Reference Manual* | ||
* chapter Constraint Transforms. | ||
* | ||
* @tparam Jacobian if `true`, increment log density accumulator with log | ||
* absolute Jacobian determinant of constraining transform | ||
* @tparam T_x Type of scalar or container | ||
* @tparam T_lp type of target log density accumulator | ||
* @param[in] x value or container | ||
* @param[in,out] lp log density accumulator | ||
*/ | ||
template <bool Jacobian, typename T_x, typename T_lp> | ||
inline auto corr_constrain(const T_x& x, T_lp& lp) { | ||
if (Jacobian) { | ||
return corr_constrain(x, lp); | ||
} else { | ||
return corr_constrain(x); | ||
} | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ namespace math { | |
* @throws std::invalid_argument if (x.size() != K + (K choose 2)). | ||
*/ | ||
template <typename T, require_eigen_col_vector_t<T>* = nullptr> | ||
Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cov_matrix_constrain(const T& x, Eigen::Index K) { | ||
using Eigen::Dynamic; | ||
using Eigen::Matrix; | ||
|
@@ -53,8 +53,6 @@ cov_matrix_constrain(const T& x, Eigen::Index K) { | |
* by K resulting from transforming the specified finite vector of | ||
* size K plus (K choose 2). | ||
* | ||
* <p>See <code>cov_matrix_free()</code> for the inverse transform. | ||
* | ||
* @tparam T type of the vector (must be derived from \c Eigen::MatrixBase and | ||
* have one compile-time dimension equal to 1) | ||
* @param x The vector to convert to a covariance matrix. | ||
|
@@ -63,8 +61,8 @@ cov_matrix_constrain(const T& x, Eigen::Index K) { | |
* @throws std::domain_error if (x.size() != K + (K choose 2)). | ||
*/ | ||
template <typename T, require_eigen_col_vector_t<T>* = nullptr> | ||
Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cov_matrix_constrain(const T& x, Eigen::Index K, value_type_t<T>& lp) { | ||
inline Eigen::Matrix<value_type_t<T>, Eigen::Dynamic, Eigen::Dynamic> | ||
cov_matrix_constrain(const T& x, Eigen::Index K, return_type_t<T>& lp) { | ||
using Eigen::Dynamic; | ||
using Eigen::Matrix; | ||
using std::exp; | ||
|
@@ -88,6 +86,34 @@ cov_matrix_constrain(const T& x, Eigen::Index K, value_type_t<T>& lp) { | |
return multiply_lower_tri_self_transpose(L); | ||
} | ||
|
||
/** | ||
* Return the symmetric, positive-definite matrix of dimensions K by K resulting | ||
* from transforming the specified finite vector of size K plus (K choose 2). If | ||
* the `Jacobian` parameter is `true`, the log density accumulator is | ||
* incremented with the log absolute Jacobian determinant of the transform. All | ||
* of the transforms are specified with their Jacobians in the *Stan Reference | ||
* Manual* chapter Constraint Transforms. | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good doc on function, but needs to mention Jacobian and its template parameter either in this first sentence or the second one. |
||
* @tparam Jacobian if `true`, increment log density accumulator with log | ||
* absolute Jacobian determinant of constraining transform | ||
* @tparam T A type inheriting from `Eigen::DenseBase` or a `var_value` with | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comments as on other doc:
|
||
* inner type inheriting from `Eigen::DenseBase` with compile time dynamic rows | ||
* and 1 column | ||
* @param x The vector to convert to a covariance matrix | ||
* @param K The dimensions of the resulting covariance matrix | ||
* @param[in, out] lp log density accumulator | ||
* @throws std::domain_error if (x.size() != K + (K choose 2)). | ||
*/ | ||
template <bool Jacobian, typename T> | ||
inline auto cov_matrix_constrain(const T& x, Eigen::Index K, | ||
return_type_t<T>& lp) { | ||
if (Jacobian) { | ||
return cov_matrix_constrain(x, K, lp); | ||
} else { | ||
return cov_matrix_constrain(x, K); | ||
} | ||
} | ||
|
||
} // namespace math | ||
} // namespace stan | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,12 +11,14 @@ namespace math { | |
* transform to the input. This promotes the input to the least upper | ||
* bound of the input types. | ||
* | ||
* @tparam Jacobian if `true`, increment log density accumulator with log | ||
* absolute Jacobian determinant of constraining transform | ||
* @tparam T type of value to promote | ||
* @tparam Types Other types. | ||
* @param[in] x object | ||
* @return transformed input | ||
*/ | ||
template <typename T, typename... Types, | ||
template <bool Jacobian = false, typename T, typename... Types, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [question] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With a value of false yes we could take all of current ones with |
||
require_all_not_var_matrix_t<T, Types...>* = nullptr> | ||
inline auto identity_constrain(T&& x, Types&&... /* args */) { | ||
return promote_scalar_t<return_type_t<T, Types...>, T>(x); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[question]
I'm unclear on how this function gets resolved since it seems to call itself inside the
if (Jacobian)
block. Is this only resolved because the nested call doesn't provide a template parameter?[comment]
I opened an issue to refactor the implementation: #2561
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes since there's no default template value for
Jacobian
it diverts to the signatures without theJacobian
template parameter