|
30 | 30 | #include <boost/math/distributions/lognormal.hpp> |
31 | 31 | #include <boost/math/distributions/normal.hpp> |
32 | 32 | #include <boost/math/distributions/students_t.hpp> |
33 | | -#include <boost/math/special_functions/gamma.hpp> |
34 | 33 | #include <boost/numeric/conversion/bounds.hpp> |
35 | 34 |
|
36 | 35 | #include <algorithm> |
@@ -487,49 +486,51 @@ class CLogMarginalLikelihood : core::CNonCopyable { |
487 | 486 | private: |
488 | 487 | //! Compute all the constants in the integrand. |
489 | 488 | void precompute() { |
490 | | - try { |
491 | | - double logVarianceScaleSum = 0.0; |
492 | | - |
493 | | - if (maths_t::hasSeasonalVarianceScale(m_Weights) || |
494 | | - maths_t::hasCountVarianceScale(m_Weights)) { |
495 | | - m_Scales.reserve(m_Weights.size()); |
496 | | - double r = m_Rate / m_Shape; |
497 | | - double s = std::exp(-r); |
498 | | - for (std::size_t i = 0u; i < m_Weights.size(); ++i) { |
499 | | - double varianceScale = maths_t::seasonalVarianceScale(m_Weights[i]) * |
500 | | - maths_t::countVarianceScale(m_Weights[i]); |
501 | | - |
502 | | - // Get the scale and shift of the exponentiated Gaussian. |
503 | | - if (varianceScale == 1.0) { |
504 | | - m_Scales.emplace_back(1.0, 0.0); |
505 | | - } else { |
506 | | - double t = r + std::log(s + varianceScale * (1.0 - s)); |
507 | | - m_Scales.emplace_back(t / r, 0.5 * (r - t)); |
508 | | - logVarianceScaleSum += std::log(t / r); |
509 | | - } |
| 489 | + double logVarianceScaleSum = 0.0; |
| 490 | + |
| 491 | + if (maths_t::hasSeasonalVarianceScale(m_Weights) || |
| 492 | + maths_t::hasCountVarianceScale(m_Weights)) { |
| 493 | + m_Scales.reserve(m_Weights.size()); |
| 494 | + double r = m_Rate / m_Shape; |
| 495 | + double s = std::exp(-r); |
| 496 | + for (std::size_t i = 0u; i < m_Weights.size(); ++i) { |
| 497 | + double varianceScale = maths_t::seasonalVarianceScale(m_Weights[i]) * |
| 498 | + maths_t::countVarianceScale(m_Weights[i]); |
| 499 | + |
| 500 | + // Get the scale and shift of the exponentiated Gaussian. |
| 501 | + if (varianceScale == 1.0) { |
| 502 | + m_Scales.emplace_back(1.0, 0.0); |
| 503 | + } else { |
| 504 | + double t = r + std::log(s + varianceScale * (1.0 - s)); |
| 505 | + m_Scales.emplace_back(t / r, 0.5 * (r - t)); |
| 506 | + logVarianceScaleSum += std::log(t / r); |
510 | 507 | } |
511 | 508 | } |
| 509 | + } |
512 | 510 |
|
513 | | - m_NumberSamples = 0.0; |
514 | | - double weightedNumberSamples = 0.0; |
| 511 | + m_NumberSamples = 0.0; |
| 512 | + double weightedNumberSamples = 0.0; |
515 | 513 |
|
516 | | - for (std::size_t i = 0u; i < m_Weights.size(); ++i) { |
517 | | - double n = maths_t::countForUpdate(m_Weights[i]); |
518 | | - m_NumberSamples += n; |
519 | | - weightedNumberSamples += |
520 | | - n / (m_Scales.empty() ? 1.0 : m_Scales[i].first); |
521 | | - } |
| 514 | + for (std::size_t i = 0u; i < m_Weights.size(); ++i) { |
| 515 | + double n = maths_t::countForUpdate(m_Weights[i]); |
| 516 | + m_NumberSamples += n; |
| 517 | + weightedNumberSamples += n / (m_Scales.empty() ? 1.0 : m_Scales[i].first); |
| 518 | + } |
522 | 519 |
|
523 | | - double impliedShape = m_Shape + 0.5 * m_NumberSamples; |
524 | | - double impliedPrecision = m_Precision + weightedNumberSamples; |
| 520 | + double impliedShape = m_Shape + 0.5 * m_NumberSamples; |
| 521 | + double impliedPrecision = m_Precision + weightedNumberSamples; |
525 | 522 |
|
526 | | - m_Constant = 0.5 * (std::log(m_Precision) - std::log(impliedPrecision)) - |
527 | | - 0.5 * m_NumberSamples * LOG_2_PI - 0.5 * logVarianceScaleSum + |
528 | | - boost::math::lgamma(impliedShape) - |
529 | | - boost::math::lgamma(m_Shape) + m_Shape * std::log(m_Rate); |
530 | | - } catch (const std::exception& e) { |
531 | | - LOG_ERROR(<< "Error calculating marginal likelihood: " << e.what()); |
| 523 | + m_Constant = 0.5 * (std::log(m_Precision) - std::log(impliedPrecision)) - |
| 524 | + 0.5 * m_NumberSamples * LOG_2_PI - |
| 525 | + 0.5 * logVarianceScaleSum + std::lgamma(impliedShape) - |
| 526 | + std::lgamma(m_Shape) + m_Shape * std::log(m_Rate); |
| 527 | + |
| 528 | + if (std::isnan(m_Constant)) { |
| 529 | + LOG_ERROR(<< "Error calculating marginal likelihood, floating point nan"); |
532 | 530 | this->addErrorStatus(maths_t::E_FpFailed); |
| 531 | + } else if (std::isinf(m_Constant)) { |
| 532 | + LOG_ERROR(<< "Error calculating marginal likelihood, floating point overflow"); |
| 533 | + this->addErrorStatus(maths_t::E_FpOverflowed); |
533 | 534 | } |
534 | 535 | } |
535 | 536 |
|
@@ -1219,7 +1220,7 @@ void CLogNormalMeanPrecConjugate::sampleMarginalLikelihood(std::size_t numberSam |
1219 | 1220 | double z = (xq - m_GaussianMean - scale * scale) / scale / |
1220 | 1221 | boost::math::double_constants::root_two; |
1221 | 1222 |
|
1222 | | - double partialExpectation = mean * (1.0 + boost::math::erf(z)) / 2.0; |
| 1223 | + double partialExpectation = mean * (1.0 + std::erf(z)) / 2.0; |
1223 | 1224 |
|
1224 | 1225 | double sample = static_cast<double>(numberSamples) * |
1225 | 1226 | (partialExpectation - lastPartialExpectation) - |
|
0 commit comments