Skip to content

Commit 2027764

Browse files
committed
Merge remote-tracking branch 'origin/develop' into student-t-qf
2 parents 2e8aa0e + f30c584 commit 2027764

139 files changed

Lines changed: 779 additions & 465 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ jobs:
7171
python runTests.py -j4 ${{ matrix.config.tests }}
7272
7373
- name: Upload gtest_output xml
74-
uses: actions/upload-artifact@v6
74+
uses: actions/upload-artifact@v7
7575
if: failure()
7676
with:
7777
name: gtest_outputs_xml
@@ -134,7 +134,7 @@ jobs:
134134
python runTests.py -j2 $MixFunProbTestsArray[(${{ matrix.group }} - 1)]
135135
136136
- name: Upload gtest_output xml
137-
uses: actions/upload-artifact@v6
137+
uses: actions/upload-artifact@v7
138138
if: failure()
139139
with:
140140
name: gtest_outputs_xml

doxygen/doxygen.cfg

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2747,7 +2747,6 @@ ALIASES += laplace_options="\
27472747
- theta_0 the initial guess for the Laplace approximation. \
27482748
- tolerance controls the convergence criterion when finding the mode in the Laplace approximation. \
27492749
- max_num_steps maximum number of steps before the Newton solver breaks and returns an error. \
2750-
- hessian_block_size Block size of Hessian of log likelihood w.r.t latent Gaussian variable theta. \
27512750
- solver Type of Newton solver. Each corresponds to a distinct choice of B matrix (i.e. application SWM formula): \
27522751
1. computes square-root of negative Hessian. \
27532752
2. computes square-root of covariance matrix. \

make/tests

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ endif
3838

3939
##
4040
# Adding a test for multiple translation units. If this fails,
41-
# a new function is probably missing an inline
41+
# a public umbrella header likely exposes a new non-inline external definition.
4242
##
4343

4444
ifneq ($(OS),Windows_NT)

runChecks.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,47 @@ def check_non_test_files_in_test():
142142
return errors
143143

144144

145+
def check_rev_test_fixtures():
146+
test_files = [
147+
x for x in files_in_folder("test/unit/math/rev")
148+
if os.path.isfile(x) and x.endswith(testsfx)
149+
]
150+
errors = []
151+
for filepath in test_files:
152+
line_num = 0
153+
multi_line_comment = False
154+
old_state_multi_line_comment = False
155+
with open(filepath, "r") as f:
156+
for line in f:
157+
line_num += 1
158+
if multi_line_comment:
159+
if re.search("\*/", line):
160+
multi_line_comment = False
161+
else:
162+
if re.search("/\*", line):
163+
multi_line_comment = True
164+
if not multi_line_comment or (
165+
multi_line_comment and not old_state_multi_line_comment
166+
):
167+
if (
168+
not re.search(r".*\bTEST\(.*\*/.*", line)
169+
and not re.search(r".*/\*.*\bTEST\(", line)
170+
and not re.search(r".*//.*\bTEST\(", line)
171+
and re.search(r"\bTEST\(", line)
172+
):
173+
errors.append(
174+
filepath
175+
+ " at line "
176+
+ str(line_num)
177+
+ ":\n\t[rev-tests] Reverse-mode tests in "
178+
+ "test/unit/math/rev must use a cleanup fixture. "
179+
+ "Replace raw TEST(...) with TEST_F(AgradRev, ...) "
180+
+ "or another approved fixture-based form."
181+
)
182+
old_state_multi_line_comment = multi_line_comment
183+
return errors
184+
185+
145186
def main():
146187
errors = []
147188
# Check for files inside stan/math/prim that contain stan/math/rev or stan/math/fwd
@@ -242,6 +283,7 @@ def main():
242283
)
243284

244285
errors.extend(check_non_test_files_in_test())
286+
errors.extend(check_rev_test_fixtures())
245287

246288
errors.extend(check_non_unique_test_names())
247289

