28using FamilyPair = std::pair<std::string, std::string>;
30std::map<FamilyPair, ComparatorRule> &comparatorRules()
32 static std::map<FamilyPair, ComparatorRule> rules;
36std::map<FamilyPair, ClosureRule> &closureRules()
38 static std::map<FamilyPair, ClosureRule> rules;
42std::map<FamilyPair, ProductRule> &productRules()
44 static std::map<FamilyPair, ProductRule> rules;
48std::map<FamilyPair, TransformRule> &transformRules()
50 static std::map<FamilyPair, TransformRule> rules;
54std::map<std::string, const DistributionFamily *> &familiesByName()
56 static std::map<std::string, const DistributionFamily *> families;
61using ConjugateKey = std::tuple<std::string, int, std::string>;
63std::map<ConjugateKey, ConjugateRule> &conjugateRules()
65 static std::map<ConjugateKey, ConjugateRule> rules;
83 double xlo, xhi, ylo, yhi;
84 const bool xok = X.integrationRange(xlo, xhi);
85 const bool yok = Y.integrationRange(ylo, yhi);
88 const bool overX = xok && (!yok || (xhi - xlo) <= (yhi - ylo));
89 const double lo = overX ? xlo : ylo;
90 const double hi = overX ? xhi : yhi;
92 const double h = (hi - lo) / N;
94 for (
int i = 0; i <= N; ++i) {
95 const double t = lo + i * h;
96 const double f = overX ? X.pdf(t) : Y.pdf(t);
97 const double F = overX ? Y.cdf(t) : X.cdf(t);
98 if (std::isnan(f) || std::isnan(F))
100 const double coeff = (i == 0 || i == N) ? 1.0 : (i % 2 == 1 ? 4.0 : 2.0);
101 acc += coeff * (overX ? (1.0 - F) : F) * f;
103 return acc * h / 3.0;
111 comparatorRules()[{x, y}] = rule;
116 closureRules()[{x, y}] = rule;
121 productRules()[{x, y}] = rule;
127 transformRules()[{transform, family}] = rule;
131 const char *prior_family,
134 conjugateRules()[{likelihood_family, wired_param, prior_family}] = rule;
139 const std::string &prior_family)
141 const auto &rules = conjugateRules();
142 const auto it = rules.find({likelihood_family, wired_param, prior_family});
143 return it == rules.end() ? nullptr : &it->second;
147 const std::vector<const Distribution *> &factors)
149 const auto &rules = productRules();
151 const char *n0 =
nullptr;
154 n0 = f->family().name;
155 const auto it = rules.find({n0, n0});
156 if (it == rules.end())
return nullptr;
159 const auto it = rules.find({n0, f->family().name});
160 if (it == rules.end() || it->second != rule)
return nullptr;
163 if (!rule)
return nullptr;
164 return rule(factors);
170 const auto &rules = transformRules();
171 const auto it = rules.find({transform, x.
family().
name});
172 return it == rules.end() ? nullptr : it->second(x);
176 const std::vector<ClosureTerm> &terms)
178 const auto &rules = closureRules();
180 const char *n0 =
nullptr;
181 for (
const auto &t : terms) {
182 if (!t.dist)
continue;
184 n0 = t.dist->family().name;
185 const auto it = rules.find({n0, n0});
186 if (it == rules.end())
return nullptr;
189 const auto it = rules.find({n0, t.dist->family().name});
190 if (it == rules.end() || it->second != rule)
return nullptr;
193 if (!rule)
return nullptr;
202 const double f_lo = d.
cdf(lo), f_hi = d.
cdf(hi);
203 if (std::isnan(f_lo) || std::isnan(f_hi) || !(f_lo <= f_hi))
205 if (p <= f_lo)
return lo;
206 if (p >= f_hi)
return hi;
210 for (
int i = 0; i < 200; ++i) {
211 const double mid = 0.5 * (lo + hi);
212 if (!(mid > lo && mid < hi))
214 const double f = d.
cdf(mid);
220 return 0.5 * (lo + hi);
225 const auto &rules = comparatorRules();
228 if (it != rules.end())
229 pLess = it->second(X, Y);
232 if (std::isnan(pLess))
233 pLess = quadraturePairLess(X, Y);
239 familiesByName()[descriptor.
name] = &descriptor;
244 std::vector<const DistributionFamily *> out;
245 for (
const auto &entry : familiesByName())
246 out.push_back(entry.second);
252 const auto &families = familiesByName();
253 const auto it = families.find(name);
254 return it == families.end() ? nullptr : it->second;
259 if (!spec.
family)
return nullptr;
Internal helpers shared by the per-family Distribution implementations under src/distributions/.
Abstract per-family continuous distribution.
virtual bool integrationRange(double &lo, double &hi) const =0
Finite window [lo, hi] covering essentially all of X's mass, for numerical quadrature.
virtual const DistributionFamily & family() const =0
The family's interned registry descriptor.
virtual double cdf(double x) const =0
F(x); NaN if the family declines.
double comparatorPairLess(const Distribution &X, const Distribution &Y)
for two independent RVs.
std::unique_ptr< Distribution >(*)( const Distribution &x) TransformRule
A closed-form image of a monotone transform of one family (e.g.
const ConjugateRule * lookupConjugateRule(const std::string &likelihood_family, int wired_param, const std::string &prior_family)
Look up the conjugate rule for (likelihood family, wired parameter position, prior family); nullptr o...
std::unique_ptr< Distribution > closeTransform(const char *transform, const Distribution &x)
The image distribution of transform applied to x, when a registered rule covers x's family; nullptr o...
std::unique_ptr< Distribution >(*)(const std::vector< ClosureTerm > &terms) ClosureRule
A family sum-closure fold.
std::unique_ptr< Distribution > makeDistribution(const DistributionSpec &spec)
Construct the per-family Distribution for a parsed spec.
void registerProductRule(const char *x, const char *y, ProductRule rule)
Register the product-closure rule for a family pair (name-token keyed, like the sum-closure rules).
std::unique_ptr< Distribution > closePlusTerms(const std::vector< ClosureTerm > &terms)
Fold PLUS(terms) into a single distribution when a registered closure covers every family in the sum.
void registerComparatorRule(const char *x, const char *y, ComparatorRule rule)
Register the closed form for a family pair.
double(*)(const Distribution &X, const Distribution &Y) ComparatorRule
A pairwise closed form for , X and Y independent.
std::unique_ptr< Distribution > closeProductFactors(const std::vector< const Distribution * > &factors)
Fold a product of independent factors into a single distribution when a registered closure covers eve...
std::vector< const DistributionFamily * > listDistributionFamilies()
Every registered family, sorted by name token.
void registerDistributionFamily(const DistributionFamily &descriptor)
Register a family; called by the registrar at static init.
std::unique_ptr< Distribution >(*)( const std::vector< const Distribution * > &factors) ProductRule
A family product-closure fold: the distribution of the product of the (independent) factors,...
double numericQuantile(const Distribution &d, double p)
Numeric inverse CDF: monotone bisection of cdf() over the family's integration window.
const DistributionFamily * lookupDistributionFamily(const std::string &name)
Look up a family by its on-disk name token.
void registerTransformRule(const char *transform, const char *family, TransformRule rule)
Register the image rule for transform ("ln" / "exp" / ...; the evaluator maps its arith opcodes to th...
void registerClosureRule(const char *x, const char *y, ClosureRule rule)
Register the sum-closure rule for a family pair (name-token keyed, like the comparator rules).
void registerConjugateRule(const char *likelihood_family, int wired_param, const char *prior_family, const ConjugateRule &rule)
Register the conjugate update for observations of likelihood_family whose parameter wired_param (0 = ...
The conjugate update for one observation of a given likelihood family against the running posterior (...
A registered family's descriptor: its complete identity.
DistributionFactory factory
Parsed distribution spec (family + up to two parameters).
const DistributionFamily * family
double p2
Second parameter (σ, b, or λ; unused for 1-parameter families).
double p1
First parameter (μ, a, k, or λ).