in lib/maths/common/CMultivariatePrior.cc [107:222]
bool CMultivariatePrior::probabilityOfLessLikelySamples(maths_t::EProbabilityCalculation calculation,
const TDouble10Vec1Vec& samples,
const TDouble10VecWeightsAry1Vec& weights,
const TSize10Vec& coordinates,
TDouble10Vec2Vec& lowerBounds,
TDouble10Vec2Vec& upperBounds,
TTail10Vec& tail) const {
if (coordinates.empty()) {
lowerBounds.clear();
upperBounds.clear();
tail.clear();
return true;
}
lowerBounds.assign(2, TDouble10Vec(coordinates.size(), 0.0));
upperBounds.assign(2, TDouble10Vec(coordinates.size(), 1.0));
tail.assign(coordinates.size(), maths_t::E_UndeterminedTail);
if (samples.empty()) {
LOG_ERROR(<< "Can't compute distribution for empty sample set");
return false;
}
if (!this->check(samples, weights)) {
return false;
}
if (this->isNonInformative()) {
lowerBounds.assign(2, TDouble10Vec(coordinates.size(), 1.0));
upperBounds.assign(2, TDouble10Vec(coordinates.size(), 1.0));
return true;
}
using TDouble1Vec = core::CSmallVector<double, 1>;
using TDoubleWeightsAry1Vec = maths_t::TDoubleWeightsAry1Vec;
using TJointProbabilityOfLessLikelySamplesVec =
core::CSmallVector<CJointProbabilityOfLessLikelySamples, 10>;
static const TSize10Vec NO_MARGINS;
static const TSizeDoublePr10Vec NO_CONDITIONS;
TJointProbabilityOfLessLikelySamplesVec lowerBounds_[2]{
TJointProbabilityOfLessLikelySamplesVec(coordinates.size()),
TJointProbabilityOfLessLikelySamplesVec(coordinates.size())};
TJointProbabilityOfLessLikelySamplesVec upperBounds_[2]{
TJointProbabilityOfLessLikelySamplesVec(coordinates.size()),
TJointProbabilityOfLessLikelySamplesVec(coordinates.size())};
std::size_t d = this->dimension();
TSize10Vec marginalize(d - 1);
TSizeDoublePr10Vec condition(d - 1);
TDouble1Vec sc(1);
TDoubleWeightsAry1Vec wc(1);
for (std::size_t i = 0; i < coordinates.size(); ++i) {
std::size_t coordinate = coordinates[i];
std::copy_if(boost::make_counting_iterator(std::size_t(0)),
boost::make_counting_iterator(d), marginalize.begin(),
[coordinate](std::size_t j) { return j != coordinate; });
TUnivariatePriorPtr margin(this->univariate(marginalize, NO_CONDITIONS).first);
if (!margin) {
return false;
}
for (std::size_t j = 0; j < samples.size(); ++j) {
for (std::size_t k = 0, l = 0; k < d; ++k) {
if (k != coordinate) {
condition[l++] = std::make_pair(k, samples[j][k]);
}
}
sc[0] = samples[j][coordinate];
for (std::size_t k = 0; k < weights[j].size(); ++k) {
wc[0][k] = weights[j][k][coordinate];
}
double lb[2], ub[2];
maths_t::ETail tc[2];
if (!margin->probabilityOfLessLikelySamples(calculation, sc, wc,
lb[0], ub[0], tc[0])) {
LOG_ERROR(<< "Failed to compute probability for coordinate " << coordinate);
return false;
}
LOG_TRACE(<< "lb(" << coordinate << ") = " << lb[0] << ", ub("
<< coordinate << ") = " << ub[0]);
TUnivariatePriorPtr conditional(
this->univariate(NO_MARGINS, condition).first);
if (!conditional->probabilityOfLessLikelySamples(calculation, sc, wc,
lb[1], ub[1], tc[1])) {
LOG_ERROR(<< "Failed to compute probability for coordinate " << coordinate);
return false;
}
LOG_TRACE(<< "lb(" << coordinate << "|.) = " << lb[1] << ", ub("
<< coordinate << "|.) = " << ub[1]);
lowerBounds_[0][i].add(lb[0]);
upperBounds_[0][i].add(ub[0]);
lowerBounds_[1][i].add(lb[1]);
upperBounds_[1][i].add(ub[1]);
tail[i] = static_cast<maths_t::ETail>(tail[i] | tc[1]);
}
}
for (std::size_t i = 0; i < coordinates.size(); ++i) {
if (!lowerBounds_[0][i].calculate(lowerBounds[0][i]) ||
!upperBounds_[0][i].calculate(upperBounds[0][i]) ||
!lowerBounds_[1][i].calculate(lowerBounds[1][i]) ||
!upperBounds_[1][i].calculate(upperBounds[1][i])) {
LOG_ERROR(<< "Failed to compute probability for coordinate " << coordinates[i]);
return false;
}
}
return true;
}