From fa4ae9bfbc85ce4ac2d39e9aebb4a6198f00b59e Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Thu, 6 Feb 2020 16:43:35 +0000 Subject: [PATCH 1/6] Add discrete_range_rng() --- stan/math/prim/prob.hpp | 1 + stan/math/prim/prob/discrete_range_rng.hpp | 65 +++++++++++++++++ .../math/prim/prob/discrete_range_test.cpp | 73 +++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 stan/math/prim/prob/discrete_range_rng.hpp create mode 100644 test/unit/math/prim/prob/discrete_range_test.cpp diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index d2b0a9d34d6..177b69017e2 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include diff --git a/stan/math/prim/prob/discrete_range_rng.hpp b/stan/math/prim/prob/discrete_range_rng.hpp new file mode 100644 index 00000000000..bf2dc957d7f --- /dev/null +++ b/stan/math/prim/prob/discrete_range_rng.hpp @@ -0,0 +1,65 @@ +#ifndef STAN_MATH_PRIM_PROB_DISCRETE_RANGE_RNG_HPP +#define STAN_MATH_PRIM_PROB_DISCRETE_RANGE_RNG_HPP + +#include +#include +#include +#include +#include + +namespace stan { +namespace math { + +/** \ingroup prob_dists + * Return a discrete random variate for the given lower and upper bounds + * (inclusive) using the specified random number generator. + * + * `lower` and `upper` can each be a scalar or a one-dimensional container. + * Any non-scalar inputs must be the same size. + * + * @tparam T_lower type of lower bound + * @tparam T_upper type of upper bound + * @tparam RNG type of random number generator + * + * @param lower lower bound + * @param upper upper bound + * @param rng random number generator + * @return A (sequence of) discrete random variate(s) between `lower` and + * `upper`, both bounds included. + * @throw std::domain_error if lower or upper are non-finite, or if upper + * is smaller than lower + * @throw std::invalid_argument if non-scalar arguments are of different + * sizes + */ +template +inline typename VectorBuilder::type +discrete_range_rng(const T_lower& lower, const T_upper& upper, RNG& rng) { + using boost::variate_generator; + using boost::random::uniform_int_distribution; + + static const char* function = "discrete_range_rng"; + + check_finite(function, "Lower bound parameter", lower); + check_finite(function, "Upper bound parameter", upper); + check_consistent_sizes(function, "Lower bound parameter", lower, + "Upper bound parameter", upper); + check_greater_or_equal(function, "Upper bound parameter", upper, lower); + + scalar_seq_view lower_vec(lower); + scalar_seq_view upper_vec(upper); + size_t N = max_size(lower, upper); + VectorBuilder output(N); + + for (size_t n = 0; n < N; ++n) { + variate_generator> discrete_range_rng( + rng, uniform_int_distribution<>(lower_vec[n], upper_vec[n])); + + output[n] = discrete_range_rng(); + } + + return output.data(); +} + +} // namespace math +} // namespace stan +#endif diff --git a/test/unit/math/prim/prob/discrete_range_test.cpp b/test/unit/math/prim/prob/discrete_range_test.cpp new file mode 100644 index 00000000000..eee756c6785 --- /dev/null +++ b/test/unit/math/prim/prob/discrete_range_test.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include + +TEST(ProbDistributionsDiscreteRange, error_check) { + using stan::math::discrete_range_rng; + boost::random::mt19937 rng; + + double nan = std::numeric_limits::quiet_NaN(); + double inf = std::numeric_limits::infinity(); + + Eigen::VectorXd lower(3); + Eigen::VectorXd upper(3); + + lower << 5.0, 11.0, -15.0; + upper << 5.0, 15.0, -10.0; + EXPECT_NO_THROW(discrete_range_rng(lower, upper, rng)); + EXPECT_THROW(discrete_range_rng(lower, 10, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(10, upper, rng), std::domain_error); + + lower << -1e3, 1.1e3, 1e4; + upper << -1e2, 1.2e3, 1e5; + EXPECT_NO_THROW(discrete_range_rng(lower, upper, rng)); + + EXPECT_THROW(discrete_range_rng(nan, upper, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(inf, upper, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(-inf, upper, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(lower, nan, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(lower, inf, rng), std::domain_error); + EXPECT_THROW(discrete_range_rng(lower, -inf, rng), std::domain_error); + + Eigen::VectorXd vec2(2); + vec2 << 1, 2; + EXPECT_THROW(discrete_range_rng(lower, vec2, rng), std::invalid_argument); + EXPECT_THROW(discrete_range_rng(vec2, upper, rng), std::invalid_argument); +} + +TEST(ProbDistributionsDiscreteRange, chiSquareGoodnessFitTest) { + boost::random::mt19937 rng; + + int N = 10000; + int lower = -3; + int upper = 20; + + int K = upper - lower + 1; + boost::math::chi_squared mydist(K - 1); + + int bin[K]; + double expect[K]; + double prop = static_cast(N) / K; + for (int i = 0; i < K; i++) { + bin[i] = 0; + expect[i] = prop; + } + + int count = 0; + while (count < N) { + int a = stan::math::discrete_range_rng(lower, upper, rng); + bin[a - lower]++; + count++; + } + + double chi = 0; + + for (int j = 0; j < K; j++) { + chi += (bin[j] - expect[j]) * (bin[j] - expect[j]) / expect[j]; + } + + EXPECT_TRUE(chi < quantile(complement(mydist, 1e-6))); +} From 209a76909ad064ebd814d7edd1198fbb537c7c7b Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 6 Feb 2020 16:55:47 +0000 Subject: [PATCH 2/6] [Jenkins] auto-formatting by clang-format version 5.0.0-3~16.04.1 (tags/RELEASE_500/final) --- stan/math/prim/prob/discrete_range_rng.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stan/math/prim/prob/discrete_range_rng.hpp b/stan/math/prim/prob/discrete_range_rng.hpp index bf2dc957d7f..59525245e1b 100644 --- a/stan/math/prim/prob/discrete_range_rng.hpp +++ b/stan/math/prim/prob/discrete_range_rng.hpp @@ -34,8 +34,8 @@ namespace math { template inline typename VectorBuilder::type discrete_range_rng(const T_lower& lower, const T_upper& upper, RNG& rng) { - using boost::variate_generator; using boost::random::uniform_int_distribution; + using boost::variate_generator; static const char* function = "discrete_range_rng"; From 61a4a1d9d118b4eb31617695284dc2ef4dd1b07e Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Fri, 7 Feb 2020 13:33:29 +0000 Subject: [PATCH 3/6] Address review requests --- stan/math/prim/prob/discrete_range_rng.hpp | 15 ++--- .../math/prim/prob/discrete_range_test.cpp | 55 ++++++++----------- 2 files changed, 29 insertions(+), 41 deletions(-) diff --git a/stan/math/prim/prob/discrete_range_rng.hpp b/stan/math/prim/prob/discrete_range_rng.hpp index 59525245e1b..9d2a5f56e3a 100644 --- a/stan/math/prim/prob/discrete_range_rng.hpp +++ b/stan/math/prim/prob/discrete_range_rng.hpp @@ -11,25 +11,24 @@ namespace stan { namespace math { /** \ingroup prob_dists - * Return a discrete random variate for the given lower and upper bounds + * Return an integer random variate between the given lower and upper bounds * (inclusive) using the specified random number generator. * * `lower` and `upper` can each be a scalar or a one-dimensional container. * Any non-scalar inputs must be the same size. * - * @tparam T_lower type of lower bound - * @tparam T_upper type of upper bound + * @tparam T_lower type of lower bound, either int or std::vector + * @tparam T_upper type of upper bound, either int or std::vector * @tparam RNG type of random number generator * * @param lower lower bound * @param upper upper bound * @param rng random number generator - * @return A (sequence of) discrete random variate(s) between `lower` and + * @return A (sequence of) integer random variate(s) between `lower` and * `upper`, both bounds included. - * @throw std::domain_error if lower or upper are non-finite, or if upper - * is smaller than lower + * @throw std::domain_error if upper is smaller than lower. * @throw std::invalid_argument if non-scalar arguments are of different - * sizes + * sizes. */ template inline typename VectorBuilder::type @@ -39,8 +38,6 @@ discrete_range_rng(const T_lower& lower, const T_upper& upper, RNG& rng) { static const char* function = "discrete_range_rng"; - check_finite(function, "Lower bound parameter", lower); - check_finite(function, "Upper bound parameter", upper); check_consistent_sizes(function, "Lower bound parameter", lower, "Upper bound parameter", upper); check_greater_or_equal(function, "Upper bound parameter", upper, lower); diff --git a/test/unit/math/prim/prob/discrete_range_test.cpp b/test/unit/math/prim/prob/discrete_range_test.cpp index eee756c6785..d6535d384f3 100644 --- a/test/unit/math/prim/prob/discrete_range_test.cpp +++ b/test/unit/math/prim/prob/discrete_range_test.cpp @@ -2,42 +2,40 @@ #include #include #include -#include #include TEST(ProbDistributionsDiscreteRange, error_check) { using stan::math::discrete_range_rng; boost::random::mt19937 rng; - double nan = std::numeric_limits::quiet_NaN(); - double inf = std::numeric_limits::infinity(); + std::vector lower{5, 11, -15}; + std::vector upper{7, 15, -10}; - Eigen::VectorXd lower(3); - Eigen::VectorXd upper(3); - - lower << 5.0, 11.0, -15.0; - upper << 5.0, 15.0, -10.0; EXPECT_NO_THROW(discrete_range_rng(lower, upper, rng)); EXPECT_THROW(discrete_range_rng(lower, 10, rng), std::domain_error); EXPECT_THROW(discrete_range_rng(10, upper, rng), std::domain_error); - lower << -1e3, 1.1e3, 1e4; - upper << -1e2, 1.2e3, 1e5; - EXPECT_NO_THROW(discrete_range_rng(lower, upper, rng)); - - EXPECT_THROW(discrete_range_rng(nan, upper, rng), std::domain_error); - EXPECT_THROW(discrete_range_rng(inf, upper, rng), std::domain_error); - EXPECT_THROW(discrete_range_rng(-inf, upper, rng), std::domain_error); - EXPECT_THROW(discrete_range_rng(lower, nan, rng), std::domain_error); - EXPECT_THROW(discrete_range_rng(lower, inf, rng), std::domain_error); - EXPECT_THROW(discrete_range_rng(lower, -inf, rng), std::domain_error); - - Eigen::VectorXd vec2(2); - vec2 << 1, 2; + std::vector vec2{1, 2}; EXPECT_THROW(discrete_range_rng(lower, vec2, rng), std::invalid_argument); EXPECT_THROW(discrete_range_rng(vec2, upper, rng), std::invalid_argument); } +TEST(ProbDistributionsDiscreteRange, boundary_values) { + using stan::math::discrete_range_rng; + boost::random::mt19937 rng; + + std::vector lower{-5, 11, 17}; + EXPECT_EQ(lower, discrete_range_rng(lower, lower, rng)); + + std::vector upper(lower); + for (int i = 0; i < upper.size(); i++) { + ++upper[i]; + } + + EXPECT_LE(lower, discrete_range_rng(lower, upper, rng)); + EXPECT_GE(upper, discrete_range_rng(lower, upper, rng)); +} + TEST(ProbDistributionsDiscreteRange, chiSquareGoodnessFitTest) { boost::random::mt19937 rng; @@ -48,19 +46,12 @@ TEST(ProbDistributionsDiscreteRange, chiSquareGoodnessFitTest) { int K = upper - lower + 1; boost::math::chi_squared mydist(K - 1); - int bin[K]; - double expect[K]; - double prop = static_cast(N) / K; - for (int i = 0; i < K; i++) { - bin[i] = 0; - expect[i] = prop; - } + std::vector bin(K, 0); + std::vector expect(K, static_cast(N) / K); - int count = 0; - while (count < N) { + for (int count = 0; count < N; ++count) { int a = stan::math::discrete_range_rng(lower, upper, rng); - bin[a - lower]++; - count++; + ++bin[a - lower]; } double chi = 0; From bbd1b28b1cb68df6f43fab01bb92af90478b3fd2 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Fri, 7 Feb 2020 14:59:32 +0000 Subject: [PATCH 4/6] Add discrete_range_lpmf --- stan/math/prim/prob.hpp | 2 + stan/math/prim/prob/discrete_range_log.hpp | 29 ++++++ stan/math/prim/prob/discrete_range_lpmf.hpp | 96 +++++++++++++++++++ .../discrete_range/discrete_range_test.hpp | 62 ++++++++++++ .../prim/prob/discrete_range_log_test.cpp | 24 +++++ 5 files changed, 213 insertions(+) create mode 100644 stan/math/prim/prob/discrete_range_log.hpp create mode 100644 stan/math/prim/prob/discrete_range_lpmf.hpp create mode 100644 test/prob/discrete_range/discrete_range_test.hpp create mode 100644 test/unit/math/prim/prob/discrete_range_log_test.cpp diff --git a/stan/math/prim/prob.hpp b/stan/math/prim/prob.hpp index 177b69017e2..6aad4c64441 100644 --- a/stan/math/prim/prob.hpp +++ b/stan/math/prim/prob.hpp @@ -75,6 +75,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/stan/math/prim/prob/discrete_range_log.hpp b/stan/math/prim/prob/discrete_range_log.hpp new file mode 100644 index 00000000000..2c47f84eaa2 --- /dev/null +++ b/stan/math/prim/prob/discrete_range_log.hpp @@ -0,0 +1,29 @@ +#ifndef STAN_MATH_PRIM_PROB_DISCRETE_RANGE_LOG_HPP +#define STAN_MATH_PRIM_PROB_DISCRETE_RANGE_LOG_HPP + +#include + +namespace stan { +namespace math { + +/** \ingroup prob_dists + * @deprecated use discrete_range_lpmf + */ +template +double discrete_range_log(const T_y& y, const T_lower& lower, + const T_upper& upper) { + return discrete_range_lpmf(y, lower, upper); +} + +/** \ingroup prob_dists + * @deprecated use discrete_range_lpmf + */ +template +inline double discrete_range_log(const T_y& y, const T_lower& lower, + const T_upper& upper) { + return discrete_range_lpmf(y, lower, upper); +} + +} // namespace math +} // namespace stan +#endif diff --git a/stan/math/prim/prob/discrete_range_lpmf.hpp b/stan/math/prim/prob/discrete_range_lpmf.hpp new file mode 100644 index 00000000000..d4bfcac138d --- /dev/null +++ b/stan/math/prim/prob/discrete_range_lpmf.hpp @@ -0,0 +1,96 @@ +#ifndef STAN_MATH_PRIM_PROB_DISCRETE_RANGE_LPMF_HPP +#define STAN_MATH_PRIM_PROB_DISCRETE_RANGE_LPMF_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace stan { +namespace math { + +/** \ingroup prob_dists + * Return the log PMF of a discrete range for the given y, lower and upper + * bound. + * + * `lower` and `upper` can each be a scalar or a one-dimensional container. + * Any non-scalar inputs must be the same size. + * + * @tparam T_y type of scalar, either int or std::vector + * @tparam T_lower type of lower bound, either int or std::vector + * @tparam T_upper type of upper bound, either int or std::vector + * + * @param y random variable + * @param lower lower bound + * @param upper upper bound + * @return Log probability. If containers are supplied, returns the log sum + * of the probabilities. + * @throw std::domain_error if upper is smaller than lower. + * @throw std::invalid_argument if non-scalar arguments are of different + * sizes. + */ +template +double discrete_range_lpmf(const T_y& y, const T_lower& lower, + const T_upper& upper) { + static const char* function = "discrete_range_lpmf"; + + using std::log; + + if (size_zero(y, lower, upper)) { + return 0.0; + } + + check_not_nan(function, "Random variable", y); + check_consistent_sizes(function, "Lower bound parameter", lower, + "Upper bound parameter", upper); + check_greater_or_equal(function, "Upper bound parameter", upper, lower); + + if (!include_summand::value) { + return 0.0; + } + + double logp(0.0); + + scalar_seq_view y_vec(y); + scalar_seq_view lower_vec(lower); + scalar_seq_view upper_vec(upper); + size_t size_lower_upper = max_size(lower, upper); + size_t N = max_size(y, lower, upper); + + for (size_t n = 0; n < N; ++n) { + const double y_dbl = value_of(y_vec[n]); + if (y_dbl < value_of(lower_vec[n]) || y_dbl > value_of(upper_vec[n])) { + return LOG_ZERO; + } + } + + VectorBuilder log_upper_minus_lower( + size_lower_upper); + + for (size_t i = 0; i < size_lower_upper; i++) { + const double lower_dbl = value_of(lower_vec[i]); + const double upper_dbl = value_of(upper_vec[i]); + log_upper_minus_lower[i] = log(upper_dbl - lower_dbl + 1); + } + + for (size_t n = 0; n < N; n++) { + logp -= log_upper_minus_lower[n]; + } + + return logp; +} + +template +inline double discrete_range_lpmf(const T_y& y, const T_lower& lower, + const T_upper& upper) { + return discrete_range_lpmf(y, lower, upper); +} + +} // namespace math +} // namespace stan +#endif diff --git a/test/prob/discrete_range/discrete_range_test.hpp b/test/prob/discrete_range/discrete_range_test.hpp new file mode 100644 index 00000000000..36433e06489 --- /dev/null +++ b/test/prob/discrete_range/discrete_range_test.hpp @@ -0,0 +1,62 @@ +// Arguments: Ints, Ints, Ints +#include + +using std::vector; + +class AgradDistributionsHypergeometric : public AgradDistributionTest { + public: + void valid_values(vector>& parameters, + vector& log_prob) { + vector param(3); + + param[0] = 3; // y + param[1] = 1; // lower + param[2] = 10; // upper + parameters.push_back(param); + log_prob.push_back(-2.302585092994045901094); // expected log_prob + + // case for lower == upper + param[0] = 5; // y + param[1] = 5; // lower + param[2] = 5; // upper + parameters.push_back(param); + log_prob.push_back(0); // expected log_prob + } + + void invalid_values(vector& /*index*/, vector& /*value*/) { + // y + + // lower + + // upper + } + + template + stan::return_type_t log_prob(const T_y& y, + const T_lower& lower, + const T_upper& upper, + const T3&, const T4&, + const T5&) { + return stan::math::discrete_range_lpmf(y, lower, upper); + } + + template + double log_prob(const T_y& y, const T_lower& lower, const T_upper& upper, + const T3&, const T4&, const T5&) { + return stan::math::discrete_range_lpmf(y, lower, upper); + } + + template + double log_prob_function(const T_y& y, const T_lower& lower, + const T_upper& upper, const T3&, const T4&, + const T5&) { + if (y < lower || y > upper) { + return stan::math::LOG_ZERO; + } + + return -log(upper - lower + 1); + } +}; diff --git a/test/unit/math/prim/prob/discrete_range_log_test.cpp b/test/unit/math/prim/prob/discrete_range_log_test.cpp new file mode 100644 index 00000000000..94472b46432 --- /dev/null +++ b/test/unit/math/prim/prob/discrete_range_log_test.cpp @@ -0,0 +1,24 @@ +#include +#include + +TEST(ProbDiscreteRange, log_matches_lpmf) { + int y = 3; + int lower = -2; + int upper = 5; + + EXPECT_FLOAT_EQ((stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); + EXPECT_FLOAT_EQ((stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); + EXPECT_FLOAT_EQ((stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); + EXPECT_FLOAT_EQ( + (stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); + EXPECT_FLOAT_EQ( + (stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); + EXPECT_FLOAT_EQ( + (stan::math::discrete_range_lpmf(y, lower, upper)), + (stan::math::discrete_range_log(y, lower, upper))); +} From f8f1b3bfee401bb7c2ded8b1e23570c5237d1f06 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Mon, 10 Feb 2020 21:18:12 +0000 Subject: [PATCH 5/6] Improve documentation and reduce whitespace --- stan/math/prim/prob/discrete_range_lpmf.hpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/stan/math/prim/prob/discrete_range_lpmf.hpp b/stan/math/prim/prob/discrete_range_lpmf.hpp index d4bfcac138d..28adbf64a63 100644 --- a/stan/math/prim/prob/discrete_range_lpmf.hpp +++ b/stan/math/prim/prob/discrete_range_lpmf.hpp @@ -16,18 +16,25 @@ namespace math { /** \ingroup prob_dists * Return the log PMF of a discrete range for the given y, lower and upper - * bound. + * bound (all integers). + * + \f{eqnarray*}{ + y &\sim& \mbox{\sf{discrete\_range}}(lower, upper) \\ + \log(p (y \, |\, lower, upper)) + &=& \log \left( \frac{1}{upper - lower + 1} \right) \\ + &=& -\log (upper - lower + 1) + \f} * * `lower` and `upper` can each be a scalar or a one-dimensional container. - * Any non-scalar inputs must be the same size. + * Any container arguments must be the same size. * * @tparam T_y type of scalar, either int or std::vector * @tparam T_lower type of lower bound, either int or std::vector * @tparam T_upper type of upper bound, either int or std::vector * - * @param y random variable - * @param lower lower bound - * @param upper upper bound + * @param y integer random variable + * @param lower integer lower bound + * @param upper integer upper bound * @return Log probability. If containers are supplied, returns the log sum * of the probabilities. * @throw std::domain_error if upper is smaller than lower. @@ -38,7 +45,6 @@ template double discrete_range_lpmf(const T_y& y, const T_lower& lower, const T_upper& upper) { static const char* function = "discrete_range_lpmf"; - using std::log; if (size_zero(y, lower, upper)) { @@ -54,8 +60,6 @@ double discrete_range_lpmf(const T_y& y, const T_lower& lower, return 0.0; } - double logp(0.0); - scalar_seq_view y_vec(y); scalar_seq_view lower_vec(lower); scalar_seq_view upper_vec(upper); @@ -78,6 +82,7 @@ double discrete_range_lpmf(const T_y& y, const T_lower& lower, log_upper_minus_lower[i] = log(upper_dbl - lower_dbl + 1); } + double logp(0.0); for (size_t n = 0; n < N; n++) { logp -= log_upper_minus_lower[n]; } From ed1a0ccf1ef505cafc506803c54276608aa27ba2 Mon Sep 17 00:00:00 2001 From: Marco Colombo Date: Tue, 11 Feb 2020 14:39:21 +0000 Subject: [PATCH 6/6] Name test correctly --- test/prob/discrete_range/discrete_range_test.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/prob/discrete_range/discrete_range_test.hpp b/test/prob/discrete_range/discrete_range_test.hpp index 36433e06489..229a40f1b56 100644 --- a/test/prob/discrete_range/discrete_range_test.hpp +++ b/test/prob/discrete_range/discrete_range_test.hpp @@ -3,7 +3,7 @@ using std::vector; -class AgradDistributionsHypergeometric : public AgradDistributionTest { +class AgradDistributionsDiscreteRange : public AgradDistributionTest { public: void valid_values(vector>& parameters, vector& log_prob) {