Skip to content
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

Bugfix/2241 rng model ctor #2313

Merged
merged 21 commits into from
Jun 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2c20c3d
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris Apr 14, 2017
1685ba9
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris Apr 14, 2017
64705bd
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris May 7, 2017
47cf70d
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris May 9, 2017
807ac54
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris May 12, 2017
0795741
Merge branch 'develop' of https://github.com/stan-dev/stan into develop
mitzimorris May 16, 2017
7100a47
modified generated code, model header, create_rng util
mitzimorris May 23, 2017
7a0b7b8
test file
mitzimorris May 23, 2017
d6cf9d6
unit tests test 3-arg model constructor, rng init
mitzimorris May 23, 2017
0ae3495
cpplint fix
mitzimorris May 23, 2017
65f3092
disambiguate model constructor calls in unit tests
mitzimorris May 23, 2017
161be44
add stmt to suppress compiler warnings
mitzimorris May 23, 2017
2d10f89
changes per code review; models with output stream ptr 0
mitzimorris May 24, 2017
cc9e4fb
merge conflicts and tests for rng constructor
Jun 12, 2017
e1d3104
cleaned up doxygen gripe for rng ctor
Jun 12, 2017
da67dd5
Merge branch 'bugfix/2241-rng-model-ctor' of https://github.com/stan-…
mitzimorris Jun 12, 2017
c4e7bba
relaxed condition on unit test for Gauss3D
mitzimorris Jun 12, 2017
501d0ce
fixed unit test
mitzimorris Jun 13, 2017
374ee14
fixed unit tests
mitzimorris Jun 13, 2017
807a532
removed spurious tests
mitzimorris Jun 13, 2017
dc6d489
fixed makefile for tests
mitzimorris Jun 13, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions make/tests
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ src/test/unit/services/sample/hmc_static_dense_e_test.cpp : src/test/test-models
src/test/unit/services/sample/hmc_static_diag_e_test.cpp : src/test/test-models/good/optimization/rosenbrock.hpp
src/test/unit/services/sample/hmc_static_diag_e_adapt_test.cpp : src/test/test-models/good/optimization/rosenbrock.hpp
src/test/unit/services/sample/hmc_static_unit_e_test.cpp : src/test/test-models/good/optimization/rosenbrock.hpp
src/test/unit/services/sample/hmc_static_unit_e_adapt_test.cpp : src/test/test-models/good/optimization/rosenbrock.hpp
src/test/unit/services/sample/hmc_nuts_dense_inv_metric_test.cpp : src/test/test-models/good/mcmc/hmc/common/gauss3D.hpp
src/test/unit/services/sample/hmc_nuts_diag_inv_metric_test.cpp : src/test/test-models/good/mcmc/hmc/common/gauss3D.hpp
src/test/unit/services/sample/hmc_static_dense_inv_metric_test.cpp : src/test/test-models/good/mcmc/hmc/common/gauss3D.hpp
Expand Down
21 changes: 11 additions & 10 deletions src/stan/lang/generator/generate_constructor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,28 @@ namespace stan {
*/
void generate_constructor(const program& prog,
const std::string& model_name, std::ostream& o) {
// constructor without RNG or template parameter
// constructor without seed or template parameter
o << INDENT << model_name << "(stan::io::var_context& context__," << EOL;
o << INDENT << " std::ostream* pstream__ = 0)" << EOL;
o << INDENT2 << ": prob_grad(0) {" << EOL;
o << INDENT2 << "typedef boost::ecuyer1988 rng_t;" << EOL;
o << INDENT2 << "rng_t base_rng(0); // 0 seed default" << EOL;
o << INDENT2 << "ctor_body(context__, base_rng, pstream__);" << EOL;
o << INDENT2 << "ctor_body(context__, 0, pstream__);" << EOL;
o << INDENT << "}" << EOL2;
// constructor with specified RNG
o << INDENT << "template <class RNG>" << EOL;
// constructor with specified seed
o << INDENT << model_name << "(stan::io::var_context& context__," << EOL;
o << INDENT << " RNG& base_rng__," << EOL;
o << INDENT << " unsigned int random_seed__," << EOL;
o << INDENT << " std::ostream* pstream__ = 0)" << EOL;
o << INDENT2 << ": prob_grad(0) {" << EOL;
o << INDENT2 << "ctor_body(context__, base_rng__, pstream__);" << EOL;
o << INDENT2 << "ctor_body(context__, random_seed__, pstream__);" << EOL;
o << INDENT << "}" << EOL2;
// body of constructor now in function
o << INDENT << "template <class RNG>" << EOL;
o << INDENT << "void ctor_body(stan::io::var_context& context__," << EOL;
o << INDENT << " RNG& base_rng__," << EOL;
o << INDENT << " unsigned int random_seed__," << EOL;
o << INDENT << " std::ostream* pstream__) {" << EOL;
o << INDENT2 << "boost::ecuyer1988 base_rng__ =" << EOL;
o << INDENT2 << " stan::services::util::create_rng(random_seed__, 0);"
<< EOL;
o << INDENT2 << "(void) base_rng__; // suppress unused var warning"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does base_rng__ end up getting used, out of curiosity? Can the user refer to base_rng__ or something in their transformed data section?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user can call _rng functions in transformed data.

<< EOL2;
o << INDENT2 << "current_statement_begin__ = -1;" << EOL2;
o << INDENT2 << "static const char* function__ = \""
<< model_name << "_namespace::" << model_name << "\";" << EOL;
Expand Down
1 change: 1 addition & 0 deletions src/stan/model/model_header.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <stan/lang/rethrow_located.hpp>
#include <stan/model/prob_grad.hpp>
#include <stan/model/indexing.hpp>
#include <stan/services/util/create_rng.hpp>

#include <boost/exception/all.hpp>
#include <boost/random/additive_combine.hpp>
Expand Down
24 changes: 14 additions & 10 deletions src/stan/services/util/create_rng.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ namespace stan {

/**
* Creates a pseudo random number generator from a random seed
* and a chain.
* and a chain id by initializing the PRNG with the seed and
* then advancing past pow(2, 50) times the chain ID draws to
* ensure different chains sample from different segments of the
* pseudo random number sequence.
*
* @param[in] random_seed the random seed
* Chain IDs should be kept to larger values than one to ensure
* that the draws used to initialized transformed data are not
* duplicated.
*
* @param[in] seed the random seed
* @param[in] chain the chain id
* @return a boost::ecuyer1988 instance
*/
boost::ecuyer1988 create_rng(unsigned int random_seed,
boost::ecuyer1988 create_rng(unsigned int seed,
unsigned int chain) {
boost::ecuyer1988 rng(random_seed);

// Advance generator to avoid process conflicts
static boost::uintmax_t DISCARD_STRIDE
= static_cast<boost::uintmax_t>(1) << 50;
rng.discard(DISCARD_STRIDE * (chain - 1));

using boost::uintmax_t;
static uintmax_t DISCARD_STRIDE = static_cast<uintmax_t>(1) << 50;
boost::ecuyer1988 rng(seed);
rng.discard(DISCARD_STRIDE * chain);
return rng;
}

Expand Down
20 changes: 20 additions & 0 deletions src/test/test-models/good/rng_transformed_data.stan
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
data {
int<lower=0> N;
}
transformed data {
vector[N] y;
for (n in 1:N)
y[n] = normal_rng(0, 1);
print(y);
}
parameters {
real mu;
real<lower = 0> sigma;
}
model {
y ~ normal(mu, sigma);
}
generated quantities {
real mean_y = mean(y);
real sd_y = sd(y);
}
4 changes: 2 additions & 2 deletions src/test/unit/io/random_var_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class random_var_context : public testing::Test {
public:
random_var_context()
: empty_context(),
model(empty_context, 0),
model(empty_context, static_cast<std::stringstream*>(0)),
rng(0) { }

stan::io::empty_var_context empty_context;
Expand All @@ -34,7 +34,7 @@ TEST_F(random_var_context, vals_r) {
EXPECT_GT(vals_r[0], -10);
EXPECT_LT(vals_r[0], 10);
EXPECT_GT(vals_r[1], -100);
EXPECT_LT(vals_r[1], 10);
EXPECT_LT(vals_r[1], 10);
}

TEST_F(random_var_context, dims_r) {
Expand Down
5 changes: 3 additions & 2 deletions src/test/unit/mcmc/hmc/hamiltonians/base_hamiltonian_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ TEST(BaseHamiltonian, streams) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

EXPECT_NO_THROW(funnel_model_namespace::funnel_model model(data_var_context, 0));

EXPECT_NO_THROW(funnel_model_namespace::funnel_model
model(data_var_context, 0,
static_cast<std::stringstream*>(0)));
std::stringstream output;
EXPECT_NO_THROW(funnel_model_namespace::funnel_model model(data_var_context, &output));
EXPECT_EQ("", output.str());
Expand Down
2 changes: 1 addition & 1 deletion src/test/unit/model/finite_diff_grad_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ TEST(ModelUtil, streams) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

stan_model model(data_var_context, 0);
stan_model model(data_var_context, static_cast<std::stringstream*>(0));
std::vector<double> params_r(1);
std::vector<int> params_i(0);
std::vector<double> gradient;
Expand Down
4 changes: 2 additions & 2 deletions src/test/unit/model/grad_hess_log_prob_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ TEST(ModelUtil, grad_hess_log_prob) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

stan_model model(data_var_context, 0);
stan_model model(data_var_context, static_cast<std::stringstream*>(0));
std::vector<double> params_r(1);
std::vector<int> params_i(0);
std::vector<double> gradient;

std::stringstream out;

try {
std::vector<double> hessian;
stan::model::grad_hess_log_prob<true, true, stan_model>(model, params_r, params_i, gradient, hessian, 0);
Expand Down
3 changes: 2 additions & 1 deletion src/test/unit/model/log_prob_grad_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ TEST(ModelUtil, streams) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

stan_model model(data_var_context, 0);

stan_model model(data_var_context, static_cast<std::stringstream*>(0));
std::vector<double> params_r(1);
std::vector<int> params_i(0);
std::vector<double> gradient;
Expand Down
17 changes: 11 additions & 6 deletions src/test/unit/model/log_prob_propto_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,24 @@ TEST(ModelUtil, streams) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

stan_model model(data_var_context, 0);

stan_model model(data_var_context, static_cast<std::stringstream*>(0));
std::vector<double> params_r(1);
std::vector<int> params_i(0);
std::vector<double> gradient;

std::stringstream out;

try {
stan::model::log_prob_propto<true, stan_model>(model, params_r, params_i, 0);
stan::model::log_prob_propto<false, stan_model>(model, params_r, params_i, 0);
stan::model::log_prob_propto<true, stan_model>(model,
params_r, params_i, 0);
stan::model::log_prob_propto<false, stan_model>(model,
params_r, params_i, 0);
out.str("");
stan::model::log_prob_propto<true, stan_model>(model, params_r, params_i, &out);
stan::model::log_prob_propto<false, stan_model>(model, params_r, params_i, &out);
stan::model::log_prob_propto<true, stan_model>(model,
params_r, params_i, &out);
stan::model::log_prob_propto<false, stan_model>(model,
params_r, params_i, &out);
EXPECT_EQ("", out.str());
} catch (...) {
FAIL() << "log_prob_propto";
Expand All @@ -41,7 +46,7 @@ TEST(ModelUtil, streams) {
FAIL() << "log_prob_propto";
}


stan::test::reset_std_streams();
EXPECT_EQ("", stan::test::cout_ss.str());
EXPECT_EQ("", stan::test::cerr_ss.str());
Expand Down
2 changes: 1 addition & 1 deletion src/test/unit/model/test_gradients_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ TEST(ModelUtil, streams) {
stan::io::dump data_var_context(data_stream);
data_stream.close();

stan_model model(data_var_context, 0);
stan_model model(data_var_context, static_cast<std::stringstream*>(0));
std::vector<double> params_r(1);
std::vector<int> params_i(0);
std::vector<double> gradient;
Expand Down
22 changes: 3 additions & 19 deletions src/test/unit/services/sample/hmc_nuts_dense_inv_metric_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, ident_adapt_250) {
stan::test::unit::instrumented_interrupt interrupt;
EXPECT_EQ(interrupt.call_count(), 0);

// run sampler with ident Euclidean metric, 250 warmups
// run sampler with ident Euclidean metric
int return_code =
stan::services::sample::hmc_nuts_dense_e_adapt(model,
context,
Expand Down Expand Up @@ -121,22 +121,6 @@ TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, ident_adapt_250) {
parameter,
diagnostic);
EXPECT_EQ(0, return_code);

// result of running adaptive sampler w/ ident Euclidean metric:
// 1.21622, -0.0271004, 0.00515814
// -0.0271004, 0.59758, -0.0153581
// 0.00515814, -0.0153581, 0.863086
std::vector<double> dense_vals;
dense_vals.push_back(1.21622);
dense_vals.push_back(-0.0271004);
dense_vals.push_back(0.00515814);
dense_vals.push_back(-0.0271004);
dense_vals.push_back(0.59758);
dense_vals.push_back(-0.0153581);
dense_vals.push_back(0.00515814);
dense_vals.push_back(-0.0153581);
dense_vals.push_back(0.863086);
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.2);
}

TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, use_metric_no_adapt) {
Expand Down Expand Up @@ -188,7 +172,7 @@ TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, use_metric_no_adapt) {

std::vector<double> dense_vals(9);
dense_vals = inv_metric.vals_r("inv_metric");
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.2);
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.4);
}

TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, use_metric_skip_adapt) {
Expand Down Expand Up @@ -255,5 +239,5 @@ TEST_F(ServicesSampleHmcNutsDenseEMassMatrix, use_metric_skip_adapt) {

std::vector<double> dense_vals(9);
dense_vals = inv_metric.vals_r("inv_metric");
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.2);
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.4);
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,6 @@ TEST_F(ServicesSampleHmcNutsDiagEMassMatrix, unit_e_adapt_250) {
parameter,
diagnostic);
EXPECT_EQ(0, return_code);

// check returned Euclidean metric
// captured result of running sampler w/ unit_e Euclidean metric, reported output:
// 0.929061, 0.823316, 0.643094
std::vector<double> diag_vals;
diag_vals.push_back(0.929061);
diag_vals.push_back(0.823316);
diag_vals.push_back(0.643094);
stan::test::unit::check_adaptation(3, diag_vals, parameter, 0.2);
}

TEST_F(ServicesSampleHmcNutsDiagEMassMatrix, use_metric_no_adapt) {
Expand Down
17 changes: 0 additions & 17 deletions src/test/unit/services/sample/hmc_static_dense_inv_metric_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,23 +121,6 @@ TEST_F(ServicesSampleHmcStaticDenseEMassMatrix, unit_e_adapt_250) {
parameter,
diagnostic);
EXPECT_EQ(0, return_code);


// brute force output match with result:
// 0.926739, 0.0734898, -0.12395
// 0.0734898, 0.876038, -0.051543
// -0.12395, -0.051543, 0.8274
std::vector<double> dense_vals;
dense_vals.push_back(0.926739);
dense_vals.push_back(0.0734898);
dense_vals.push_back(-0.12395);
dense_vals.push_back(0.0734898);
dense_vals.push_back(0.876038);
dense_vals.push_back(-0.051543);
dense_vals.push_back(-0.12395);
dense_vals.push_back(-0.051543);
dense_vals.push_back(0.8274);
stan::test::unit::check_adaptation(3, 3, dense_vals, parameter, 0.2);
}

TEST_F(ServicesSampleHmcStaticDenseEMassMatrix, use_metric_no_adapt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,6 @@ TEST_F(ServicesSampleHmcStaticDiagEMassMatrix, unit_e_adapt_250) {
parameter,
diagnostic);
EXPECT_EQ(0, return_code);

// check returned Euclidean metric
// captured result of running sampler w/ unit_e Euclidean metric, reported output:
// 1.19161, 0.710345, 0.793847
std::vector<double> diag_vals;
diag_vals.push_back(1.19161);
diag_vals.push_back(0.710345);
diag_vals.push_back(0.793847);
stan::test::unit::check_adaptation(3, diag_vals, parameter, 0.2);
}

TEST_F(ServicesSampleHmcStaticDiagEMassMatrix, use_metric_no_adapt) {
Expand Down
15 changes: 12 additions & 3 deletions src/test/unit/services/util/create_rng_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,27 @@
TEST(rng, initialize_with_seed) {
boost::ecuyer1988 rng1 = stan::services::util::create_rng(0, 1);
boost::ecuyer1988 rng2 = stan::services::util::create_rng(0, 1);

EXPECT_EQ(rng1, rng2);

rng2();
rng2(); // generate a random number
EXPECT_NE(rng1, rng2);
}

TEST(rng, initialize_with_id) {
boost::ecuyer1988 rng1 = stan::services::util::create_rng(0, 1);

for (unsigned int n = 2; n < 20; n++) {
boost::ecuyer1988 rng2 = stan::services::util::create_rng(0, n);
EXPECT_NE(rng1, rng2);
}
}

// warning---this will reuse draws from transformed data
// if we initialize with zero
TEST(rng, initialize_with_zero) {
boost::ecuyer1988 rng1 = stan::services::util::create_rng(0, 0);
boost::ecuyer1988 rng2 = stan::services::util::create_rng(0, 0);
EXPECT_EQ(rng1, rng2);

rng2();
EXPECT_NE(rng1, rng2);
}
7 changes: 5 additions & 2 deletions src/test/unit/services/util/initialize_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@
class ServicesUtilInitialize : public testing::Test {
public:
ServicesUtilInitialize()
: model(empty_context, &model_ss),
: model(empty_context, 12345, &model_ss),
message(message_ss),
rng(stan::services::util::create_rng(0, 1)) {}

stan_model model;
stan::io::empty_var_context empty_context;
std::stringstream model_ss;
stan_model model;
std::stringstream message_ss;
stan::callbacks::stream_writer message;
stan::test::unit::instrumented_logger logger;
stan::test::unit::instrumented_writer init;
boost::ecuyer1988 rng;
Expand Down
4 changes: 2 additions & 2 deletions src/test/unit/variational/hier_logistic_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ class advi_test : public ::testing::Test {
stan::io::dump data_var_context(data_stream);
data_stream.close();

model_ = new stan_model(data_var_context, &model_stream_);
model_null_stream_ = new stan_model(data_var_context, NULL);
model_ = new stan_model(data_var_context, 0, &model_stream_);
model_null_stream_ = new stan_model(data_var_context, 0, NULL);

base_rng_.seed(0);
cont_params_ = Eigen::VectorXd::Zero(model_->num_params_r());
Expand Down