Skip to content

Commit f45ba61

Browse files
committed
Fix support for all vector signatures in poisson-binomial
1 parent 27116c0 commit f45ba61

2 files changed

Lines changed: 35 additions & 25 deletions

File tree

stan/math/prim/fun/poisson_binomial_log_probs.hpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ namespace math {
2222
* @return the last row of the computed log probability matrix
2323
*/
2424
template <typename T_theta, typename T_scalar = scalar_type_t<T_theta>,
25-
require_eigen_vector_t<T_theta>* = nullptr>
26-
plain_type_t<T_theta> poisson_binomial_log_probs(int y, const T_theta& theta) {
25+
require_vector_t<T_theta>* = nullptr>
26+
Eigen::Matrix<T_scalar, 1, -1>
27+
poisson_binomial_log_probs(int y, const T_theta& theta) {
2728
int size_theta = theta.size();
2829
plain_type_t<T_theta> log_theta = log(theta);
2930
plain_type_t<T_theta> log1m_theta = log1m(theta);
@@ -39,34 +40,18 @@ plain_type_t<T_theta> poisson_binomial_log_probs(int y, const T_theta& theta) {
3940

4041
// 0 < j < i successes in i trials
4142
for (int j = 0; j < std::min(y, i); ++j) {
42-
alpha(i + 1, j + 1) = log_sum_exp(alpha(i, j) + log_theta[i],
43-
alpha(i, j + 1) + log1m_theta[i]);
43+
alpha(i + 1, j + 1) = log_mix(theta[i], alpha(i, j), alpha(i, j + 1));
4444
}
4545

4646
// i successes in i trials
4747
if (i < y) {
48-
alpha(i + 1, i + 1) = alpha(i, i) + log_theta(i);
48+
alpha(i + 1, i + 1) = alpha(i, i) + log_theta[i];
4949
}
5050
}
5151

5252
return alpha.row(size_theta);
5353
}
5454

55-
template <typename T_y, typename T_theta, require_vt_integral<T_y>* = nullptr>
56-
auto poisson_binomial_log_probs(const T_y& y, const T_theta& theta) {
57-
using T_scalar = scalar_type_t<T_theta>;
58-
size_t max_sizes = std::max(stan::math::size(y), size_mvt(theta));
59-
std::vector<Eigen::Matrix<T_scalar, Eigen::Dynamic, 1>> result(max_sizes);
60-
scalar_seq_view<T_y> y_vec(y);
61-
vector_seq_view<T_theta> theta_vec(theta);
62-
63-
for (size_t i = 0; i < max_sizes; ++i) {
64-
result[i] = poisson_binomial_log_probs(y_vec[i], theta_vec[i]);
65-
}
66-
67-
return result;
68-
}
69-
7055
} // namespace math
7156
} // namespace stan
7257
#endif

test/unit/math/prim/prob/poisson_binomial_test.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,39 @@
66
#include <vector>
77

88
TEST(ProbDistributionsPoissonBinomial, lpmf_length_0_length_1) {
9+
using stan::math::poisson_binomial_lpmf;
10+
using stan::math::to_row_vector;
11+
using stan::math::to_array_1d;
12+
913
Eigen::VectorXd v0(0);
1014
Eigen::VectorXd v1(1);
1115
v1 << 0.4;
1216

13-
EXPECT_FLOAT_EQ(stan::math::poisson_binomial_lpmf(0, v0), 0.0);
14-
EXPECT_FLOAT_EQ(stan::math::poisson_binomial_lpmf(1, v1), std::log(0.4));
17+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(0, v0), 0.0);
18+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(0, to_row_vector(v0)), 0.0);
19+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(0, to_array_1d(v0)), 0.0);
20+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(1, v1), std::log(0.4));
21+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(1, to_row_vector(v1)), std::log(0.4));
22+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(1, to_array_1d(v1)), std::log(0.4));
1523
}
16-
1724
TEST(ProbDistributionsPoissonBinomial, lpmf_length_0_length_1_vectorial_y) {
25+
using stan::math::poisson_binomial_lpmf;
26+
using stan::math::to_row_vector;
27+
using stan::math::to_array_1d;
28+
1829
Eigen::VectorXd v0(0);
1930
Eigen::VectorXd v1(1);
2031
v1 << 0.4;
2132

2233
std::vector<int> y0{0, 0};
2334
std::vector<int> y1{1, 1};
2435

25-
EXPECT_FLOAT_EQ(stan::math::poisson_binomial_lpmf(y0, v0), 0.0);
26-
EXPECT_FLOAT_EQ(stan::math::poisson_binomial_lpmf(y1, v1), std::log(0.4) * 2);
36+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y0, v0), 0.0);
37+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y0, to_row_vector(v0)), 0.0);
38+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y0, to_array_1d(v0)), 0.0);
39+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y1, v1), std::log(0.4) * 2);
40+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y1, to_row_vector(v1)), std::log(0.4) * 2);
41+
EXPECT_FLOAT_EQ(poisson_binomial_lpmf(y1, to_array_1d(v1)), std::log(0.4) * 2);
2742
}
2843

2944
TEST(ProbDistributionsPoissonBinomial, lpmf_works_on_scalar_arguments) {
@@ -41,25 +56,35 @@ TEST(ProbDistributionsPoissonBinomial, lpmf_works_on_scalar_arguments) {
4156

4257
TEST(ProbDistributionsPoissonBinomial, lpmf_works_on_vectorial_y) {
4358
using stan::math::poisson_binomial_lpmf;
59+
using stan::math::to_row_vector;
60+
using stan::math::to_array_1d;
4461
using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;
4562

4663
vec p(3, 1);
4764
p << 0.5, 0.2, 0.7;
4865
std::vector<int> y{2, 2};
4966

5067
EXPECT_NEAR(-0.967584 * 2, poisson_binomial_lpmf(y, p), 1e-6);
68+
EXPECT_NEAR(-0.967584 * 2, poisson_binomial_lpmf(y, to_row_vector(p)), 1e-6);
69+
EXPECT_NEAR(-0.967584 * 2, poisson_binomial_lpmf(y, to_array_1d(p)), 1e-6);
5170
}
5271

5372
TEST(ProbDistributionsPoissonBinomial, lpmf_works_on_vectorial_y_and_theta) {
5473
using stan::math::poisson_binomial_lpmf;
74+
using stan::math::to_row_vector;
75+
using stan::math::to_array_1d;
5576
using vec = Eigen::Matrix<double, Eigen::Dynamic, 1>;
5677

5778
vec p(3, 1);
5879
p << 0.5, 0.2, 0.7;
5980
std::vector<int> y{2, 0};
6081
std::vector<vec> ps{p, p};
82+
std::vector<Eigen::RowVectorXd> ps_rv{to_row_vector(p), to_row_vector(p)};
83+
std::vector<std::vector<double>> ps_std{to_array_1d(p), to_array_1d(p)};
6184

6285
EXPECT_NEAR(-0.967584 - 2.12026, poisson_binomial_lpmf(y, ps), 1e-5);
86+
EXPECT_NEAR(-0.967584 - 2.12026, poisson_binomial_lpmf(y, ps_rv), 1e-5);
87+
EXPECT_NEAR(-0.967584 - 2.12026, poisson_binomial_lpmf(y, ps_std), 1e-5);
6388
}
6489

6590
TEST(ProbDistributionsPoissonBinomial,

0 commit comments

Comments
 (0)