4 std::vector<double> weights,
7 : eng_(seed), u01_(0.0, 1.0), values_(
std::move(values)), standardize_(standardize)
9 if (values_.empty())
throw std::invalid_argument(
"LikelihoodDiscrete: empty values.");
10 if (weights.size() != values_.size())
throw std::invalid_argument(
"LikelihoodDiscrete: weights size mismatch.");
14 for (
double w : weights) {
15 if (!(w >= 0.0) || !std::isfinite(w))
throw std::invalid_argument(
"LikelihoodDiscrete: invalid weight (must be finite >=0).");
18 if (wsum <= 0.0)
throw std::invalid_argument(
"LikelihoodDiscrete: sum(weights) must be > 0.");
23 for (std::size_t i = 0; i < values_.size(); ++i) m += values_[i] * (weights[i] / wsum);
26 for (std::size_t i = 0; i < values_.size(); ++i) {
27 double d = values_[i] - m;
28 v += d * d * (weights[i] / wsum);
31 std_ = (v > 0.0) ? std::sqrt(v) : 1.0;
34 build_alias_tables(std::move(weights));
37void LikelihoodMarginal::build_alias_tables(std::vector<double> weights) {
38 const std::size_t n = values_.size();
43 double sumw = std::accumulate(weights.begin(), weights.end(), 0.0);
44 if (sumw <= 0.0)
throw std::invalid_argument(
"LikelihoodDiscrete: sum(weights) must be > 0.");
46 std::vector<double> scaled(n);
47 for (std::size_t i = 0; i < n; ++i) scaled[i] = (weights[i] * n) / sumw;
49 std::vector<std::size_t> small;
50 std::vector<std::size_t> large;
54 for (std::size_t i = 0; i < n; ++i) {
55 if (scaled[i] < 1.0) small.push_back(i);
56 else large.push_back(i);
59 while (!small.empty() && !large.empty()) {
60 const std::size_t
s = small.back(); small.pop_back();
61 const std::size_t l = large.back(); large.pop_back();
66 scaled[l] = (scaled[l] + scaled[
s]) - 1.0;
67 if (scaled[l] < 1.0) small.push_back(l);
68 else large.push_back(l);
71 for (std::size_t i : large) {
75 for (std::size_t i : small) {
82 std::vector<double> out(n);
83 const std::size_t m = values_.size();
84 std::uniform_int_distribution<std::size_t> uid(0, m - 1);
86 for (std::size_t k = 0; k < n; ++k) {
87 const std::size_t i = uid(eng_);
88 const double r = u01_(eng_);
89 const std::size_t idx = (r < prob_[i]) ? i : alias_[i];
90 double x = values_[idx];
91 if (standardize_) x = (x - mean_) / std_;
std::vector< double > rvs(std::size_t n) override
Draws random samples from the marginal distribution.
LikelihoodMarginal(std::vector< double > values, std::vector< double > weights, unsigned int seed=std::random_device{}(), bool standardize=false)
Constructs a discrete likelihood marginal.
Hash specialization for SymbolId<Tag>.