stan/math/fwd/fun/atan.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ inline fvar<T> atan(const fvar<T>& x) {
2222
*
2323
* @tparam T autodiff value type
2424
* @param[in] z argument
25-
* @return arc tanget of the argument
25+
* @return arc tangent of the argument
2626
*/
2727
template <typename T>
2828
inline std::complex<fvar<T>> atan(const std::complex<fvar<T>>& z) {

stan/math/fwd/fun/read_fvar.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class read_fvar_functor {
3232

3333
/**
3434
* Function applying the read_fvar_functor to extract the values
35-
* and tangets of a given fvar matrix into separate matrices.
35+
* and tangents of a given fvar matrix into separate matrices.
3636
*
3737
* @tparam EigFvar type of the Eigen container of fvar.
3838
* @tparam EigOut type of the Eigen containers to copy to

stan/math/fwd/functor/finite_diff.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ inline auto aggregate_tangent(const FuncTangent& tangent, const InputArg& arg) {
5151

5252
/**
5353
* Construct an fvar<T> where the tangent is calculated by finite-differencing.
54-
* Finite-differencing is only perfomed where the scalar type to be evaluated is
55-
* `fvar<T>.
54+
* Finite-differencing is only performed where the scalar type to be evaluated
55+
* is `fvar<T>.
5656
*
5757
* Higher-order inputs (i.e., fvar<var> & fvar<fvar<T>>) are also implicitly
5858
* supported through auto-diffing the finite-differencing process.
@@ -95,8 +95,8 @@ inline auto finite_diff(const F& func, const TArgs&... args) {
9595

9696
/**
9797
* Construct an fvar<T> where the tangent is calculated by finite-differencing.
98-
* Finite-differencing is only perfomed where the scalar type to be evaluated is
99-
* `fvar<T>.
98+
* Finite-differencing is only performed where the scalar type to be evaluated
99+
* is `fvar<T>.
100100
*
101101
* This overload is used when no fvar<T> arguments are passed and simply
102102
* evaluates the functor with the provided arguments.

stan/math/memory/stack_alloc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class stack_alloc {
254254
/**
255255
* Return number of bytes allocated to this instance by the heap.
256256
* This is not the same as the number of bytes allocated through
257-
* calls to memalloc_. The latter number is not calculatable
257+
* calls to memalloc_. The latter number is not calculable
258258
* because space is wasted at the end of blocks if the next
259259
* alloc request doesn't fit. (Perhaps we could trim down to
260260
* what is actually used?)

stan/math/mix/functor/laplace_marginal_density_estimator.hpp

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef STAN_MATH_MIX_FUNCTOR_LAPLACE_MARGINAL_DENSITY_ESTIMATOR_HPP
22
#define STAN_MATH_MIX_FUNCTOR_LAPLACE_MARGINAL_DENSITY_ESTIMATOR_HPP
33
#include <stan/math/prim/fun/Eigen.hpp>
4+
#include <stan/math/prim/fun/generate_laplace_options.hpp>
45
#include <stan/math/mix/functor/laplace_likelihood.hpp>
56
#include <stan/math/mix/functor/wolfe_line_search.hpp>
67
#include <stan/math/rev/meta.hpp>
@@ -10,6 +11,7 @@
1011
#include <stan/math/mix/functor/barzilai_borwein_step_size.hpp>
1112
#include <stan/math/prim/fun/to_ref.hpp>
1213
#include <stan/math/prim/fun/quad_form_diag.hpp>
14+
#include <stan/math/prim/fun/value_of.hpp>
1315
#include <stan/math/prim/functor/iter_tuple_nested.hpp>
1416
#include <unsupported/Eigen/MatrixFunctions>
1517
#include <cmath>
@@ -30,7 +32,7 @@ namespace math {
3032
*/
3133
struct laplace_options_base {
3234
/* Size of the blocks in block diagonal hessian*/
33-
int hessian_block_size{1}; // 0
35+
int hessian_block_size{internal::laplace_default_hessian_block_size}; // 0
3436
/**
3537
* Which linear solver to use inside the Newton step.
3638
*
@@ -46,19 +48,20 @@ struct laplace_options_base {
4648
* `Sigma = K_root * K_root^T` and form `B = I + K_root^T * W * K_root`.
4749
* 3. General LU: form `B = I + Sigma * W` and factorize with LU.
4850
*/
49-
int solver{1}; // 1
51+
int solver{internal::laplace_default_solver}; // 1
5052
/**
5153
* Iterations end when the absolute change in the optimization objective
5254
* is less than this tolerance.
5355
*
5456
* Note: the objective used for convergence is the one optimized by the
5557
* Newton/Wolfe loop (not the final Laplace-corrected log marginal density).
5658
*/
57-
double tolerance{1.49012e-08}; // 2
59+
double tolerance{internal::laplace_default_tolerance}; // 2
5860
/* Maximum number of steps*/
59-
int max_num_steps{500}; // 3
60-
int allow_fallthrough{true}; // 4
61-
laplace_line_search_options line_search; // 5
61+
int max_num_steps{internal::laplace_default_max_num_steps}; // 3
62+
int allow_fallthrough{internal::laplace_default_allow_fallthrough}; // 4
63+
laplace_line_search_options line_search{
64+
internal::laplace_default_max_steps_line_search}; // 5
6265
laplace_options_base() = default;
6366
laplace_options_base(int hessian_block_size_, int solver_, double tolerance_,
6467
int max_num_steps_, bool allow_fallthrough_,
@@ -75,7 +78,13 @@ template <bool HasInitTheta>
7578
struct laplace_options;
7679

7780
template <>
78-
struct laplace_options<false> : public laplace_options_base {};
81+
struct laplace_options<false> : public laplace_options_base {
82+
laplace_options() = default;
83+
84+
explicit laplace_options(int hessian_block_size_) {
85+
hessian_block_size = hessian_block_size_;
86+
}
87+
};
7988

8089
template <>
8190
struct laplace_options<true> : public laplace_options_base {
@@ -89,25 +98,12 @@ struct laplace_options<true> : public laplace_options_base {
8998
: laplace_options_base(hessian_block_size_, solver_, tolerance_,
9099
max_num_steps_, allow_fallthrough_,
91100
max_steps_line_search_),
92-
theta_0(std::forward<ThetaVec>(theta_0_)) {}
101+
theta_0(value_of(std::forward<ThetaVec>(theta_0_))) {}
93102
};
94103

95104
using laplace_options_default = laplace_options<false>;
96105
using laplace_options_user_supplied = laplace_options<true>;
97106

98-
/**
99-
* User function for generating laplace options tuple
100-
* @param theta_0_size Size of user supplied initial theta
101-
* @return tuple representing laplace options exposed to user.
102-
*/
103-
inline auto generate_laplace_options(int theta_0_size) {
104-
auto ops = laplace_options_default{};
105-
return std::make_tuple(
106-
Eigen::VectorXd::Zero(theta_0_size).eval(), // 0 -> 6
107-
ops.tolerance, ops.max_num_steps, ops.hessian_block_size, ops.solver,
108-
ops.line_search.max_iterations, static_cast<int>(ops.allow_fallthrough));
109-
}
110-
111107
namespace internal {
112108

113109
template <typename Options>
@@ -135,41 +131,36 @@ inline constexpr auto tuple_to_laplace_options(Options&& ops) {
135131
"the laplace approximation.");
136132
}
137133
if constexpr (!stan::is_inner_tuple_type_v<3, Ops, int>) {
138-
static_assert(
139-
sizeof(std::decay_t<Ops>*) == 0,
140-
"ERROR:(laplace_marginal_lpdf) The fifth laplace argument is "
141-
"expected to be an int representing the hessian block size.");
142-
}
143-
if constexpr (!stan::is_inner_tuple_type_v<4, Ops, int>) {
144134
static_assert(
145135
sizeof(std::decay_t<Ops>*) == 0,
146136
"ERROR:(laplace_marginal_lpdf) The fourth laplace argument is "
147137
"expected to be an int representing the solver.");
148138
}
149-
if constexpr (!stan::is_inner_tuple_type_v<5, Ops, int>) {
139+
if constexpr (!stan::is_inner_tuple_type_v<4, Ops, int>) {
150140
static_assert(
151141
sizeof(std::decay_t<Ops>*) == 0,
152-
"ERROR:(laplace_marginal_lpdf) The sixth laplace argument is "
142+
"ERROR:(laplace_marginal_lpdf) The fifth laplace argument is "
153143
"expected to be an int representing the max steps for the laplace "
154144
"approximaton's wolfe line search.");
155145
}
156146
constexpr bool is_fallthrough
157147
= stan::is_inner_tuple_type_v<
158-
6, Ops, int> || stan::is_inner_tuple_type_v<6, Ops, bool>;
148+
5, Ops, int> || stan::is_inner_tuple_type_v<5, Ops, bool>;
159149
if constexpr (!is_fallthrough) {
160150
static_assert(
161151
sizeof(std::decay_t<Ops>*) == 0,
162-
"ERROR:(laplace_marginal_lpdf) The seventh laplace argument is "
152+
"ERROR:(laplace_marginal_lpdf) The sixth laplace argument is "
163153
"expected to be an int representing allow fallthrough (0/1).");
164154
}
155+
auto defaults = laplace_options_default{};
165156
return laplace_options_user_supplied{
166157
value_of(std::get<0>(std::forward<Ops>(ops))),
167158
std::get<1>(ops),
168159
std::get<2>(ops),
160+
defaults.hessian_block_size,
169161
std::get<3>(ops),
170162
std::get<4>(ops),
171-
std::get<5>(ops),
172-
(std::get<6>(ops) > 0) ? true : false,
163+
(std::get<5>(ops) > 0) ? true : false,
173164
};
174165
} else {
175166
return std::forward<Ops>(ops);

stan/math/mix/prob/laplace_latent_bernoulli_logit_rng.hpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ namespace math {
2424
* @param[in] n_samples Vector of number of trials.
2525
* @param[in] mean the mean of the latent normal variable.
2626
* \laplace_common_args
27+
* @param[in] hessian_block_size Block size for the Hessian approximation with
28+
* respect to the latent gaussian variable theta.
2729
* \laplace_options
2830
* \rng_arg
2931
* \msg_arg
@@ -32,15 +34,16 @@ template <typename Mean, typename CovarFun, typename CovarArgs,
3234
typename OpsTuple, typename RNG>
3335
inline Eigen::VectorXd laplace_latent_tol_bernoulli_logit_rng(
3436
const std::vector<int>& y, const std::vector<int>& n_samples, Mean&& mean,
35-
CovarFun&& covariance_function, CovarArgs&& covar_args, OpsTuple&& ops,
36-
RNG& rng, std::ostream* msgs) {
37+
int hessian_block_size, CovarFun&& covariance_function,
38+
CovarArgs&& covar_args, OpsTuple&& ops, RNG& rng, std::ostream* msgs) {
39+
auto options
40+
= internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops));
41+
options.hessian_block_size = hessian_block_size;
3742
return laplace_base_rng(
3843
bernoulli_logit_likelihood{},
3944
std::forward_as_tuple(to_vector(y), n_samples, std::forward<Mean>(mean)),
4045
std::forward<CovarFun>(covariance_function),
41-
std::forward<CovarArgs>(covar_args),
42-
internal::tuple_to_laplace_options(std::forward<OpsTuple>(ops)), rng,
43-
msgs);
46+
std::forward<CovarArgs>(covar_args), std::move(options), rng, msgs);
4447
}
4548

4649
/**
@@ -59,20 +62,22 @@ inline Eigen::VectorXd laplace_latent_tol_bernoulli_logit_rng(
5962
* @param[in] n_samples Vector of number of trials.
6063
* @param[in] mean the mean of the latent normal variable.
6164
* \laplace_common_args
65+
* @param[in] hessian_block_size Block size for the Hessian approximation with
66+
* respect to the latent gaussian variable theta.
6267
* \rng_arg
6368
* \msg_arg
6469
*/
6570
template <typename Mean, typename CovarFun, typename CovarArgs, typename RNG>
6671
inline Eigen::VectorXd laplace_latent_bernoulli_logit_rng(
6772
const std::vector<int>& y, const std::vector<int>& n_samples, Mean&& mean,
68-
CovarFun&& covariance_function, CovarArgs&& covar_args, RNG& rng,
69-
std::ostream* msgs) {
73+
int hessian_block_size, CovarFun&& covariance_function,
74+
CovarArgs&& covar_args, RNG& rng, std::ostream* msgs) {
75+
auto options = laplace_options_default{hessian_block_size};
7076
return laplace_base_rng(
7177
bernoulli_logit_likelihood{},
7278
std::forward_as_tuple(to_vector(y), n_samples, std::forward<Mean>(mean)),
7379
std::forward<CovarFun>(covariance_function),
74-
std::forward<CovarArgs>(covar_args), laplace_options_default{}, rng,
75-
msgs);
80+
std::forward<CovarArgs>(covar_args), options, rng, msgs);
7681
}
7782

7883
} // namespace math

0 commit comments

Comments
 (0)