@@ -138,63 +138,66 @@ inline void block_matrix_sqrt(WRootMat& W_root,
138138/* *
139139 * @brief Performs a simple line search
140140 *
141- * @tparam AVec Type of the parameter update vector (`a`), e.g. Eigen::VectorXd.
142- * @tparam APrev Type of the previous parameter vector (`a_prev`), same shape as AVec.
141+ * @tparam AVec Type of the parameter update vector (`a`), e.g.
142+ * Eigen::VectorXd.
143+ * @tparam APrev Type of the previous parameter vector (`a_prev`), same shape
144+ * as AVec.
143145 * @tparam ThetaVec Type of the transformed vector (`theta`), e.g. Σ·a.
144146 * @tparam LLFun Functor type for computing the log‐likelihood.
145147 * @tparam LLArgs Tuple or pack type forwarded to `ll_fun`.
146148 * @tparam Covar Matrix type for the covariance Σ, e.g. Eigen::MatrixXd.
147149 * @tparam Msgs Diagnostics container type for capturing warnings/errors.
148150 *
149- * @param[in,out] objective_new On entry: objective at the full‐step `a` (must satisfy objective_new < objective_old). On exit: best objective found.
150- * @param[in,out] a On entry: candidate parameter vector. On exit: updated to the step achieving the lowest objective.
151- * @param[in,out] theta On entry: Σ·a for the initial candidate. On exit: Σ·a for the accepted best step.
152- * @param[in,out] a_prev On entry: previous parameter vector, with objective `objective_old`. On exit: rolled forward to each newly accepted step.
153- * @param[in] ll_fun Callable that computes the log‐likelihood given `(theta, ll_args, msgs)`.
151+ * @param[in,out] objective_new On entry: objective at the full‐step `a` (must
152+ * satisfy objective_new < objective_old). On exit: best objective found.
153+ * @param[in,out] a On entry: candidate parameter vector. On exit: updated to
154+ * the step achieving the lowest objective.
155+ * @param[in,out] theta On entry: Σ·a for the initial candidate. On exit: Σ·a
156+ * for the accepted best step.
157+ * @param[in,out] a_prev On entry: previous parameter vector, with objective
158+ * `objective_old`. On exit: rolled forward to each newly accepted step.
159+ * @param[in] ll_fun Callable that computes the log‐likelihood given `(theta,
160+ * ll_args, msgs)`.
154161 * @param[in] ll_args Arguments forwarded to `ll_fun` at each evaluation.
155162 * @param[in] covariance Covariance matrix Σ used to compute `theta = Σ·a`.
156163 * @param[in] max_steps_line_search Maximum number of iterations.
157- * @param[in] objective_old Objective value at the initial `a_prev` (used as f₀ for the first pass).
158- * @param[in,out] msgs Pointer to a diagnostics container; may be used by `ll_fun` to record warnings.
164+ * @param[in] objective_old Objective value at the initial `a_prev` (used as f₀
165+ * for the first pass).
166+ * @param[in,out] msgs Pointer to a diagnostics container; may be used by
167+ * `ll_fun` to record warnings.
159168 */
160- template <typename AVec, typename APrev, typename ThetaVec,
161- typename LLFun, typename LLArgs, typename Covar, typename Msgs>
162- inline void line_search (double & objective_new,
163- AVec& a,
164- ThetaVec& theta,
165- APrev& a_prev,
166- LLFun&& ll_fun,
167- LLArgs&& ll_args,
168- Covar&& covariance,
169- const int max_steps_line_search,
170- const double objective_old,
171- double tolerance,
172- Msgs* msgs) {
173- Eigen::VectorXd a_tmp (a.size ());
174- double objective_new_tmp = 0.0 ;
175- double objective_old_tmp = objective_old;
176- Eigen::VectorXd theta_tmp (covariance.rows ());
177- for (int j = 0 ; j < max_steps_line_search && (objective_new < objective_old_tmp);
178- ++j) {
179- a_tmp.noalias () = a_prev + 0.5 * (a - a_prev);
180- theta_tmp.noalias () = covariance * a_tmp;
181- if (!theta_tmp.allFinite ()) {
182- break ;
183- } else {
184- objective_new_tmp = -0.5 * a_tmp.dot (theta_tmp)
185- + laplace_likelihood::log_likelihood (
186- ll_fun, theta_tmp, ll_args, msgs);
187- if (objective_new_tmp < objective_new) {
188- a_prev.swap (a);
189- a.swap (a_tmp);
190- theta.swap (theta_tmp);
191- objective_old_tmp = objective_new;
192- objective_new = objective_new_tmp;
193- } else {
194- break ;
195- }
196- }
197- }
169+ template <typename AVec, typename APrev, typename ThetaVec, typename LLFun,
170+ typename LLArgs, typename Covar, typename Msgs>
171+ inline void line_search (double & objective_new, AVec& a, ThetaVec& theta,
172+ APrev& a_prev, LLFun&& ll_fun, LLArgs&& ll_args,
173+ Covar&& covariance, const int max_steps_line_search,
174+ const double objective_old, double tolerance,
175+ Msgs* msgs) {
176+ Eigen::VectorXd a_tmp (a.size ());
177+ double objective_new_tmp = 0.0 ;
178+ double objective_old_tmp = objective_old;
179+ Eigen::VectorXd theta_tmp (covariance.rows ());
180+ for (int j = 0 ;
181+ j < max_steps_line_search && (objective_new < objective_old_tmp); ++j) {
182+ a_tmp.noalias () = a_prev + 0.5 * (a - a_prev);
183+ theta_tmp.noalias () = covariance * a_tmp;
184+ if (!theta_tmp.allFinite ()) {
185+ break ;
186+ } else {
187+ objective_new_tmp = -0.5 * a_tmp.dot (theta_tmp)
188+ + laplace_likelihood::log_likelihood (
189+ ll_fun, theta_tmp, ll_args, msgs);
190+ if (objective_new_tmp < objective_new) {
191+ a_prev.swap (a);
192+ a.swap (a_tmp);
193+ theta.swap (theta_tmp);
194+ objective_old_tmp = objective_new;
195+ objective_new = objective_new_tmp;
196+ } else {
197+ break ;
198+ }
199+ }
200+ }
198201}
199202
200203// iter_tuple_n
@@ -447,9 +450,9 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
447450 + laplace_likelihood::log_likelihood (ll_fun, theta,
448451 ll_args_vals, msgs);
449452 if (options.max_steps_line_search ) {
450- line_search (objective_new, a, theta, a_prev,
451- ll_fun, ll_args_vals, covariance ,
452- options. max_steps_line_search , objective_old, options.tolerance , msgs);
453+ line_search (objective_new, a, theta, a_prev, ll_fun, ll_args_vals,
454+ covariance, options. max_steps_line_search , objective_old ,
455+ options.tolerance , msgs);
453456 }
454457 // Check for convergence
455458 if (abs (objective_new - objective_old) < options.tolerance ) {
@@ -514,9 +517,9 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
514517 + laplace_likelihood::log_likelihood (
515518 ll_fun, value_of (theta), ll_args_vals, msgs);
516519 if (options.max_steps_line_search > 0 ) {
517- line_search (objective_new, a, theta, a_prev,
518- ll_fun, ll_args_vals, covariance ,
519- options. max_steps_line_search , objective_old, options.tolerance , msgs);
520+ line_search (objective_new, a, theta, a_prev, ll_fun, ll_args_vals,
521+ covariance, options. max_steps_line_search , objective_old ,
522+ options.tolerance , msgs);
520523 }
521524 // Check for convergence
522525 if (abs (objective_new - objective_old) < options.tolerance ) {
@@ -566,9 +569,9 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
566569 ll_args_vals, msgs);
567570 // linesearch
568571 if (options.max_steps_line_search > 0 ) {
569- line_search (objective_new, a, theta, a_prev,
570- ll_fun, ll_args_vals, covariance ,
571- options. max_steps_line_search , objective_old, options.tolerance , msgs);
572+ line_search (objective_new, a, theta, a_prev, ll_fun, ll_args_vals,
573+ covariance, options. max_steps_line_search , objective_old ,
574+ options.tolerance , msgs);
572575 }
573576 // Check for convergence
574577 if (abs (objective_new - objective_old) < options.tolerance ) {
@@ -612,9 +615,9 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
612615
613616 // TODO(Charles): How do we handle NA values in theta?
614617 if (options.max_steps_line_search > 0 ) {
615- line_search (objective_new, a, theta, a_prev,
616- ll_fun, ll_args_vals, covariance ,
617- options. max_steps_line_search , objective_old, options.tolerance , msgs);
618+ line_search (objective_new, a, theta, a_prev, ll_fun, ll_args_vals,
619+ covariance, options. max_steps_line_search , objective_old ,
620+ options.tolerance , msgs);
618621 }
619622 if (abs (objective_new - objective_old) < options.tolerance ) {
620623 // TODO(Charles): There has to be a simple trick for this
0 commit comments