-
-
Notifications
You must be signed in to change notification settings - Fork 183
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
Feature/issue 962 bivar norm #1009
Conversation
…r derivatives, fixed segfaults for lcdf
…stable/2017-11-14)
…xp1~20180509124008.99 (branches/release_50)
…dev/math into feature/issue-962-bivar-norm
…xp1~20180509124008.99 (branches/release_50)
…xp1~20180509124008.99 (branches/release_50)
@bob-carpenter this is ready for a review when you've got some time |
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.
Thanks. This is basically OK. I'd be a lot happier if all of the cut-and-paste code in the tests could be cosolidated.
const T_partials_return sqrt_one_minus_rho_sq = sqrt(one_minus_rho_sq); | ||
const T_partials_return rho_times_y2 = rho_dbl * y2_dbl; | ||
const T_partials_return y1_minus_rho_times_y2 = y1_dbl - rho_times_y2; | ||
const bool y1_isfinite = std::isfinite(value_of_rec(y1_dbl)); |
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.
Stan's is_finite
will work directly on y1
, I think---I'm not sure why there's a recursive value_of here.
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.
I don't think that Stan has an is_finite implementation that works for arbitrary types. Here's an implementation for vars
: https://github.com/stan-dev/math/blob/502487c511594ccb93eb979df5b8fe163becb417/stan/math/rev/scal/fun/boost_isfinite.hpp but as far as I can tell this is it. I have the value_of_rec
to handle the nested AD types cases.
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.
Thanks for looking. That's a separate shortcoming of the math lib you don't need to address here.
if (!is_constant_struct<T_rho>::value) | ||
ops_partials.edge2_.partials_[n] | ||
+= cdf_ > 0 && y1_y2_arefinite && rho_lt_one | ||
? inv_cdf_ * 0.5 / (stan::math::pi() * sqrt_one_minus_rho_sq) |
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.
Arithmetic is left associative, so all the constants should be pushed together, here (0.5 / ...)
.
? inv_cdf_ * 0.5 / (stan::math::pi() * sqrt_one_minus_rho_sq) | ||
* exp(-0.5 / one_minus_rho_sq * y1_minus_rho_times_y2 | ||
* y1_minus_rho_times_y2 | ||
- 0.5 * y2_dbl * y2_dbl) |
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.
The -0.5
should go on the outside to save a multiplication,
exp(-0.5 * (square(y1_minus_rho_times_y2) / one_minus_rho_sq
+ square(y2_dbl)));
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.
Is square
better to use than direct multiplication? i.e. x * x
vs. square(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.
Only if the variable can be an autodiff variable.
} | ||
}; | ||
|
||
// vector<Row Vector>, real |
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.
These should also be templatable. No big deal if you don't combine, but it's easier to maintain with fewer cut-and-paste functions.
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.
Yeah, I'm OK templating these tests more. I did so for the copula PR, so redoing these should be easier.
template <typename T> | ||
inline T operator()( | ||
const Eigen::Matrix<T, Eigen::Dynamic, 1>& inp_vec) const { | ||
vector<Matrix<T, Dynamic, 1>> y; |
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.
These four lines of code are repeated other than for type, so they should be pullable into a function.
}; | ||
|
||
// Row Vector, double | ||
struct RV_D_std_binorm_lcdf { |
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.
Consolidate vetor and row vector versions using templating.
} | ||
}; | ||
|
||
// double vector<Row Vector>, real |
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.
Basically, way too many of these. Figure out how to consolidate using templates if at all possible.
If not, document the scheme up top.
vector<Eigen::Matrix<T, Eigen::Dynamic, 1>>& y, T& rho) { | ||
int cntr = 0; | ||
for (int i = 0; i < N_y; ++i) { | ||
Eigen::Matrix<T, Eigen::Dynamic, 1> el(2); |
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.
At the very least, these repeated pieces need to be turned into functions.
Does the y
need to be passed in here as an argument since it's just being constructed? How about returning it rather than passing it in?
Closing due to inactivity. |
Summary
Adds
std_binormal_lcdf
andstd_binormal_integral
to compute the log-CDF and the CDF of the bivariate standard normal density.Tests
Added tests for prim, rev, fwd, mix for
std_binormal_integral
and tests for prim, rev, mix forstd_binormal_lcdf
. Gradient and higher-order tests are in rev and mix for both functions.Side Effects
None
Checklist
Math issue Bivariate normal distribution #962
Copyright holder: Rob Trangucci
The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
- Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
- Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
the basic tests are passing
./runTests.py test/unit
)make test-headers
)make doxygen
)make cpplint
)the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested