From 4068ed6a9cab4b1608828ab23b94280d4be15da6 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 12 Sep 2022 12:21:39 -0400 Subject: [PATCH 1/2] Python: Bridge -> StanModel --- python/bridgestan/__init__.py | 8 ++--- python/docs/languages/python.rst | 2 +- python/example.py | 8 ++--- python/test/test_bridgestan.py | 54 ++++++++++++++++---------------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/python/bridgestan/__init__.py b/python/bridgestan/__init__.py index ba8e8158..cb8f8c37 100644 --- a/python/bridgestan/__init__.py +++ b/python/bridgestan/__init__.py @@ -9,7 +9,7 @@ FloatArray = npt.NDArray[np.float64] double_array = ndpointer(dtype=ctypes.c_double, flags=("C_CONTIGUOUS")) -__all__ = ["Bridge"] +__all__ = ["StanModel"] def validate_readable(f: str) -> bool: @@ -23,9 +23,9 @@ def validate_readable(f: str) -> bool: raise FileNotFoundError("could not open file f =", f) -class Bridge: +class StanModel: """ - A Bridge instance encapsulates a Stan model instantiated with data + A StanModel instance encapsulates a Stan model instantiated with data and provides methods to access parameter names, transforms, log densities, gradients, and Hessians. @@ -51,7 +51,7 @@ def __init__( chain_id: int = 0, ) -> None: """ - Construct a Bridge object to a Stan model and data given + Construct a StanModel object for a Stan model and data given constructor arguments. :param model_lib: A system path to compiled shared object. diff --git a/python/docs/languages/python.rst b/python/docs/languages/python.rst index 533288f7..4e88bad4 100644 --- a/python/docs/languages/python.rst +++ b/python/docs/languages/python.rst @@ -3,5 +3,5 @@ Python Interface: bridgestan.py =============================== -.. autoclass:: bridgestan.Bridge +.. autoclass:: bridgestan.StanModel :members: diff --git a/python/example.py b/python/example.py index c4223a50..d1c3e22a 100644 --- a/python/example.py +++ b/python/example.py @@ -3,7 +3,7 @@ import numpy as np # small shim to add dims(), required by MCMC impl -class BridgeDims(bs.Bridge): +class StaModelDims(bs.StanModel): def dims(self) -> int: return self.param_unc_num() @@ -13,7 +13,7 @@ def dims(self) -> int: bernoulli_lib = "./stan/bernoulli/bernoulli_model.so" bernoulli_data = "./stan/bernoulli/bernoulli.data.json" -smb = BridgeDims(bernoulli_lib, bernoulli_data) +smb = StaModelDims(bernoulli_lib, bernoulli_data) x = np.random.uniform(size = smb.dims()) q = np.log(x / (1 - x)) # unconstrained scale @@ -31,7 +31,7 @@ def dims(self) -> int: multi_lib = "./stan/multi/multi_model.so" multi_data = "./stan/multi/multi.data.json" -smm = BridgeDims(multi_lib, multi_data) +smm = StaModelDims(multi_lib, multi_data) x = np.random.uniform(size = smm.param_num()) print("log_density and gradient of Multivariate Gaussian model:") @@ -43,7 +43,7 @@ def dims(self) -> int: # HMC -model = BridgeDims(multi_lib, multi_data, seed=1234) +model = StaModelDims(multi_lib, multi_data, seed=1234) stepsize = 0.25 steps = 10 diff --git a/python/test/test_bridgestan.py b/python/test/test_bridgestan.py index 16713845..6a9e281c 100644 --- a/python/test/test_bridgestan.py +++ b/python/test/test_bridgestan.py @@ -9,41 +9,41 @@ def test_constructor(): # test empty data std_so = "../stan/stdnormal/stdnormal_model.so" - b1 = bs.Bridge(std_so) + b1 = bs.StanModel(std_so) np.testing.assert_allclose(bool(b1), True) # test load data bernoulli_so = "../stan/bernoulli/bernoulli_model.so" bernoulli_data = "../stan/bernoulli/bernoulli.data.json" - b2 = bs.Bridge(bernoulli_so, bernoulli_data) + b2 = bs.StanModel(bernoulli_so, bernoulli_data) np.testing.assert_allclose(bool(b2), True) # test missing so file with np.testing.assert_raises(FileNotFoundError): - b3 = bs.Bridge("nope, not going to find it") + b3 = bs.StanModel("nope, not going to find it") # test missing data file with np.testing.assert_raises(FileNotFoundError): - b3 = bs.Bridge(bernoulli_so, "nope, not going to find it") + b3 = bs.StanModel(bernoulli_so, "nope, not going to find it") # test data load exception throw_data_so = "../stan/throw_data/throw_data_model.so" print("construct() EXCEPTION MSG ON NEXT LINE IS NOT AN ERROR") with np.testing.assert_raises(RuntimeError): - b4 = bs.Bridge(throw_data_so) + b4 = bs.StanModel(throw_data_so) # TODO(carpenter): test get right error message on stderr def test_name(): std_so = "../stan/stdnormal/stdnormal_model.so" - b = bs.Bridge(std_so) + b = bs.StanModel(std_so) np.testing.assert_equal("stdnormal_model", b.name()) def test_param_num(): full_so = "../stan/full/full_model.so" - b = bs.Bridge(full_so) + b = bs.StanModel(full_so) np.testing.assert_equal(1, b.param_num()) np.testing.assert_equal(1, b.param_num(include_tp=False)) np.testing.assert_equal(1, b.param_num(include_gq=False)) @@ -57,14 +57,14 @@ def test_param_num(): def test_param_unc_num(): simplex_so = "../stan/simplex/simplex_model.so" - b = bs.Bridge(simplex_so) + b = bs.StanModel(simplex_so) np.testing.assert_equal(5, b.param_num()) np.testing.assert_equal(4, b.param_unc_num()) def test_param_names(): matrix_so = "../stan/matrix/matrix_model.so" - b = bs.Bridge(matrix_so) + b = bs.StanModel(matrix_so) np.testing.assert_array_equal( ["A.1.1", "A.2.1", "A.3.1", "A.1.2", "A.2.2", "A.3.2"], b.param_names() ) @@ -144,13 +144,13 @@ def test_param_names(): def test_param_unc_names(): matrix_so = "../stan/matrix/matrix_model.so" - b1 = bs.Bridge(matrix_so) + b1 = bs.StanModel(matrix_so) np.testing.assert_array_equal( ["A.1.1", "A.2.1", "A.3.1", "A.1.2", "A.2.2", "A.3.2"], b1.param_unc_names() ) simplex_so = "../stan/simplex/simplex_model.so" - b2 = bs.Bridge(simplex_so) + b2 = bs.StanModel(simplex_so) np.testing.assert_array_equal( ["theta.1", "theta.2", "theta.3", "theta.4"], b2.param_unc_names() ) @@ -168,7 +168,7 @@ def cov_constrain(v, D): def test_param_constrain(): fr_gaussian_so = "../stan/fr_gaussian/fr_gaussian_model.so" fr_gaussian_data = "../stan/fr_gaussian/fr_gaussian.data.json" - bridge = bs.Bridge(fr_gaussian_so, fr_gaussian_data) + bridge = bs.StanModel(fr_gaussian_so, fr_gaussian_data) D = 4 size = 16 @@ -193,7 +193,7 @@ def test_param_constrain(): np.testing.assert_allclose(B_expected, B) full_so = "../stan/full/full_model.so" - bridge2 = bs.Bridge(full_so) + bridge2 = bs.StanModel(full_so) b2 = bridge.param_constrain(a) np.testing.assert_equal(1, bridge2.param_constrain(a).size) @@ -214,7 +214,7 @@ def test_param_constrain(): # exception handling test in transformed parameters/model (compiled same way) throw_tp_so = "../stan/throw_tp/throw_tp_model.so" - bridge2 = bs.Bridge(throw_tp_so) + bridge2 = bs.StanModel(throw_tp_so) y = np.array(np.random.uniform(1)) bridge2.param_constrain(y, include_tp=False) @@ -223,7 +223,7 @@ def test_param_constrain(): bridge2.param_constrain(y, include_tp=True) throw_gq_so = "../stan/throw_gq/throw_gq_model.so" - bridge3 = bs.Bridge(throw_gq_so) + bridge3 = bs.StanModel(throw_gq_so) bridge3.param_constrain(y, include_gq=False) print("param_constrain() EXCEPTION MSG ON NEXT LINE IS NOT AN ERROR") with np.testing.assert_raises(RuntimeError): @@ -233,7 +233,7 @@ def test_param_constrain(): def test_param_unconstrain(): fr_gaussian_so = "../stan/fr_gaussian/fr_gaussian_model.so" fr_gaussian_data = "../stan/fr_gaussian/fr_gaussian.data.json" - bridge = bs.Bridge(fr_gaussian_so, fr_gaussian_data) + bridge = bs.StanModel(fr_gaussian_so, fr_gaussian_data) unc_size = 10 a = np.random.normal(size=unc_size) @@ -252,7 +252,7 @@ def test_param_unconstrain(): def test_param_unconstrain_json(): gaussian_so = "../stan/gaussian/gaussian_model.so" gaussian_data = "../stan/gaussian/gaussian.data.json" - bridge = bs.Bridge(gaussian_so, gaussian_data) + bridge = bs.StanModel(gaussian_so, gaussian_data) # theta = np.array([0.2, 1.9]) theta_unc = np.array([0.2, np.log(1.9)]) @@ -284,7 +284,7 @@ def _bernoulli_jacobian(y, p): def test_log_density(): bernoulli_so = "../stan/bernoulli/bernoulli_model.so" bernoulli_data = "../stan/bernoulli/bernoulli.data.json" - bridge = bs.Bridge(bernoulli_so, bernoulli_data) + bridge = bs.StanModel(bernoulli_so, bernoulli_data) y = np.asarray([0, 1, 0, 0, 0, 0, 0, 0, 0, 1]) for _ in range(2): x = np.random.uniform(size=bridge.param_unc_num()) @@ -299,7 +299,7 @@ def test_log_density(): np.testing.assert_allclose(lp4, _bernoulli(y, x)) throw_lp_so = "../stan/throw_lp/throw_lp_model.so" - bridge2 = bs.Bridge(throw_lp_so) + bridge2 = bs.StanModel(throw_lp_so) y2 = np.array(np.random.uniform(1)) print("log_density() EXCEPTION MSG ON NEXT LINE IS NOT AN ERROR") with np.testing.assert_raises(RuntimeError): @@ -328,7 +328,7 @@ def _grad_jacobian_true(y_unc): return 1 jacobian_so = "../stan/jacobian/jacobian_model.so" - bridge = bs.Bridge(jacobian_so) + bridge = bs.StanModel(jacobian_so) y = np.abs(np.random.normal(1)) y_unc = np.log(y) @@ -418,7 +418,7 @@ def _hess_jacobian_true(y_unc): return 0 jacobian_so = "../stan/jacobian/jacobian_model.so" - bridge = bs.Bridge(jacobian_so) + bridge = bs.StanModel(jacobian_so) # test value, gradient, hessian, all combos +/- propto, +/- jacobian y = np.abs(np.random.normal(1)) @@ -494,7 +494,7 @@ def _hess_jacobian_true(y_unc): # test with 5 x 5 Hessian simple_so = "../stan/simple/simple_model.so" simple_data = "../stan/simple/simple.data.json" - bridge2 = bs.Bridge(simple_so, simple_data) + bridge2 = bs.StanModel(simple_so, simple_data) D = 5 y = np.random.uniform(size=D) @@ -506,7 +506,7 @@ def _hess_jacobian_true(y_unc): def test_out_behavior(): bernoulli_so = "../stan/bernoulli/bernoulli_model.so" bernoulli_data = "../stan/bernoulli/bernoulli.data.json" - smb = bs.Bridge(bernoulli_so, bernoulli_data) + smb = bs.StanModel(bernoulli_so, bernoulli_data) grads = [] for _ in range(2): @@ -542,7 +542,7 @@ def _bernoulli(y, p): bernoulli_so = "../stan/bernoulli/bernoulli_model.so" bernoulli_data = "../stan/bernoulli/bernoulli.data.json" - smb = bs.Bridge(bernoulli_so, bernoulli_data) + smb = bs.StanModel(bernoulli_so, bernoulli_data) np.testing.assert_string_equal(smb.name(), "bernoulli_model") np.testing.assert_allclose(smb.param_unc_num(), 1) np.testing.assert_allclose(smb.param_num(include_tp=False, include_gq=False), 1) @@ -568,7 +568,7 @@ def _grad_multi(x): multi_so = "../stan/multi/multi_model.so" multi_data = "../stan/multi/multi.data.json" - smm = bs.Bridge(multi_so, multi_data) + smm = bs.StanModel(multi_so, multi_data) x = np.random.normal(size=smm.param_unc_num()) logdensity, grad = smm.log_density_gradient(x) np.testing.assert_allclose(logdensity, _multi(x)) @@ -580,7 +580,7 @@ def test_gaussian(): lib = "../stan/gaussian/gaussian_model.so" data = "../stan/gaussian/gaussian.data.json" - model = bs.Bridge(lib, data) + model = bs.StanModel(lib, data) theta = np.array([0.2, 1.9]) theta_unc = np.array([0.2, np.log(1.9)]) @@ -607,7 +607,7 @@ def cov_constrain(v, D): lib = "../stan/fr_gaussian/fr_gaussian_model.so" data = "../stan/fr_gaussian/fr_gaussian.data.json" - model = bs.Bridge(lib, data) + model = bs.StanModel(lib, data) size = 16 unc_size = 10 From 4a52572c2729fa8d8c6c1fa878447173f8717e0e Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 12 Sep 2022 12:22:52 -0400 Subject: [PATCH 2/2] R: Bridge -> StanModel --- R/bridgestan.R | 2 +- R/tests/test_bridgestan.R | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/R/bridgestan.R b/R/bridgestan.R index 01fd5e97..efa8a952 100755 --- a/R/bridgestan.R +++ b/R/bridgestan.R @@ -1,5 +1,5 @@ -Bridge <- R6::R6Class("Bridge", +StanModel <- R6::R6Class("StanModel", public = list( initialize = function(lib, data, rng_seed, chain_id) { if (.Platform$OS.type == "windows"){ diff --git a/R/tests/test_bridgestan.R b/R/tests/test_bridgestan.R index 5f3be3a3..781f2f57 100644 --- a/R/tests/test_bridgestan.R +++ b/R/tests/test_bridgestan.R @@ -1,7 +1,7 @@ source("../bridgestan.R") library(testthat) -simple <- Bridge$new("../../stan/simple/simple_model.so", "../../stan/simple/simple.data.json", 1234, 0) +simple <- StanModel$new("../../stan/simple/simple_model.so", "../../stan/simple/simple.data.json", 1234, 0) test_that("simple_model name is correct", { expect_identical(simple$name(), "simple_model") }) @@ -26,9 +26,7 @@ test_that("simple_model Hessian is -I",{ }) -bernoulli <- Bridge$new("../../stan/bernoulli/bernoulli_model.so", "../../stan/bernoulli/bernoulli.data.json", 1234, 0) - - +bernoulli <- StanModel$new("../../stan/bernoulli/bernoulli_model.so", "../../stan/bernoulli/bernoulli.data.json", 1234, 0) test_that("loading another library didn't break prior ones", { if (.Platform$OS.type == "windows"){