diff --git a/pymc/distributions/continuous.py b/pymc/distributions/continuous.py index 91d219350..fe881983e 100644 --- a/pymc/distributions/continuous.py +++ b/pymc/distributions/continuous.py @@ -1347,15 +1347,24 @@ class Exponential(PositiveContinuous): ---------- lam : tensor_like of float Rate or inverse scale (``lam`` > 0). + scale: tensor_like of float + Alternative parameter (scale = 1/lam). """ rv_op = exponential @classmethod - def dist(cls, lam: DIST_PARAMETER_TYPES, *args, **kwargs): - lam = pt.as_tensor_variable(floatX(lam)) + def dist(cls, lam=None, scale=None, *args, **kwargs): + if lam is not None and scale is not None: + raise ValueError("Incompatible parametrization. Can't specify both lam and scale.") + elif lam is None and scale is None: + raise ValueError("Incompatible parametrization. Must specify either lam or scale.") + + if scale is None: + scale = pt.reciprocal(lam) + scale = pt.as_tensor_variable(floatX(scale)) # PyTensor exponential op is parametrized in terms of mu (1/lam) - return super().dist([pt.reciprocal(lam)], **kwargs) + return super().dist([scale], **kwargs) def moment(rv, size, mu): if not rv_size_is_none(size): diff --git a/tests/distributions/test_continuous.py b/tests/distributions/test_continuous.py index 1f673eb28..7ca5eb53a 100644 --- a/tests/distributions/test_continuous.py +++ b/tests/distributions/test_continuous.py @@ -444,6 +444,15 @@ def test_exponential(self): lambda q, lam: st.expon.ppf(q, loc=0, scale=1 / lam), ) + def test_exponential_wrong_arguments(self): + msg = "Incompatible parametrization. Can't specify both lam and scale" + with pytest.raises(ValueError, match=msg): + pm.Exponential.dist(lam=0.5, scale=5) + + msg = "Incompatible parametrization. Must specify either lam or scale" + with pytest.raises(ValueError, match=msg): + pm.Exponential.dist() + def test_laplace(self): check_logp( pm.Laplace, @@ -2091,6 +2100,13 @@ class TestExponential(BaseTestDistributionRandom): ] +class TestExponentialScale(BaseTestDistributionRandom): + pymc_dist = pm.Exponential + pymc_dist_params = {"scale": 5.0} + expected_rv_op_params = {"mu": pymc_dist_params["scale"]} + checks_to_run = ["check_pymc_params_match_rv_op"] + + class TestCauchy(BaseTestDistributionRandom): pymc_dist = pm.Cauchy pymc_dist_params = {"alpha": 2.0, "beta": 5.0}