@@ -409,17 +409,19 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
409409 for (Eigen::Index i = 0 ; i <= options.max_num_steps ; i++) {
410410 auto [theta_grad, W] = laplace_likelihood::diff (
411411 ll_fun, theta, options.hessian_block_size , ll_args, msgs);
412-
412+ Eigen::VectorXd W_r (W. rows ());
413413 // Compute matrix square-root of W. If all elements of W are positive,
414414 // do an element wise square-root. Else try a matrix square-root
415415 for (Eigen::Index i = 0 ; i < W.rows (); i++) {
416416 if (W.coeff (i, i) < 0 ) {
417417 throw std::domain_error (
418418 " laplace_marginal_density: Hessian matrix is not positive "
419419 " definite" );
420+ } else {
421+ W_r.coeffRef (i) = std::sqrt (W.coeff (i, i));
420422 }
421423 }
422- Eigen::SparseMatrix<double > W_r = W.cwiseSqrt ();
424+ // Eigen::SparseMatrix<double> W_r = W.cwiseSqrt();
423425 // TODO(Charles): Need better way to handle negative diagonals
424426 /*
425427 if (W_is_spd) {
@@ -431,16 +433,16 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
431433 // TODO(Steve): Memory can be made once out of the loop
432434 // This is our main cost
433435 B.noalias () = MatrixXd::Identity (theta_size, theta_size)
434- + W_r.diagonal (). asDiagonal () * covariance
435- * W_r.diagonal (). asDiagonal ();
436+ + W_r.asDiagonal () * covariance
437+ * W_r.asDiagonal ();
436438 Eigen::LLT<Eigen::Ref<Eigen::MatrixXd>> llt_B (B);
437439 auto L = llt_B.matrixL ();
438440 auto LT = llt_B.matrixU ();
439441 b.noalias () = W.diagonal ().cwiseProduct (theta) + theta_grad;
440442 a.noalias () = b
441- - W_r
443+ - W_r. asDiagonal ()
442444 * LT.solve (L.solve (
443- W_r.diagonal (). cwiseProduct (covariance * b)));
445+ W_r.cwiseProduct (covariance * b)));
444446 // Simple Newton step
445447 theta.noalias () = covariance * a;
446448 objective_old = objective_new;
@@ -461,11 +463,13 @@ inline auto laplace_marginal_density_est(LLFun&& ll_fun, LLTupleArgs&& ll_args,
461463 if (abs (objective_new - objective_old) < options.tolerance ) {
462464 const double B_log_determinant
463465 = 2.0 * llt_B.matrixLLT ().diagonal ().array ().log ().sum ();
466+ // Overwrite W instead of making a new sparse matrix
467+ W.diagonal () = W_r;
464468 return laplace_density_estimates{
465469 objective_new - 0.5 * B_log_determinant,
466470 std::move (covariance),
467471 std::move (theta),
468- std::move (W_r ),
472+ std::move (W ),
469473 std::move (Eigen::MatrixXd (L)),
470474 std::move (a),
471475 std::move (theta_grad),
0 commit comments