46#include "utils/jsonb.h"
47#include "utils/fmgrprotos.h"
48#include "utils/uuid.h"
75void emit_bin(std::ostringstream &out,
bool &first,
76 double lo,
double hi,
double count)
78 if (!first) out <<
',';
80 out <<
"{\"bin_lo\":" << lo
81 <<
",\"bin_hi\":" << hi
82 <<
",\"count\":" << count <<
'}';
91 int bins = PG_GETARG_INT32(1);
95 provsql_error(
"rv_histogram: bins must be positive (got %d)", bins);
97 std::ostringstream out;
101 out << std::setprecision(17);
112 gate_t root_gate, event_gate;
118 Datum json = DirectFunctionCall1(
119 jsonb_in, CStringGetDatum(pstrdup(out.str().c_str())));
120 PG_RETURN_DATUM(json);
124 std::optional<gate_t> event_opt;
130 const bool conditional = event_opt.has_value();
142 emit_bin(out, first, v, v, n);
145 std::vector<double> samples;
155 std::optional<std::vector<std::tuple<double, double, double>>> ahist;
159 for (
const auto &[bl, bh, mass] : *ahist)
160 emit_bin(out, first, bl, bh, mass);
166 (errmsg(
"rv_histogram: no closed-form shape and "
167 "provsql.rv_mc_samples = 0; returning an empty "
180 gc, root_gate, *event_opt, N);
182 samples = std::move(*direct);
185 gc, root_gate, *event_opt, N);
186 if (cs.accepted.empty())
188 "rv_histogram: conditional MC accepted 0 of %u samples; "
189 "raise provsql.rv_mc_samples or check that the event is "
192 samples = std::move(cs.accepted);
199 if (!samples.empty()) {
213 std::sort(samples.begin(), samples.end());
214 const std::size_t n = samples.size();
215 const std::size_t lo_idx = n / 1000;
216 const std::size_t hi_idx = n - 1 - lo_idx;
218 double smin = std::isfinite(support.first)
221 double smax = std::isfinite(support.second)
228 emit_bin(out, first, smin, smax,
229 static_cast<unsigned>(samples.size()));
231 std::vector<unsigned> counts(bins, 0);
232 const double width = (smax - smin) / bins;
233 for (
double x : samples) {
234 int b =
static_cast<int>((x - smin) / width);
236 if (b >= bins) b = bins - 1;
239 for (
int i = 0; i < bins; ++i) {
240 const double lo = smin + i * width;
241 const double hi = (i == bins - 1) ? smax : lo + width;
242 emit_bin(out, first, lo, hi, counts[i]);
250 "rv_histogram: root gate type '%s' is not a scalar "
251 "(expected gate_value, gate_rv, gate_arith, gate_mixture, "
252 "gate_agg, or gate_semimod)",
255 }
catch (
const std::exception &e) {
262 Datum json = DirectFunctionCall1(
263 jsonb_in, CStringGetDatum(pstrdup(out.str().c_str())));
264 PG_RETURN_DATUM(json);
GenericCircuit getJointCircuit(pg_uuid_t root_token, pg_uuid_t event_token, gate_t &root_gate, gate_t &event_gate)
Build a GenericCircuit containing the closures of two roots, with shared subgraphs unified.
Build in-memory circuits from the mmap-backed persistent store.
gate_t
Strongly-typed gate identifier.
Analytical expectation / variance / moment evaluator over RV circuits.
Semiring-agnostic in-memory provenance circuit.
Monte Carlo sampling over a GenericCircuit, RV-aware.
Continuous random-variable helpers (distribution parsing, moments).
Support-based bound check for continuous-RV comparators.
Datum rv_histogram(PG_FUNCTION_ARGS)
Exception type thrown by circuit operations on invalid input.
gateType getGateType(gate_t g) const
Return the type of gate g.
In-memory provenance circuit with semiring-generic evaluation.
std::string getExtra(gate_t g) const
Return the string extra for gate g.
std::pair< double, double > compute_support(const GenericCircuit &gc, gate_t root, std::optional< gate_t > event_root)
Compute the [lo, hi] support interval of a scalar sub-circuit rooted at root.
std::optional< ClosedFormShape > matchClosedFormDistribution(const GenericCircuit &gc, gate_t root, std::optional< gate_t > event_root)
Detect any of the closed-form shapes supported by rv_analytical_curves.
gate_t lift_conditioning(GenericCircuit &gc, gate_t root, std::optional< gate_t > &event_opt)
Lift conditioning out of a scalar arithmetic expression.
std::optional< std::vector< std::tuple< double, double, double > > > analyticalHistogram(const ClosedFormShape &shape, int bins)
Exact histogram (bin_lo, bin_hi, probability mass) of a closed-form shape, in bins equal-width bins o...
double parseDoubleStrict(const std::string &s)
Strictly parse s as a double.
ConditionalScalarSamples monteCarloConditionalScalarSamples(const GenericCircuit &gc, gate_t root, gate_t event_root, unsigned samples)
Rejection-sample root conditioned on event_root.
std::vector< double > monteCarloScalarSamples(const GenericCircuit &gc, gate_t root, unsigned samples)
Sample a scalar sub-circuit samples times and return the draws.
std::optional< std::vector< double > > try_truncated_closed_form_sample(const GenericCircuit &gc, gate_t root, gate_t event_root, unsigned n)
Try to draw n exact samples from the conditional distribution of root given event_root via closed-for...
int provsql_rv_mc_samples
Default sample count for analytical-evaluator MC fallbacks; 0 disables fallback (callers raise instea...
Uniform error-reporting macros for ProvSQL.
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
const char * gate_type_name[]
Names of gate types.
Core types, constants, and utilities shared across ProvSQL.
@ gate_rv
Continuous random-variable leaf (extra encodes distribution).
@ gate_mixture
Probabilistic mixture: three wires [p_token (gate_input Bernoulli), x_token, y_token]; samples x when...
@ gate_arith
n-ary arithmetic gate over scalar-valued children (info1 holds operator tag)
C++ utility functions for UUID manipulation.