From 1a49f554ed29296c6463c4c8f49c4f2154661e8e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:30:09 +0000 Subject: [PATCH 01/10] Initial plan From 4898fe52cd9b5df3b0d70504fb82a8ded2c197ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:47:08 +0000 Subject: [PATCH 02/10] Return floats instead of integers in ShiftedBetaGeometricRV.rng_fn Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 6 ++---- tests/clv/test_distributions.py | 9 +++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index ed7409321..2f914b9b1 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -897,7 +897,7 @@ class ShiftedBetaGeometricRV(RandomVariable): name = "sbg" signature = "(),()->()" - dtype = "int64" + dtype = "floatX" _print_name = ("ShiftedBetaGeometric", "\\operatorname{ShiftedBetaGeometric}") @classmethod @@ -912,9 +912,7 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - # TODO: Consider returning np.float64 types instead of np.int64 - # See relevant PR comment: https://github.com/pymc-labs/pymc-marketing/pull/2010#discussion_r2444116986 - return rng.geometric(p, size=size) + return rng.geometric(p, size=size).astype(float) sbg = ShiftedBetaGeometricRV() diff --git a/tests/clv/test_distributions.py b/tests/clv/test_distributions.py index 384b45e97..1cacfb580 100644 --- a/tests/clv/test_distributions.py +++ b/tests/clv/test_distributions.py @@ -824,6 +824,15 @@ def test_random_edge_cases(self): assert np.mean(draws) >= 1 assert np.var(draws) >= 0 + def test_random_returns_float_type(self): + """Test that rng_fn returns float type, not integer type""" + dist = self.pymc_dist.dist(alpha=1.0, beta=1.0, size=10) + draws = dist.eval() + + # Verify that the dtype is float, not int + assert np.issubdtype(draws.dtype, np.floating), \ + f"Expected float dtype, but got {draws.dtype}" + def test_logp(self): alpha = pt.scalar("alpha") beta = pt.scalar("beta") From cd0a80bfb3c8a96d5befaeeb1f1b78a9c5c4599c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:52:52 +0000 Subject: [PATCH 03/10] Fix trailing whitespace in test file Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- tests/clv/test_distributions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/clv/test_distributions.py b/tests/clv/test_distributions.py index 1cacfb580..7ae5a5985 100644 --- a/tests/clv/test_distributions.py +++ b/tests/clv/test_distributions.py @@ -828,7 +828,7 @@ def test_random_returns_float_type(self): """Test that rng_fn returns float type, not integer type""" dist = self.pymc_dist.dist(alpha=1.0, beta=1.0, size=10) draws = dist.eval() - + # Verify that the dtype is float, not int assert np.issubdtype(draws.dtype, np.floating), \ f"Expected float dtype, but got {draws.dtype}" From e4d4be5fc2bf4e366ab28482e7364e8ed08a66d7 Mon Sep 17 00:00:00 2001 From: Juan Orduz Date: Tue, 4 Nov 2025 17:54:40 +0100 Subject: [PATCH 04/10] Update tests/clv/test_distributions.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tests/clv/test_distributions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/clv/test_distributions.py b/tests/clv/test_distributions.py index 7ae5a5985..635ae73c6 100644 --- a/tests/clv/test_distributions.py +++ b/tests/clv/test_distributions.py @@ -830,8 +830,9 @@ def test_random_returns_float_type(self): draws = dist.eval() # Verify that the dtype is float, not int - assert np.issubdtype(draws.dtype, np.floating), \ + assert np.issubdtype(draws.dtype, np.floating), ( f"Expected float dtype, but got {draws.dtype}" + ) def test_logp(self): alpha = pt.scalar("alpha") From 60e01165ccdaf79818169b4b3332e3f545424980 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:59:03 +0000 Subject: [PATCH 05/10] Use np.float64 instead of float for explicit dtype Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index 2f914b9b1..0c19a7641 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -912,7 +912,7 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - return rng.geometric(p, size=size).astype(float) + return rng.geometric(p, size=size).astype(np.float64) sbg = ShiftedBetaGeometricRV() From f9f7ae0c343dd35f7d880da72698ba2f069d79b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:24:13 +0000 Subject: [PATCH 06/10] Use pytensor.config.floatX instead of np.float64 to respect floatX configuration Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index 0c19a7641..ab7ff5d45 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -16,6 +16,7 @@ from functools import reduce import numpy as np +import pytensor import pytensor.tensor as pt from pymc.distributions.continuous import PositiveContinuous from pymc.distributions.dist_math import betaln, check_parameters @@ -912,7 +913,7 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - return rng.geometric(p, size=size).astype(np.float64) + return rng.geometric(p, size=size).astype(pytensor.config.floatX) sbg = ShiftedBetaGeometricRV() From 0252cd2ab30cf0148efcfb8d47c016be2abd649a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 20:08:06 +0000 Subject: [PATCH 07/10] Revert changes to restore passing tests - back to original int64 dtype Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 7 ++++--- tests/clv/test_distributions.py | 10 ---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index ab7ff5d45..ed7409321 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -16,7 +16,6 @@ from functools import reduce import numpy as np -import pytensor import pytensor.tensor as pt from pymc.distributions.continuous import PositiveContinuous from pymc.distributions.dist_math import betaln, check_parameters @@ -898,7 +897,7 @@ class ShiftedBetaGeometricRV(RandomVariable): name = "sbg" signature = "(),()->()" - dtype = "floatX" + dtype = "int64" _print_name = ("ShiftedBetaGeometric", "\\operatorname{ShiftedBetaGeometric}") @classmethod @@ -913,7 +912,9 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - return rng.geometric(p, size=size).astype(pytensor.config.floatX) + # TODO: Consider returning np.float64 types instead of np.int64 + # See relevant PR comment: https://github.com/pymc-labs/pymc-marketing/pull/2010#discussion_r2444116986 + return rng.geometric(p, size=size) sbg = ShiftedBetaGeometricRV() diff --git a/tests/clv/test_distributions.py b/tests/clv/test_distributions.py index 635ae73c6..384b45e97 100644 --- a/tests/clv/test_distributions.py +++ b/tests/clv/test_distributions.py @@ -824,16 +824,6 @@ def test_random_edge_cases(self): assert np.mean(draws) >= 1 assert np.var(draws) >= 0 - def test_random_returns_float_type(self): - """Test that rng_fn returns float type, not integer type""" - dist = self.pymc_dist.dist(alpha=1.0, beta=1.0, size=10) - draws = dist.eval() - - # Verify that the dtype is float, not int - assert np.issubdtype(draws.dtype, np.floating), ( - f"Expected float dtype, but got {draws.dtype}" - ) - def test_logp(self): alpha = pt.scalar("alpha") beta = pt.scalar("beta") From d7545312c15a3571aca96561d6807c0017000e7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 21:10:03 +0000 Subject: [PATCH 08/10] Trigger CI tests with trivial whitespace change Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index ed7409321..5a3d16dfd 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -920,6 +920,7 @@ def rng_fn(cls, rng, alpha, beta, size): sbg = ShiftedBetaGeometricRV() + class ShiftedBetaGeometric(Discrete): r"""Shifted Beta-Geometric distribution. From 1bed62a64299e89dca95195a1fe4fd40210efa43 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 4 Nov 2025 21:14:16 +0000 Subject: [PATCH 09/10] Return floats instead of integers in ShiftedBetaGeometricRV.rng_fn Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 8 +++----- tests/clv/test_distributions.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index 5a3d16dfd..ab7ff5d45 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -16,6 +16,7 @@ from functools import reduce import numpy as np +import pytensor import pytensor.tensor as pt from pymc.distributions.continuous import PositiveContinuous from pymc.distributions.dist_math import betaln, check_parameters @@ -897,7 +898,7 @@ class ShiftedBetaGeometricRV(RandomVariable): name = "sbg" signature = "(),()->()" - dtype = "int64" + dtype = "floatX" _print_name = ("ShiftedBetaGeometric", "\\operatorname{ShiftedBetaGeometric}") @classmethod @@ -912,15 +913,12 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - # TODO: Consider returning np.float64 types instead of np.int64 - # See relevant PR comment: https://github.com/pymc-labs/pymc-marketing/pull/2010#discussion_r2444116986 - return rng.geometric(p, size=size) + return rng.geometric(p, size=size).astype(pytensor.config.floatX) sbg = ShiftedBetaGeometricRV() - class ShiftedBetaGeometric(Discrete): r"""Shifted Beta-Geometric distribution. diff --git a/tests/clv/test_distributions.py b/tests/clv/test_distributions.py index 384b45e97..635ae73c6 100644 --- a/tests/clv/test_distributions.py +++ b/tests/clv/test_distributions.py @@ -824,6 +824,16 @@ def test_random_edge_cases(self): assert np.mean(draws) >= 1 assert np.var(draws) >= 0 + def test_random_returns_float_type(self): + """Test that rng_fn returns float type, not integer type""" + dist = self.pymc_dist.dist(alpha=1.0, beta=1.0, size=10) + draws = dist.eval() + + # Verify that the dtype is float, not int + assert np.issubdtype(draws.dtype, np.floating), ( + f"Expected float dtype, but got {draws.dtype}" + ) + def test_logp(self): alpha = pt.scalar("alpha") beta = pt.scalar("beta") From 204ce7bcf8711c6943f52300e103e70b5605ec5a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 5 Nov 2025 08:05:15 +0000 Subject: [PATCH 10/10] Fix: Use np.float64 instead of pytensor.config.floatX for type conversion Co-authored-by: juanitorduz <22996444+juanitorduz@users.noreply.github.com> --- pymc_marketing/clv/distributions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pymc_marketing/clv/distributions.py b/pymc_marketing/clv/distributions.py index ab7ff5d45..00b0c8d7d 100644 --- a/pymc_marketing/clv/distributions.py +++ b/pymc_marketing/clv/distributions.py @@ -16,7 +16,6 @@ from functools import reduce import numpy as np -import pytensor import pytensor.tensor as pt from pymc.distributions.continuous import PositiveContinuous from pymc.distributions.dist_math import betaln, check_parameters @@ -913,7 +912,9 @@ def rng_fn(cls, rng, alpha, beta, size): # prevent log(0) by clipping small p samples p = np.clip(p_samples, 1e-100, 1) - return rng.geometric(p, size=size).astype(pytensor.config.floatX) + # Convert to float to match dtype="floatX" specification + # Using numpy's default float type for consistency with other distributions + return rng.geometric(p, size=size).astype(np.float64) sbg = ShiftedBetaGeometricRV()