Skip to content

Force theta to be an Eigen::VectorXd in laplace_marginal_density_est #3197

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

Merged
merged 7 commits into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions stan/math/mix/functor/laplace_likelihood.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,6 @@ inline auto compute_s2(F&& f, Theta&& theta, AMat&& A,
Matrix<fvar<fvar<var>>, Dynamic, 1> theta_ffvar(theta_size);
auto shallow_copy_args
= shallow_copy_vargs<fvar<fvar<var>>>(std::forward_as_tuple(args...));
// build a “row” index 0,1,2,…,total-1
Eigen::Index total = n_blocks * hessian_block_size;
for (Eigen::Index i = 0; i < hessian_block_size; ++i) {
nested_rev_autodiff nested;
v.setZero();
Expand Down
4 changes: 2 additions & 2 deletions stan/math/mix/functor/laplace_marginal_density.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
};
auto ll_args_vals = value_of(ll_args);
const Eigen::Index theta_size = theta_0.size();
std::decay_t<ThetaVec> theta = theta_0;
Eigen::VectorXd theta = std::forward<ThetaVec>(theta_0);
double objective_old = std::numeric_limits<double>::lowest();
double objective_new = std::numeric_limits<double>::lowest() + 1;
Eigen::VectorXd a_prev = Eigen::VectorXd::Zero(theta_size);
Expand Down Expand Up @@ -1039,7 +1039,7 @@ inline auto laplace_marginal_density(const LLFun& ll_fun, LLTupleArgs&& ll_args,
// Solver 3
arena_t<Eigen::MatrixXd> LU_solve_covariance;
// Solver 1, 2, 3
arena_t<promote_scalar_t<double, std::decay_t<ThetaVec>>> s2(
arena_t<promote_scalar_t<double, plain_type_t<std::decay_t<ThetaVec>>>> s2(
theta_0.size());
// Make one hard copy here
using laplace_likelihood::internal::conditional_copy_and_promote;
Expand Down
222 changes: 0 additions & 222 deletions test/unit/math/laplace/laplace_marginal_lpdf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,228 +20,6 @@ struct poisson_log_likelihood2 {
}
};

template <typename T1, typename T2>
auto in_throw_list(T1&& test_values, T2&& test_arr) {
for (auto&& x : test_values) {
if (x[0] == test_arr[0] && x[1] == test_arr[1] && x[2] == test_arr[2]) {
return true;
}
}
return false;
}

struct poisson_log_likelihood_tuple {
template <typename Theta, typename Eta>
auto operator()(const Theta& theta, const std::vector<int>& delta_int,
Eta&& eta, std::ostream* pstream) const {
return stan::math::poisson_log_lpmf(delta_int, theta) + std::get<0>(eta)
+ std::get<1>(eta);
}
};

struct poisson_log_likelihood_tuple_expanded {
template <typename Theta, typename Eta, typename Eta1, typename Eta2>
auto operator()(const Theta& theta, const std::vector<int>& delta_int,
Eta&& eta, Eta1&& eta1, Eta2&& eta2,
std::ostream* pstream) const {
return stan::math::poisson_log_lpmf(delta_int, theta) + std::get<0>(eta)
+ std::get<1>(eta) + stan::math::sum(eta1) + stan::math::sum(eta2);
}
};

TEST(laplace, poisson_log_phi_dim_2_tuple_extended) {
using stan::math::laplace_marginal;
using stan::math::laplace_marginal_tol;
using stan::math::to_vector;
using stan::math::value_of;
using stan::math::var;
// logger->current_test_name_ = "poisson_log_phi_dim_2";
int dim_phi = 2;
Eigen::Matrix<double, Eigen::Dynamic, 1> phi_dbl(dim_phi);
phi_dbl << 1.6, 0.45;

int dim_theta = 2;
Eigen::VectorXd theta_0(dim_theta);
theta_0 << 0, 0;

int dim_x = 2;
std::vector<Eigen::VectorXd> x(dim_theta);
Eigen::VectorXd x_0{{0.05100797, 0.16086164}};
Eigen::VectorXd x_1{{-0.59823393, 0.98701425}};
x[0] = x_0;
x[1] = x_1;

Eigen::VectorXd y_dummy;

std::vector<int> n_samples = {1, 1};
std::vector<int> sums = {1, 0};

constexpr double tolerance = 1e-12;
constexpr int max_num_steps = 100;
using stan::is_var_v;
using stan::scalar_type_t;
using stan::math::test::laplace_issue;
constexpr std::array known_issues{laplace_issue{0, 0, 0}};
stan::test::ad_tolerances tols;
tols.gradient_grad_ = 1e-1;
stan::math::test::run_solver_grid(
[&](int solver_num, int hessian_block_size, int max_steps_line_search,
auto&& theta_0) {
auto f_ll = [&](auto&& eta1, auto&& eta2, auto&& eta3) {
auto eta1_tuple = std::make_tuple(eta1(0), eta1(1));
return laplace_marginal_tol<false>(
poisson_log_likelihood_tuple_expanded{},
std::forward_as_tuple(sums, eta1_tuple, eta2, eta3), theta_0,
stan::math::test::squared_kernel_functor{},
std::forward_as_tuple(x, std::make_tuple(phi_dbl(0), phi_dbl(1))),
tolerance, max_num_steps, hessian_block_size, solver_num,
max_steps_line_search, nullptr);
};
Eigen::VectorXd test1(phi_dbl);
std::vector<double> test2 = {1.0, 1.0};
stan::test::expect_ad<true>(tols, f_ll, phi_dbl, test1, test2);
},
theta_0);
}

TEST(laplace, poisson_log_phi_dim_2_tuple) {
using stan::math::laplace_marginal;
using stan::math::laplace_marginal_tol;
using stan::math::to_vector;
using stan::math::value_of;
using stan::math::var;
// logger->current_test_name_ = "poisson_log_phi_dim_2";
int dim_phi = 2;
Eigen::Matrix<double, Eigen::Dynamic, 1> phi_dbl(dim_phi);
phi_dbl << 1.6, 0.45;

int dim_theta = 2;
Eigen::VectorXd theta_0(dim_theta);
theta_0 << 0, 0;

int dim_x = 2;
std::vector<Eigen::VectorXd> x(dim_theta);
Eigen::VectorXd x_0{{0.05100797, 0.16086164}};
Eigen::VectorXd x_1{{-0.59823393, 0.98701425}};
x[0] = x_0;
x[1] = x_1;

Eigen::VectorXd y_dummy;

std::vector<int> n_samples = {1, 1};
std::vector<int> sums = {1, 0};

constexpr double tolerance = 1e-12;
constexpr int max_num_steps = 100;
using stan::is_var_v;
using stan::scalar_type_t;
using stan::math::test::laplace_issue;
constexpr std::array known_issues{laplace_issue{0, 0, 0}};
stan::test::ad_tolerances tols;
tols.gradient_grad_ = 1e-1;
stan::math::test::run_solver_grid(
[&](int solver_num, int hessian_block_size, int max_steps_line_search,
auto&& theta_0) {
auto f_covar = [&](auto&& x_v, auto&& alpha, auto&& rho) {
return laplace_marginal_tol<false>(
poisson_log_likelihood2{}, std::forward_as_tuple(sums), theta_0,
stan::math::test::squared_kernel_functor{},
std::forward_as_tuple(x_v, std::make_tuple(alpha, rho)),
tolerance, max_num_steps, hessian_block_size, solver_num,
max_steps_line_search, nullptr);
};
stan::test::expect_ad<true>(tols, f_covar, x, phi_dbl[0], phi_dbl[1]);
},
theta_0);
stan::math::test::run_solver_grid(
[&](int solver_num, int hessian_block_size, int max_steps_line_search,
auto&& theta_0) {
auto f_ll = [&](auto&& alpha_rho, auto&& eta1, auto&& eta2) {
return laplace_marginal_tol<false>(
poisson_log_likelihood_tuple{},
std::forward_as_tuple(sums, std::make_tuple(eta1, eta2)), theta_0,
stan::math::test::squared_kernel_functor{},
std::forward_as_tuple(
x, std::make_tuple(alpha_rho(0), alpha_rho(1))),
tolerance, max_num_steps, hessian_block_size, solver_num,
max_steps_line_search, nullptr);
};
auto test1 = 1.0;
auto test2 = 1.0;
stan::test::expect_ad<true>(tols, f_ll, phi_dbl, test1, test2);
},
theta_0);
}

struct poisson_log_likelihood_array_tuple {
template <typename Theta, typename Eta>
auto operator()(const Theta& theta, const std::vector<int>& delta_int,
Eta&& eta, std::ostream* pstream) const {
return stan::math::poisson_log_lpmf(delta_int, theta) + std::get<0>(eta[0])
+ std::get<1>(eta[0]);
}
};

TEST(laplace, poisson_log_phi_dim_2_array_tuple) {
using stan::math::laplace_marginal;
using stan::math::laplace_marginal_tol;
using stan::math::to_vector;
using stan::math::value_of;
using stan::math::var;
// logger->current_test_name_ = "poisson_log_phi_dim_2";
int dim_phi = 2;
Eigen::Matrix<double, Eigen::Dynamic, 1> phi_dbl(dim_phi);
phi_dbl << 1.6, 0.45;

int dim_theta = 2;
Eigen::VectorXd theta_0(dim_theta);
theta_0 << 0, 0;

int dim_x = 2;
std::vector<Eigen::VectorXd> x(dim_theta);
Eigen::VectorXd x_0{{0.05100797, 0.16086164}};
Eigen::VectorXd x_1{{-0.59823393, 0.98701425}};
x[0] = x_0;
x[1] = x_1;

Eigen::VectorXd y_dummy;

std::vector<int> n_samples = {1, 1};
std::vector<int> sums = {1, 0};

constexpr double tolerance = 1e-12;
constexpr int max_num_steps = 100;
using stan::is_var_v;
using stan::scalar_type_t;
using stan::math::test::laplace_issue;
constexpr std::array known_issues{laplace_issue{0, 0, 0}};
stan::test::ad_tolerances tols;
tols.gradient_grad_ = 1e-1;
stan::math::test::run_solver_grid(
[&](int solver_num, int hessian_block_size, int max_steps_line_search,
auto&& theta_0) {
auto f_ll = [&](auto&& alpha_rho, auto&& eta1, auto&& eta2) {
std::vector<std::tuple<std::decay_t<decltype(eta1)>,
std::decay_t<decltype(eta2)>>>
eta_tuple;
eta_tuple.push_back(std::make_tuple(eta1, eta2));
using alpha_scalar = stan::scalar_type_t<decltype(alpha_rho)>;
std::vector<std::tuple<alpha_scalar, alpha_scalar>> alpha_tuple;
alpha_tuple.push_back(std::make_tuple(alpha_rho(0), alpha_rho(1)));
return laplace_marginal_tol<false>(
poisson_log_likelihood_array_tuple{},
std::forward_as_tuple(sums, eta_tuple), theta_0,
stan::math::test::squared_kernel_functor{},
std::forward_as_tuple(x, alpha_tuple), tolerance, max_num_steps,
hessian_block_size, solver_num, max_steps_line_search, nullptr);
};
auto test1 = 1.0;
auto test2 = 1.0;
stan::test::expect_ad<true>(tols, f_ll, phi_dbl, test1, test2);
},
theta_0);
}

TEST(laplace, poisson_log_phi_dim_2) {
using stan::math::laplace_marginal;
using stan::math::laplace_marginal_tol;
Expand Down
Loading