ProvSQL SQL API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
Type for continuous random variables

Custom type random_variable: a thin wrapper around a provenance gate UUID, used to expose continuous probabilistic c-tables in SQL. More...

Types

TYPE  provsql.rv_percentile_state
 Transition state for rv_percentile_impl: the fraction (from the first row) plus the interleaved indicator/value token pairs. More...

Functions

random_variable provsql.random_variable_in (CSTRING)
 Input function for the random_variable type.
CSTRING provsql.random_variable_out (random_variable)
 Output function for the random_variable type.
random_variable provsql.random_variable_make (UUID tok)
 Build a random_variable from a UUID (internal).
CREATE provsql.CAST (random_variable AS UUID) WITHOUT FUNCTION AS ASSIGNMENT
 Binary-coercible cast random_variable -> UUID.
CREATE provsql.CAST (UUID AS random_variable) WITHOUT FUNCTION
random_variable provsql.agg_token_to_random_variable (AGG_TOKEN a)
 Coerce an AGG_TOKEN to a random_variable (its circuit token).
random_variable provsql.CAST(AGG_TOKEN AS RANDOM_VARIABLE) (AGG_TOKEN)
BOOL provsql.is_finite_float8 (DOUBLE PRECISION x)
 Internal: true iff x is a finite (non-NaN, non-±∞) float8.
random_variable provsql.rv_parametric2 (TEXT family, UUID p1_tok, DOUBLE PRECISION p1_lit, UUID p2_tok, DOUBLE PRECISION p2_lit)
 Internal: build a two-parameter latent gate_rv.
random_variable provsql.rv_parametric1 (TEXT family, UUID p_tok)
 Internal: build a one-parameter latent gate_rv (rate/scale).
random_variable provsql.normal (random_variable mu, DOUBLE PRECISION sigma)
 normal(mu, sigma)
random_variable provsql.normal (DOUBLE PRECISION mu, random_variable sigma)
random_variable provsql.normal (random_variable mu, random_variable sigma)
random_variable provsql.logistic (random_variable mu, DOUBLE PRECISION s)
 logistic(mu, s)
random_variable provsql.logistic (DOUBLE PRECISION mu, random_variable s)
random_variable provsql.logistic (random_variable mu, random_variable s)
random_variable provsql.uniform (random_variable a, DOUBLE PRECISION b)
 uniform(a, b)
random_variable provsql.uniform (DOUBLE PRECISION a, random_variable b)
random_variable provsql.uniform (random_variable a, random_variable b)
random_variable provsql.exponential (random_variable lambda)
 exponential(lambda)
random_variable provsql.gamma (random_variable k, DOUBLE PRECISION lambda)
 gamma(k, lambda)
random_variable provsql.gamma (DOUBLE PRECISION k, random_variable lambda)
random_variable provsql.gamma (random_variable k, random_variable lambda)
random_variable provsql.lognormal (random_variable mu, DOUBLE PRECISION sigma)
 lognormal(mu, sigma)
random_variable provsql.lognormal (DOUBLE PRECISION mu, random_variable sigma)
random_variable provsql.lognormal (random_variable mu, random_variable sigma)
random_variable provsql.weibull (random_variable k, DOUBLE PRECISION lambda)
 weibull(k, lambda)
random_variable provsql.weibull (DOUBLE PRECISION k, random_variable lambda)
random_variable provsql.weibull (random_variable k, random_variable lambda)
random_variable provsql.pareto (random_variable xm, DOUBLE PRECISION alpha)
 pareto(xm, alpha)
random_variable provsql.pareto (DOUBLE PRECISION xm, random_variable alpha)
random_variable provsql.pareto (random_variable xm, random_variable alpha)
random_variable provsql.beta (random_variable alpha, DOUBLE PRECISION beta)
 beta(alpha, beta)
random_variable provsql.beta (DOUBLE PRECISION alpha, random_variable beta)
random_variable provsql.beta (random_variable alpha, random_variable beta)
random_variable provsql.inverse_gamma (random_variable alpha, DOUBLE PRECISION beta)
 inverse_gamma(alpha, beta)
random_variable provsql.inverse_gamma (DOUBLE PRECISION alpha, random_variable beta)
random_variable provsql.inverse_gamma (random_variable alpha, random_variable beta)
random_variable provsql.inverse_gaussian (random_variable mu, DOUBLE PRECISION lambda)
 inverse_gaussian(mu, lambda)
random_variable provsql.inverse_gaussian (DOUBLE PRECISION mu, random_variable lambda)
random_variable provsql.inverse_gaussian (random_variable mu, random_variable lambda)
random_variable provsql.normal (DOUBLE PRECISION mu, DOUBLE PRECISION sigma)
 Construct a normal-distribution random variable.
random_variable provsql.logistic (DOUBLE PRECISION mu, DOUBLE PRECISION s)
 Construct a logistic-distribution random variable Logistic(μ, s).
random_variable provsql.uniform (DOUBLE PRECISION a, DOUBLE PRECISION b)
 Construct a uniform-distribution random variable on [a, b].
random_variable provsql.exponential (DOUBLE PRECISION lambda)
 Construct an exponential-distribution random variable with rate λ
random_variable provsql.erlang (INTEGER k, DOUBLE PRECISION lambda)
 Construct an Erlang-distribution random variable, sum of k i.i.d.
random_variable provsql.gamma (DOUBLE PRECISION k, DOUBLE PRECISION lambda)
 Construct a gamma-distribution random variable with shape k (any positive real) and rate lambda.
random_variable provsql.chi_squared (DOUBLE PRECISION k)
 Construct a chi-squared random variable with k degrees of freedom: syntactic sugar for gamma(k/2, 1/2).
random_variable provsql.lognormal (DOUBLE PRECISION mu, DOUBLE PRECISION sigma)
 Construct a log-normal random variable: exp of a Normal(mu, sigma), parameterised by the underlying normal (so its median is exp(mu) and its mean exp(mu + sigma^2/2)).
random_variable provsql.weibull (DOUBLE PRECISION k, DOUBLE PRECISION lambda)
 Construct a Weibull random variable with shape k and scale lambda.
random_variable provsql.pareto (DOUBLE PRECISION xm, DOUBLE PRECISION alpha)
 Construct a Pareto random variable with scale (minimum) xm and shape alpha.
random_variable provsql.inverse_gamma (DOUBLE PRECISION alpha, DOUBLE PRECISION beta)
 Construct an inverse-gamma random variable with shape alpha and scale beta.
random_variable provsql.inverse_gaussian (DOUBLE PRECISION mu, DOUBLE PRECISION lambda)
 Construct an inverse-Gaussian (Wald) random variable with mean mu and shape lambda.
random_variable provsql.wald (DOUBLE PRECISION mu, DOUBLE PRECISION lambda)
 Wald distribution: alias for inverse_gaussian.
random_variable provsql.categorical_from_log_pmf (DOUBLE_PRECISION[] outcomes, DOUBLE_PRECISION[] log_pmf)
 Build a discrete (categorical) random variable from outcomes and UNNORMALISED log-masses.
random_variable provsql.poisson (DOUBLE PRECISION lambda)
 Construct a Poisson random variable with mean lambda, as a truncated categorical.
random_variable provsql.poisson (random_variable lambda)
 Poisson with a LATENT rate: poisson(random_variable).
random_variable provsql.beta (DOUBLE PRECISION alpha, DOUBLE PRECISION beta)
 Construct a Beta(α, β) random variable on the unit interval.
random_variable provsql.binomial (INTEGER n, DOUBLE PRECISION p)
 Construct a Binomial(n, p) random variable (number of successes in n independent trials), as a categorical.
random_variable provsql.binomial (INTEGER n, random_variable p)
 Binomial with a fixed trial count and a LATENT success probability: binomial(INTEGER, random_variable).
random_variable provsql.geometric (DOUBLE PRECISION p)
 Construct a Geometric(p) random variable – the number of TRIALS up to and including the first success (support starting at 1; subtract 1 for the failures convention).
random_variable provsql.geometric (random_variable p)
 Geometric with a LATENT success probability: geometric(random_variable).
random_variable provsql.hypergeometric (INTEGER pop_n, INTEGER k_marked, INTEGER n)
 Construct a Hypergeometric(N, K, n) random variable: the number of marked items among n draws WITHOUT replacement from a population of pop_n items of which k_marked are marked.
random_variable provsql.negative_binomial (DOUBLE PRECISION r, DOUBLE PRECISION p)
 Construct a negative-binomial random variable: the number of FAILURES before the r-th success (support starting at 0), with real r > 0 allowed (the Polya / overdispersed-count parameterisation, the Poisson-Gamma mixture).
random_variable provsql.negative_binomial (DOUBLE PRECISION r, random_variable p)
random_variable provsql.negative_binomial (random_variable r, DOUBLE PRECISION p)
random_variable provsql.negative_binomial (random_variable r, random_variable p)
TABLE provsql.rv_families ()
 Catalog of the registered continuous-distribution families.
random_variable provsql.mixture (UUID p, random_variable x, random_variable y)
 Construct a probabilistic-mixture random variable.
random_variable provsql.mixture (DOUBLE PRECISION p_value, random_variable x, random_variable y)
 Ad-hoc mixture constructor that mints a fresh anonymous gate_input Bernoulli with probability p_value.
random_variable provsql.categorical (DOUBLE_PRECISION[] probs, DOUBLE_PRECISION[] outcomes)
 Categorical-RV constructor over explicit (probabilities, values) arrays.
random_variable provsql.gmm (DOUBLE_PRECISION[] weights, DOUBLE_PRECISION[] means, DOUBLE_PRECISION[] stddevs)
 Gaussian-mixture-model (GMM) constructor.
random_variable provsql.empirical_samples (DOUBLE_PRECISION[] samples)
 Empirical-samples constructor: the ecdf of a sample bundle as a random_variable.
random_variable provsql.empirical_cdf (DOUBLE_PRECISION[] grid, DOUBLE_PRECISION[] cdf)
 Empirical-CDF constructor: a piecewise-linear CDF table as a random_variable.
random_variable provsql.as_random (DOUBLE PRECISION c)
 Lift a deterministic constant into a random_variable.
CREATE provsql.CAST (DOUBLE PRECISION AS random_variable) WITH FUNCTION as_random(DOUBLE PRECISION) AS IMPLICIT
 Implicit cast DOUBLE PRECISION -> random_variable (lifts a scalar literal to a constant RV).
random_variable provsql.as_random (INTEGER c)
 as_random for INTEGER (delegates to the float8 form).
random_variable provsql.as_random (NUMERIC c)
 as_random for NUMERIC (delegates to the float8 form).
random_variable provsql.CAST(INTEGER AS RANDOM_VARIABLE) (INTEGER)
 Implicit cast INTEGER -> random_variable.
random_variable provsql.CAST(NUMERIC AS RANDOM_VARIABLE) (NUMERIC)
 Implicit cast NUMERIC -> random_variable.

Arithmetic and comparison on random_variable

Each binary operator below is declared on (random_variable, random_variable) only; mixed shapes such as rv + 2 or 2.5 > rv resolve through the implicit casts from INTEGER / NUMERIC / double precision to random_variable declared above.

This avoids the resolution ambiguity that would arise if both (rv, NUMERIC) and (rv, rv) overloads were declared while implicit casts also existed.

Arithmetic operators build a gate_arith via provenance_arith and return a new random_variable wrapping its UUID.

Comparison operators are placeholders that return BOOLEAN and raise if executed – the BOOLEAN return type is required so that PostgreSQL accepts WHERE rv > 2 at parse-analyze. The planner hook intercepts every such OpExpr (matched by opfuncid against constants_t::OID_FUNCTION_RV_CMP) and rewrites it into a provenance_cmp call whose UUID is conjoined into the tuple's provsql column via provenance_times. Code that needs a gate_cmp UUID directly (without going through the planner hook) uses the rv_cmp_* family below, which call provenance_cmp with the matching float8-comparator OID.

CREATE OPERATOR CLASS random_variable_ops DEFAULT FOR TYPE random_variable USING btree AS OPERATOR<, OPERATOR 2<=, OPERATOR 3=, OPERATOR 4 > provsql.OPERATOR
random_variable provsql.random_variable_plus (random_variable a, random_variable b)
 random_variable + random_variable (gate_arith PLUS).
random_variable provsql.random_variable_minus (random_variable a, random_variable b)
 random_variable - random_variable (gate_arith MINUS).
random_variable provsql.random_variable_times (random_variable a, random_variable b)
 random_variable * random_variable (gate_arith TIMES).
random_variable provsql.random_variable_div (random_variable a, random_variable b)
 random_variable / random_variable (gate_arith DIV).
random_variable provsql.random_variable_neg (random_variable a)
 Unary -random_variable (gate_arith NEG).
random_variable provsql.random_variable_pow (random_variable a, random_variable b)
 random_variable ^ random_variable (gate_arith POW).
random_variable provsql.ln (random_variable a)
 Natural logarithm of a random_variable (gate_arith LN).
random_variable provsql.exp (random_variable a)
 e^x for a random_variable (gate_arith EXP).
random_variable provsql.pow (random_variable a, random_variable b)
 pow / power spellings of the ^ operator, mirroring PostgreSQL's NUMERIC surface.
random_variable provsql.power (random_variable a, random_variable b)
random_variable provsql.sqrt (random_variable a)
 Square root of a random_variable: sugar for x ^ 0.5 (no gate or opcode of its own).
oid provsql.random_variable_cmp_oid (TEXT sym)
 Internal helper: float8-comparator OID for a given symbol.
BOOLEAN provsql.random_variable_cmp_placeholder (random_variable a, random_variable b)
 Placeholder body shared by every random_variable_* comparison procedure.
BOOLEAN provsql.random_variable_lt (random_variable a, random_variable b)
BOOLEAN provsql.random_variable_le (random_variable a, random_variable b)
BOOLEAN provsql.random_variable_eq (random_variable a, random_variable b)
BOOLEAN provsql.random_variable_ne (random_variable a, random_variable b)
BOOLEAN provsql.random_variable_ge (random_variable a, random_variable b)
BOOLEAN provsql.random_variable_gt (random_variable a, random_variable b)
UUID provsql.rv_cmp_lt (random_variable a, random_variable b)
 Build a gate_cmp for a < b and return its UUID.
UUID provsql.rv_cmp_le (random_variable a, random_variable b)
 Build a gate_cmp for a ≤ b and return its UUID.
UUID provsql.rv_cmp_eq (random_variable a, random_variable b)
 Build a gate_cmp for a = b and return its UUID.
UUID provsql.rv_cmp_ne (random_variable a, random_variable b)
 Build a gate_cmp for a <> b and return its UUID.
UUID provsql.rv_cmp_ge (random_variable a, random_variable b)
 Build a gate_cmp for a ≥ b and return its UUID.
UUID provsql.rv_cmp_gt (random_variable a, random_variable b)
 Build a gate_cmp for a > b and return its UUID.
BOOLEAN provsql.random_variable_op_random_variable (random_variable left, random_variable right)
 Prefix unary minus on random_variable.
BOOLEAN provsql.random_variable_lt_random_variable (random_variable left, random_variable right)
BOOLEAN provsql.random_variable_le_random_variable (random_variable left, random_variable right)
BOOLEAN provsql.random_variable_eq_random_variable (random_variable left, random_variable right)
BOOLEAN provsql.random_variable_ne_random_variable (random_variable left, random_variable right)
BOOLEAN provsql.random_variable_ge_random_variable (random_variable left, random_variable right)
BOOLEAN provsql.random_variable_gt_random_variable (random_variable left, random_variable right)
INTEGER provsql.random_variable_btree_cmp (random_variable a, random_variable b)
 btree comparison support for random_variable – always an error.
random_variable provsql.random_variable_cond (random_variable rv, UUID cond)
 Condition a random variable on an event: "X | C".
BOOLEAN provsql.random_variable_op_uuid (random_variable left, UUID right)
random_variable provsql.random_variable_cond_predicate (random_variable rv, BOOLEAN predicate)
 Placeholder for "X | (predicate)" – conditioning a random variable on a Boolean comparison written naturally.
BOOLEAN provsql.random_variable_op_boolean (random_variable left, BOOLEAN right)
UUID provsql.rv_conditioned_target (UUID token)
 Unpack the target of a random-variable conditioning gate.
UUID provsql.rv_conditioned_prov (UUID token, UUID prov)
 Combine a conditioning gate's event with an explicit prov.
UUID provsql.evidence_as_observation (UUID ev)
 Internal: rewrite a point-equality conditioning event into an observation.
UUID provsql.observe (random_variable x, DOUBLE PRECISION datum)
 Internal: bind an observed datum to a random-variable leaf – the likelihood-weighting evidence behind "X | (Y = d)".
UUID provsql.and_agg_sfunc (UUID state, UUID ev)
 Conjunction state function for and_agg (evidence gate_times).
VOID provsql.and_agg (UUID)
 Conjoin per-row evidence tokens into one evidence circuit.
DOUBLE PRECISION provsql.evidence (UUID evidence)
 Marginal likelihood P(data) of an evidence circuit.
UUID[] provsql.observe_atoms (UUID evidence)
 The observe atoms of an evidence circuit.
TABLE provsql.shapley_observe (UUID target, UUID evidence, TEXT payoff='expected')
 Shapley attribution of each observation to a posterior moment.

Order statistics over random_variable

Same-row greatest / least over random_variable arguments: the order-statistic counterpart of the element-wise "+ - * /" operators.

They lower to a single gate_arith with the MAX / MIN opcode over the argument circuits, the same n-ary shape the max / min aggregates build. Evaluation is Monte-Carlo-correct out of the box (std::max / std::min over the jointly-sampled children, so shared base RVs stay coupled); closed forms for i.i.d. families come from the analytic order-statistic pass.

PostgreSQL's built-in GREATEST / LEAST are dedicated syntax (a MinMaxExpr requiring a btree comparison), not overloadable functions, so the surface is the schema-qualified provsql.greatest(...) / provsql.least(...). NULL arguments are ignored, matching the built-in (an all-NULL / empty call returns NULL).

CREATE OR REPLACE FUNCTION provsql.greatest (VARIADIC args random_variable[]) RETURNS random_variable AS CREATE OR REPLACE FUNCTION "least"(VARIADIC args random_variable[]) RETURNS random_variable AS random_variable rv_case(UUID[] children)
 "greatest" / "least" are col_name keywords, so the CREATE FUNCTION name must be quoted; callers reach them qualified as provsql.greatest(...).
AGG_TOKEN provsql.agg_case (UUID[] children)
 Build an AGG_TOKEN from a guarded-selection gate_case.

Aggregates over random_variable

An overload of the standard sum aggregate that takes a random_variable per row and returns the random_variable representing the (provenance-weighted) sum.

Lives in the provsql schema so a sum(random_variable) call resolves to it without colliding with the built-in NUMERIC sum overloads in pg_catalog.

Direct calls outside a provenance-tracked query treat each row's contribution unconditionally (no per-row Boolean selector). When the planner hook sees a provsql.sum Aggref over a provenance-tracked query, it wraps the per-row argument x in provsql.mixture(prov_token, x, provsql.as_random(0)) so the aggregate's effective semantics become \(\mathrm{SUM}(x) = \sum_i \mathbf{1}\{\varphi_i\} \cdot X_i\), the natural extension of semimodule-provenance to RV-valued M.

The internal state is the array of UUIDs of the per-row mixtures. The final function builds a single gate_arith PLUS over them (or returns as_random(0) for an empty group, the additive identity). Sharing on provenance_arith's v5 hash means two sum invocations over the same set of rows collide on the same gate.

random_variable provsql.rv_aggregate_semimod (UUID prov, random_variable rv)
 Per-row helper: wrap an RV in mixture(prov, rv, as_random(0)).
random_variable provsql.rv_aggregate_semimod (UUID prov, random_variable rv, DOUBLE PRECISION identity)
 Identity-parameterised per-row wrap for an RV-returning aggregate.
random_variable provsql.rv_aggregate_indicator (UUID prov)
 Per-row denominator wrap for avg(random_variable): the provenance indicator \(\mathbf{1}\{\varphi\}\).
random_variable provsql.rv_aggregate_indicator (UUID prov, random_variable rv)
 Value-aware presence indicator: NULL when the row's aggregated value is NULL.
UUID[] provsql.sum_rv_sfunc (UUID[] state, random_variable rv)
 State-transition function for sum(random_variable).
random_variable provsql.sum_rv_ffunc (UUID[] state)
 Final function for sum(random_variable): build a gate_arith PLUS root.
VOID provsql.sum (random_variable)
random_variable provsql.rv_sum_or_null_ffunc (UUID[] state)
 Numerator final function for the avg rewrite: sum, but NULL on an empty group.
VOID provsql.rv_sum_or_null (random_variable)
random_variable provsql.avg_rv_ffunc (UUID[] state)
 Final function for avg(random_variable).
VOID provsql.avg (random_variable)
random_variable provsql.product_rv_ffunc (UUID[] state)
 Final function for product(random_variable): fold a gate_arith TIMES root over the per-row contributions.
VOID provsql.product (random_variable)
random_variable provsql.extremum_rv_ffunc (UUID[] state, INTEGER op, DOUBLE PRECISION identity)
 Final function for max(random_variable) / min(random_variable): fold a gate_arith MAX / MIN root over the per-row contributions.
random_variable provsql.max_rv_ffunc (UUID[] state)
random_variable provsql.min_rv_ffunc (UUID[] state)
VOID provsql.max (random_variable)
VOID provsql.min (random_variable)
UUID[] provsql.rv_stat1_sfunc (UUID[] state, random_variable x)
 SQL-standard statistic aggregates over random_variable rows: covar_pop / covar_samp / corr (two-argument), stddev_pop / stddev_samp (one-argument), and the ordered-set percentile_cont.
UUID[] provsql.rv_stat2_sfunc (UUID[] state, random_variable x, random_variable y)
 State transition for the two-argument RV statistic aggregates (covar_pop / covar_samp / corr): append the certain indicator and the row's RV pair as a triple.
UUID[] provsql.rv_stat1_impl_sfunc (UUID[] state, random_variable ind, random_variable x)
 Indicator-carrying state transition for the one-argument rv_*_impl statistic aggregates: the planner-hook rewrite passes the row's provenance indicator rv_aggregate_indicator(prov) as ind.
UUID[] provsql.rv_stat2_impl_sfunc (UUID[] state, random_variable ind, random_variable x, random_variable y)
 Indicator-carrying state transition for the two-argument rv_*_impl statistic aggregates.
VOID provsql.rv_stat_sum_tokens (UUID[] state, INTEGER stride, OUT UUID n_tok, OUT UUID sx_tok, OUT UUID sxx_tok, OUT UUID sy_tok, OUT UUID sxy_tok, OUT UUID syy_tok)
 Mint the indicator-weighted power-sum gates shared by the covariance / stddev final functions.
UUID provsql.rv_stat_var_pop_token (UUID n_tok, UUID s_tok, UUID ss_tok)
 Population-variance gate \(SXX/N - (SX/N)^2\) from the power-sum tokens.
UUID provsql.rv_stat_var_samp_token (UUID n_tok, UUID s_tok, UUID ss_tok)
 Sample-variance gate \((SXX - SX^2/N) / (N - 1)\) from the power-sum tokens (NaN in a world with \(N \le 1\), the undefined-world convention).
UUID provsql.rv_stat_sqrt_token (UUID v_tok)
 \(\sqrt{\max(v, 0)}\) gate over a variance token: the max-clamp removes the tiny negative values float error can produce (variance is mathematically non-negative), so the POW domain guard never fires.
UUID provsql.rv_stat_covar_pop_token (UUID n_tok, UUID sx_tok, UUID sy_tok, UUID sxy_tok)
 Population-covariance gate \(SXY/N - (SX/N)(SY/N)\) from the power-sum tokens.
random_variable provsql.covar_pop_rv_ffunc (UUID[] state)
 Final function for covar_pop(random_variable, random_variable).
random_variable provsql.covar_samp_rv_ffunc (UUID[] state)
 Final function for covar_samp(random_variable, random_variable): \((SXY - SX\,SY/N) / (N-1)\).
random_variable provsql.corr_rv_ffunc (UUID[] state)
 Final function for corr(random_variable, random_variable): \(\mathrm{covar\_pop} / \sqrt{\max(v_x v_y, 0)}\) (a zero-variance world divides to \(\pm\infty\) / NaN, the undefined-world convention, matching SQL's NULL for a zero-stddev input).
random_variable provsql.stddev_pop_rv_ffunc (UUID[] state)
 Final function for stddev_pop(random_variable).
random_variable provsql.stddev_samp_rv_ffunc (UUID[] state)
 Final function for stddev_samp(random_variable).
VOID provsql.covar_pop (random_variable, random_variable)
VOID provsql.covar_samp (random_variable, random_variable)
VOID provsql.corr (random_variable, random_variable)
VOID provsql.stddev_pop (random_variable)
VOID provsql.stddev_samp (random_variable)
VOID provsql.rv_covar_pop_impl (random_variable, random_variable, random_variable)
 The indicator-carrying rewrite targets (planner hook only; never called directly by users).
VOID provsql.rv_covar_samp_impl (random_variable, random_variable, random_variable)
VOID provsql.rv_corr_impl (random_variable, random_variable, random_variable)
VOID provsql.rv_stddev_pop_impl (random_variable, random_variable)
VOID provsql.rv_stddev_samp_impl (random_variable, random_variable)
random_variable provsql.rv_percentile_make (DOUBLE PRECISION fraction, UUID[] pairs)
 Mint the PROVSQL_ARITH_PERCENTILE gate: the continuous percentile (SQL percentile_cont) over a group of RV rows.
UUID[] provsql.percentile_cont_rv_sfunc (UUID[] state, random_variable x)
 State transition for the public ordered-set percentile_cont(float8) WITHIN GROUP (ORDER BY random_variable): append the certain indicator and the row's RV.
random_variable provsql.percentile_cont_rv_ffunc (UUID[] state, DOUBLE PRECISION fraction)
 Final function for the public ordered-set percentile_cont: receives the direct fraction argument after the state.
VOID provsql.percentile_cont (DOUBLE PRECISION ORDER BY random_variable)
rv_percentile_state provsql.rv_percentile_impl_sfunc (rv_percentile_state state, DOUBLE PRECISION fraction, random_variable ind, random_variable x)
 State transition for rv_percentile_impl, the planner-hook rewrite target of a provenance-tracked percentile_cont: stashes the (group-constant) fraction and appends the indicator/value pair.
random_variable provsql.rv_percentile_impl_ffunc (rv_percentile_state state)
 Final function for rv_percentile_impl.
VOID provsql.rv_percentile_impl (DOUBLE PRECISION, random_variable, random_variable)

Detailed Description

Custom type random_variable: a thin wrapper around a provenance gate UUID, used to expose continuous probabilistic c-tables in SQL.

The UUID indexes either a gate_rv (an actual distribution) or a gate_value (a zero-variance constant produced by provsql.as_random). Binary-coercible with UUID (same 16-byte layout), so an rv-typed expression flows directly into any function expecting a UUID at zero runtime cost.

Constructors live in this group: provsql.normal(μ, σ), provsql.uniform(a, b), provsql.exponential(λ), provsql.erlang(k, λ), provsql.gamma(k, λ), provsql.chi_squared(k), provsql.lognormal(μ, σ), provsql.weibull(k, λ), provsql.pareto(xₘ, α), provsql.beta(α, β), the discrete count constructors (provsql.poisson(λ), provsql.binomial(n, p), provsql.geometric(p), provsql.hypergeometric(N, K, n), provsql.negative_binomial(r, p), all lowering to categorical via categorical_from_log_pmf), and provsql.as_random(c). Operator overloads (+ - * / and the six comparators) are defined further below, alongside direct rv_cmp_* UUID constructors for callers that want a gate_cmp token without going through the planner hook.

Function Documentation

◆ agg_case()

AGG_TOKEN provsql.agg_case ( UUID[] children)

Build an AGG_TOKEN from a guarded-selection gate_case.

The aggregate-carrier analogue of rv_case: a thin AGG_TOKEN wrapper over the carrier-agnostic provenance_case, the target of the planner-hook lowering of a searched CASE whose guards are aggregate comparisons and whose branches are aggregates. The branches (and default) are already flattened into [guard_1, value_1, ..., default] UUIDs. The display cell carries the actual-world CASE value – the branch selected on the actual data, resolved by agg_gate_value, exactly as a bare aggregate's cell carries its actual-world value. The probabilistic result is produced by the measure evaluators (expected / probability / possible-worlds / Monte Carlo) from the gate, not the token's cell.

Source code
provsql.sql line 5728

◆ agg_token_to_random_variable()

random_variable provsql.agg_token_to_random_variable ( AGG_TOKEN a)

Coerce an AGG_TOKEN to a random_variable (its circuit token).

An aggregate over probabilistic tuples IS a random variable: its AGG_TOKEN carries the provenance circuit of the aggregate distribution. Exposing that as a random_variable lets a comparison / conditioning predicate mix the two – e.g. conditioning a latent leaf on a count, "R | (poisson(lambda) = C)" with C a count(*) AGG_TOKEN – resolve to the ordinary random_variable comparison operators (which the planner hook rewrites into a gate_cmp). IMPLICIT so the mixed comparison type-checks without an explicit cast; the polymorphic dispatchers keep their exact AGG_TOKEN overloads (an exact match beats the cast).

Source code
provsql.sql line 3074

◆ and_agg()

VOID provsql.and_agg ( UUID )

Conjoin per-row evidence tokens into one evidence circuit.

The evidence-conjunction counterpart used to fold one observe (or any Boolean conditioning event) per row into a single gate_times root, to be passed as the prov argument of the moment / quantile / sample readouts. An empty group yields NULL (no evidence).

Source code
provsql.sql line 5474

◆ and_agg_sfunc()

UUID provsql.and_agg_sfunc ( UUID state,
UUID ev )

Conjunction state function for and_agg (evidence gate_times).

Not STRICT: provenance_times maps a NULL operand to the times neutral, so an empty group leaves the state NULL (no evidence) and a first row seeds it with that row's evidence.

Source code
provsql.sql line 5460

◆ as_random() [1/3]

random_variable provsql.as_random ( DOUBLE PRECISION c)

Lift a deterministic constant into a random_variable.

Creates a gate_value carrying the constant's TEXT form so that comparisons against a random_variable column produce the same circuit shape regardless of whether the operand is an actual RV or a literal constant.

Marked IMMUTABLE: the gate UUID is derived deterministically from the constant via the same v5 convention as provenance_semimod's inline value gate (concat('value', CAST(c AS VARCHAR))), so as_random(2) always resolves to the same gate, and any other code path that already creates a value gate for the same constant (e.g. provenance_semimod) shares the UUID. create_gate is idempotent on already-mapped tokens, so repeat invocations are harmless.

See also
Wikipedia: Degenerate distribution (Dirac point mass)
Source code
provsql.sql line 4736

◆ as_random() [2/3]

random_variable provsql.as_random ( INTEGER c)

as_random for INTEGER (delegates to the float8 form).

Source code
provsql.sql line 4736

◆ as_random() [3/3]

random_variable provsql.as_random ( NUMERIC c)

as_random for NUMERIC (delegates to the float8 form).

Source code
provsql.sql line 4736

◆ avg()

VOID provsql.avg ( random_variable )

◆ avg_rv_ffunc()

random_variable provsql.avg_rv_ffunc ( UUID[] state)

Final function for avg(random_variable).

avg lifts the "@c AVG @c = @c SUM @c / @c COUNT" identity into the random_variable algebra:

\[ \mathrm{AVG}(x) \;=\; \frac{\sum_i \mathbf{1}\{\varphi_i\} \cdot X_i} {\sum_i \mathbf{1}\{\varphi_i\}}. \]

In a provenance-tracked query the planner-hook rewrites avg(x) into rv_sum_or_null(rv_aggregate_semimod(prov, x)) / sum(rv_aggregate_indicator(prov)) (see make_rv_aggregate_expression), so both the numerator and the provenance-weighted count denominator are built by sum's fold and no gate is inspected. This FFUNC is therefore reached only on an untracked call, where every row is unconditionally present: the numerator is sum over the raw per-row RVs and the denominator is the plain row count n (each row contributing as_random(1)).

Empty group: returns NULL, matching standard SQL AVG (and unlike sum, whose empty group is the additive identity as_random(0)): the caller cannot otherwise disambiguate "0 rows" from "rows summing to 0".

Source code
provsql.sql line 5957

◆ beta() [1/4]

random_variable provsql.beta ( DOUBLE PRECISION alpha,
DOUBLE PRECISION beta )

Construct a Beta(α, β) random variable on the unit interval.

The conjugate prior of Bernoulli / binomial success probabilities: closed-form moments, CDF through the regularised incomplete beta, quantiles through the generic CDF bisection over the finite [0, 1] support, and closed-form truncated moments (interval conditioning). Beta(1, 1) IS Uniform(0, 1) and is silently routed through uniform to share its richer closed forms.

Validation: both shapes must be finite and strictly positive.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Beta distribution
Source code
provsql.sql line 3269

◆ beta() [2/4]

random_variable provsql.beta ( DOUBLE PRECISION alpha,
random_variable beta )

◆ beta() [3/4]

random_variable provsql.beta ( random_variable alpha,
DOUBLE PRECISION beta )

beta(alpha, beta)

◆ beta() [4/4]

random_variable provsql.beta ( random_variable alpha,
random_variable beta )

◆ binomial() [1/2]

random_variable provsql.binomial ( INTEGER n,
DOUBLE PRECISION p )

Construct a Binomial(n, p) random variable (number of successes in n independent trials), as a categorical.

Enumerated over {0..n} by the log-space recurrence ln p(k+1) = ln p(k) + ln((n-k)/(k+1)) + ln(p/(1-p)) (outcomes below 1e-15 relative mass are dropped). p = 0 / p = 1 are Diracs at 0 / n; n is capped at 10000.

See also
Wikipedia: Binomial distribution
Source code
provsql.sql line 3967

◆ binomial() [2/2]

random_variable provsql.binomial ( INTEGER n,
random_variable p )

Binomial with a fixed trial count and a LATENT success probability: binomial(INTEGER, random_variable).

n is a literal trial count; p is a latent (token-valued) success probability (e.g. "40.0 / N" for a latent population size N). Builds a parametric gate_rv leaf (family "binomial", extra "binomial:n,$0") the Monte Carlo sampler resolves per draw; observe weights by the Binomial pmf. Unblocks capture-recapture-style posteriors such as "N | (binomial(50, 40.0/N) = recaptured_count)".

Source code
provsql.sql line 3967

◆ CAST() [1/3]

CREATE provsql.CAST ( DOUBLE PRECISION AS random_variable)

Implicit cast DOUBLE PRECISION -> random_variable (lifts a scalar literal to a constant RV).

Lets users write WHERE reading > 2.5::float8 instead of WHERE reading > provsql.as_random(2.5); the planner-hook rewriter then sees a uniform random_variable on both sides. Sibling casts below cover INTEGER and NUMERIC literals so plain WHERE reading > 2 and WHERE reading > 2.5 also work; PostgreSQL's operator resolution does not chain casts across more than one step, so each NUMERIC-source type needs its own direct cast.

◆ CAST() [2/3]

CREATE provsql.CAST ( random_variable AS UUID)

Binary-coercible cast random_variable -> UUID.

A random_variable is byte-for-byte a pg_uuid_t (alignment char, length 16), so WITHOUT FUNCTION lets PostgreSQL reinterpret the bytes at zero runtime cost. The cast is ASSIGNMENT (not IMPLICIT): an implicit cross-domain cast would silently reroute a comparison such as v < w to UUID < UUID (raw byte comparison) whenever provsql is not in search_path, since operators are resolved through search_path but casts are not. Demoting to ASSIGNMENT turns that silent wrong result into a clean parse error. Passing a random_variable to a UUID-taking function now needs an explicit v::UUID (function resolution never applies assignment casts).

◆ CAST() [3/3]

CREATE provsql.CAST ( UUID AS random_variable)

◆ CAST(AGG_TOKEN AS RANDOM_VARIABLE)()

random_variable provsql.CAST(AGG_TOKEN AS RANDOM_VARIABLE) ( AGG_TOKEN )

◆ CAST(INTEGER AS RANDOM_VARIABLE)()

random_variable provsql.CAST(INTEGER AS RANDOM_VARIABLE) ( INTEGER )

Implicit cast INTEGER -> random_variable.

Source code
provsql.sql line 4785

◆ CAST(NUMERIC AS RANDOM_VARIABLE)()

random_variable provsql.CAST(NUMERIC AS RANDOM_VARIABLE) ( NUMERIC )

Implicit cast NUMERIC -> random_variable.

Source code
provsql.sql line 4789

◆ categorical()

random_variable provsql.categorical ( DOUBLE_PRECISION[] probs,
DOUBLE_PRECISION[] outcomes )

Categorical-RV constructor over explicit (probabilities, values) arrays.

Builds a categorical-form gate_mixture directly: a fresh gate_input "key" anchor and one gate_mulinput per outcome with positive mass, all sharing the key. The wires [key, mul_1, ..., mul_n] are what downstream evaluators (Expectation, MonteCarloSampler, AnalyticEvaluator, RangeCheck) recognise via isCategoricalMixture and treat as a scalar RV with the categorical distribution probs over outcomes.

Validation:

  • probs and outcomes must be non-null, same length, length ≥ 1.
  • Each probs[i] must be finite, in [0, 1], and the array must sum to 1 within 1e-9.
  • Each outcomes[i] must be finite.

Each call mints a fresh key gate and a fresh set of mulinputs, so two calls to categorical with the same arrays are independent categorical RVs. The marking is VOLATILE accordingly.

Degenerate case: a categorical with exactly one positive-mass outcome reduces to as_random(v) at construction (the block would just be a single mulinput, which is operationally a Dirac point mass). Two such calls share the gate_value UUID via the v5 convention as_random already uses.

See also
mixture for the Bernoulli-weighted choice constructor.
Wikipedia: Categorical distribution
Source code
provsql.sql line 4363

◆ categorical_from_log_pmf()

random_variable provsql.categorical_from_log_pmf ( DOUBLE_PRECISION[] outcomes,
DOUBLE_PRECISION[] log_pmf )

Build a discrete (categorical) random variable from outcomes and UNNORMALISED log-masses.

The shared back end of the discrete count constructors (poisson, binomial, geometric, hypergeometric, negative_binomial), and directly usable for any custom discrete pmf: the log-masses are shifted by their maximum (so only relative magnitudes matter and no exp underflows), outcomes whose relative mass is below 1e-15 are dropped, and the rest is renormalised before being handed to categorical. Working in log space keeps arbitrarily large parameters stable (e.g. a Poisson(1000) pmf whose linear-space recurrence would underflow at exp(-1000)).

Parameters
outcomesoutcome values, same length as log_pmf
log_pmfnatural logs of the (unnormalised) masses
Source code
provsql.sql line 3810

◆ chi_squared()

random_variable provsql.chi_squared ( DOUBLE PRECISION k)

Construct a chi-squared random variable with k degrees of freedom: syntactic sugar for gamma(k/2, 1/2).

k is accepted as double precision so fractional degrees of freedom work; it must be finite and strictly positive. Even degrees of freedom route through erlang via gamma's INTEGER-shape rule.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Chi-squared distribution
Source code
provsql.sql line 3571

◆ corr()

VOID provsql.corr ( random_variable ,
random_variable  )

◆ corr_rv_ffunc()

random_variable provsql.corr_rv_ffunc ( UUID[] state)

Final function for corr(random_variable, random_variable): \(\mathrm{covar\_pop} / \sqrt{\max(v_x v_y, 0)}\) (a zero-variance world divides to \(\pm\infty\) / NaN, the undefined-world convention, matching SQL's NULL for a zero-stddev input).

Source code
provsql.sql line 6349

◆ covar_pop()

VOID provsql.covar_pop ( random_variable ,
random_variable  )

◆ covar_pop_rv_ffunc()

random_variable provsql.covar_pop_rv_ffunc ( UUID[] state)

◆ covar_samp()

VOID provsql.covar_samp ( random_variable ,
random_variable  )

◆ covar_samp_rv_ffunc()

random_variable provsql.covar_samp_rv_ffunc ( UUID[] state)

Final function for covar_samp(random_variable, random_variable): \((SXY - SX\,SY/N) / (N-1)\).

Source code
provsql.sql line 6323

◆ empirical_cdf()

random_variable provsql.empirical_cdf ( DOUBLE_PRECISION[] grid,
DOUBLE_PRECISION[] cdf )

Empirical-CDF constructor: a piecewise-linear CDF table as a random_variable.

Loads a tabulated CDF – simulation output percentile tables, risk models, expert-elicited forecasts – as the distribution whose CDF is cdf[i] at grid[i], linear in between: mass cdf[i+1] - cdf[i] spread uniformly over (grid[i], grid[i+1]), plus (when cdf[1] > 0) an atom of mass cdf[1] at grid[1] for the probability at or below the grid start. Packaged, like gmm, as a stick-breaking cascade of Bernoulli mixture nodes over uniform components (and the optional as_random atom), so moments and sampling are exact through the existing mixture machinery; comparisons ride Monte Carlo.

provsql.empirical_cdf(
grid => ARRAY[0.0, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0],
cdf => ARRAY[0.32, 0.51, 0.67, 0.82, 0.94, 0.99, 1.0])

Validation: same-length arrays of at least two entries, grid strictly increasing and finite, cdf non-decreasing within [0, 1] and ending at 1 within 1e-9.

See also
gmm, empirical_samples
Wikipedia: Cumulative distribution function
Source code
provsql.sql line 4651

◆ empirical_samples()

random_variable provsql.empirical_samples ( DOUBLE_PRECISION[] samples)

Empirical-samples constructor: the ecdf of a sample bundle as a random_variable.

Loads a Monte Carlo / MCMC / bootstrap sample array as the discrete distribution putting mass 1/n on each draw (duplicates merge, so a value drawn k times carries k/n) – the standard empirical distribution. Reduces entirely to categorical, so the whole exact discrete surface applies: moments are the sample moments, comparisons against constants are decided analytically ("fraction of samples below c"), and quantiles are the exact empirical quantiles.

-- Bulk load via array_agg over a sample table
INSERT INTO model_posteriors
SELECT param, provsql.empirical_samples(array_agg(value))
FROM mcmc_chain GROUP BY param;

At most 10000 distinct values (the categorical block cap): thin the chain or bin the samples (e.g. with width_bucket) beyond that.

See also
categorical, empirical_cdf
Wikipedia: Empirical distribution function
Source code
provsql.sql line 4575

◆ erlang()

random_variable provsql.erlang ( INTEGER k,
DOUBLE PRECISION lambda )

Construct an Erlang-distribution random variable, sum of k i.i.d.

exponentials with shared rate lambda

The Erlang distribution is the sum of k independent Exp(λ) random variables (equivalently the gamma with INTEGER shape). It is the natural closure of i.i.d. exponentials under addition, and is materialised here as a single gate_rv so the analytic CDF and closed-form moments fire directly (rather than the sampler having to draw and sum k exponential leaves per Monte-Carlo iteration).

Validation:

  • k must be ≥ 1. The degenerate k=1 case is silently routed through exponential so erlang(1, λ) shares its gate with exponential(λ).
  • lambda must be finite and strictly positive.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Erlang distribution
Source code
provsql.sql line 3484

◆ evidence()

DOUBLE PRECISION provsql.evidence ( UUID evidence)

Marginal likelihood P(data) of an evidence circuit.

The mean raw importance weight over provsql.rv_mc_samples prior draws – the same quantity rejection conditioning computes as P(C), now the product of the observations' densities. evidence is an and_agg conjunction of observe tokens (and/or Boolean events).

Source code
provsql.sql line 5487

◆ evidence_as_observation()

UUID provsql.evidence_as_observation ( UUID ev)

Internal: rewrite a point-equality conditioning event into an observation.

If ev is a gate_cmp with the "=" operator, one side a bare gate_rv leaf and the other a constant, return observe(leaf, const); otherwise return ev unchanged.

This is the bridge that makes the natural equality form the surface for likelihood-weighting conditioning: "X | (Y = c)" and "given(Y = c)" both produce a gate_cmp, which this turns into density evidence. A point event on a bare leaf is only meaningful as an observation (a continuous "Y = c" is measure-zero as a Boolean selection), so the rewrite is unambiguous. Non-equality / non-leaf events pass through as ordinary Boolean conditioning.

Source code
provsql.sql line 5370

◆ exp()

random_variable provsql.exp ( random_variable a)

e^x for a random_variable (gate_arith EXP).

Total.

Source code
provsql.sql line 4914

◆ exponential() [1/2]

random_variable provsql.exponential ( DOUBLE PRECISION lambda)

Construct an exponential-distribution random variable with rate λ

Validation:

  • lambda must be finite and strictly positive. No degenerate form exists for the exponential distribution, so there is no silent route through as_random.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Exponential distribution
Source code
provsql.sql line 3220

◆ exponential() [2/2]

random_variable provsql.exponential ( random_variable lambda)

exponential(lambda)

◆ extremum_rv_ffunc()

random_variable provsql.extremum_rv_ffunc ( UUID[] state,
INTEGER op,
DOUBLE PRECISION identity )

Final function for max(random_variable) / min(random_variable): fold a gate_arith MAX / MIN root over the per-row contributions.

The order-statistic analogues of sum / product:

\[ \mathrm{MAX}(x) = \max_{i : \varphi_i} X_i, \qquad \mathrm{MIN}(x) = \min_{i : \varphi_i} X_i. \]

A row absent in a world (its provenance \(\varphi_i\) false) must not perturb the extremum, so it contributes the order-statistic identity \(\mp\infty\). That identity is baked into each per-row contribution upstream: a provenance-tracked query wraps the argument as mixture(prov_i, X_i, as_random(∓∞)) (via the three-argument rv_aggregate_semimod), and an untracked call passes the raw RV through. So the FFUNC is a plain fold with no gate inspection: gate_arith(op, state).

Empty group: the identity as_random(identity) ( \(-\infty\) / \(+\infty\)), the extremum counterpart to sum's as_random(0). Singleton group: the single child directly.

Source code
provsql.sql line 6069

◆ gamma() [1/4]

random_variable provsql.gamma ( DOUBLE PRECISION k,
DOUBLE PRECISION lambda )

Construct a gamma-distribution random variable with shape k (any positive real) and rate lambda.

The gamma distribution generalises Erlang to non-INTEGER shape; its CDF is the regularised lower incomplete gamma, evaluated in closed form by the analytic passes. Sums of independent gammas with the same rate fold to a single gamma in the simplifier.

Validation:

  • k must be finite and strictly positive. An INTEGER k (in INTEGER range) is silently routed through erlang – the gamma with INTEGER shape is Erlang – so gamma(2, λ) shares its gate encoding and closure interplay with erlang(2, λ).
  • lambda must be finite and strictly positive.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Gamma distribution
Source code
provsql.sql line 3225

◆ gamma() [2/4]

random_variable provsql.gamma ( DOUBLE PRECISION k,
random_variable lambda )

◆ gamma() [3/4]

random_variable provsql.gamma ( random_variable k,
DOUBLE PRECISION lambda )

gamma(k, lambda)

◆ gamma() [4/4]

random_variable provsql.gamma ( random_variable k,
random_variable lambda )

◆ geometric() [1/2]

random_variable provsql.geometric ( DOUBLE PRECISION p)

Construct a Geometric(p) random variable – the number of TRIALS up to and including the first success (support starting at 1; subtract 1 for the failures convention).

P(X = k) = (1-p)^{k-1} p, enumerated up to the 1e-15 relative-mass tail and renormalised. p = 1 is a Dirac at 1.

See also
Wikipedia: Geometric distribution
Source code
provsql.sql line 4030

◆ geometric() [2/2]

random_variable provsql.geometric ( random_variable p)

Geometric with a LATENT success probability: geometric(random_variable).

A latent (token-valued) p cannot be enumerated at construction, so this builds a parametric gate_rv leaf (family "geometric") wiring the probability, resolved per draw by the sampler. observe weights by the geometric pmf; unblocks a Beta-Geometric conjugate posterior.

Source code
provsql.sql line 4030

◆ gmm()

random_variable provsql.gmm ( DOUBLE_PRECISION[] weights,
DOUBLE_PRECISION[] means,
DOUBLE_PRECISION[] stddevs )

Gaussian-mixture-model (GMM) constructor.

Packages the common fitted-density pattern – a categorical choice among Normal components – into one call:

provsql.gmm(weights => ARRAY[0.3, 0.5, 0.2],
means => ARRAY[120.0, 380.0, 1200.0],
stddevs => ARRAY[40.0, 90.0, 250.0])

No new gate: the mixture decomposes into a stick-breaking cascade of Bernoulli gate_mixture nodes over gate_rv Normal leaves (component i is selected with conditional probability w_i / (w_i + ... + w_n), so the joint selection probabilities are exactly weights), which every evaluator already handles: moments are closed-form through the mixture recursion, sampling is exact, and comparisons ride the existing mixture machinery. Zero-weight components are skipped; a single positive-weight component returns its Normal directly (no mixture node).

Validation mirrors categorical: same-length non-empty arrays, weights finite in [0, 1] summing to 1 within 1e-9; the component parameters are validated by provsql.normal (finite mu, non-negative sigma; sigma = 0 degenerates to a Dirac component).

See also
mixture, categorical, normal
Wikipedia: Mixture model
Source code
provsql.sql line 4494

◆ greatest()

CREATE OR REPLACE FUNCTION provsql.greatest ( VARIADIC args random_variable[])

"greatest" / "least" are col_name keywords, so the CREATE FUNCTION name must be quoted; callers reach them qualified as provsql.greatest(...).

Idempotence: max / min ignore repeats, so identical children (same gate) are de-duplicated ///< greatest(x, x, y) == greatest(x, y) ///< and a single surviving child collapses to itself ///< greatest(x) == x. DISTINCT also sorts the children, so the argument order does not matter for gate sharing. (Two independent draws of the same distribution are distinct gates and are NOT de-duplicated.)

Build a random_variable from a guarded-selection gate_case.

Thin random_variable wrapper over provenance_case (defined with the other gate builders, since it is UUID-only), the target of the planner-hook CASE-over-RV rewrite: the hook flattens the branches into [guard_1, value_1, ..., default] and emits this call so an RV-typed CASE surfaces as a first-class random_variable.

Source code
provsql.sql line 5706

◆ hypergeometric()

random_variable provsql.hypergeometric ( INTEGER pop_n,
INTEGER k_marked,
INTEGER n )

Construct a Hypergeometric(N, K, n) random variable: the number of marked items among n draws WITHOUT replacement from a population of pop_n items of which k_marked are marked.

The exact finite support [max(0, n-(N-K)), min(n, K)] is enumerated by the pmf ratio recurrence (in log space, so large populations cannot overflow) and normalised – exact "sampling without replacement" probabilities with no combinatorial functions needed.

See also
Wikipedia: Hypergeometric distribution
Source code
provsql.sql line 4084

◆ inverse_gamma() [1/4]

random_variable provsql.inverse_gamma ( DOUBLE PRECISION alpha,
DOUBLE PRECISION beta )

Construct an inverse-gamma random variable with shape alpha and scale beta.

The distribution of 1/Y for Y ~ gamma(alpha, beta) (the conjugate prior for a Gaussian variance). Its CDF is the regularised upper incomplete gamma, evaluated in closed form by the analytic passes; raw moments are infinite for alpha <= k and reported as Infinity (the mean for alpha <= 1, the variance for alpha <= 2) rather than estimated. Positive scalings rescale beta in the simplifier.

Validation: both parameters must be finite and strictly positive.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Inverse-gamma distribution
Source code
provsql.sql line 3280

◆ inverse_gamma() [2/4]

random_variable provsql.inverse_gamma ( DOUBLE PRECISION alpha,
random_variable beta )

◆ inverse_gamma() [3/4]

random_variable provsql.inverse_gamma ( random_variable alpha,
DOUBLE PRECISION beta )

inverse_gamma(alpha, beta)

◆ inverse_gamma() [4/4]

random_variable provsql.inverse_gamma ( random_variable alpha,
random_variable beta )

◆ inverse_gaussian() [1/4]

random_variable provsql.inverse_gaussian ( DOUBLE PRECISION mu,
DOUBLE PRECISION lambda )

Construct an inverse-Gaussian (Wald) random variable with mean mu and shape lambda.

The first-passage time of Brownian motion with drift: a positive, right-skewed family. Its CDF has a closed form in the standard normal Phi, so comparisons and quantiles are analytic; all raw moments are finite. Positive scalings map c·IG(mu, lambda) to IG(c·mu, c·lambda), and a sum of independent inverse Gaussians sharing the ratio lambda/mu² folds to a single inverse Gaussian in the simplifier. wald is an alias.

Validation: both parameters must be finite and strictly positive.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Inverse Gaussian distribution
Source code
provsql.sql line 3291

◆ inverse_gaussian() [2/4]

random_variable provsql.inverse_gaussian ( DOUBLE PRECISION mu,
random_variable lambda )

◆ inverse_gaussian() [3/4]

random_variable provsql.inverse_gaussian ( random_variable mu,
DOUBLE PRECISION lambda )

inverse_gaussian(mu, lambda)

◆ inverse_gaussian() [4/4]

random_variable provsql.inverse_gaussian ( random_variable mu,
random_variable lambda )

◆ is_finite_float8()

BOOL provsql.is_finite_float8 ( DOUBLE PRECISION x)

Internal: true iff x is a finite (non-NaN, non-±∞) float8.

PostgreSQL's isnan is defined for NUMERIC only, not for DOUBLE PRECISION; we use the inequality form, which works because PG defines NaN = NaN as TRUE for floats (so NaN <> 'NaN'::float8 is FALSE).

Source code
provsql.sql line 3089

◆ ln()

random_variable provsql.ln ( random_variable a)

Natural logarithm of a random_variable (gate_arith LN).

Defined on [0, +Infinity): evaluation raises if a negative value is drawn (restrict the argument's support); a draw of exactly 0 yields -Infinity.

Source code
provsql.sql line 4904

◆ logistic() [1/4]

random_variable provsql.logistic ( DOUBLE PRECISION mu,
DOUBLE PRECISION s )

Construct a logistic-distribution random variable Logistic(μ, s).

The location-scale family whose CDF is the logistic sigmoid; a threshold event over a Logistic(0, 1) noise realises the logit link exactly (P(eps < score) = 1/(1 + exp(-score))), the natural link for a log-odds / latent-utility selection model.

Validation:

  • mu and s must be finite.
  • s (the scale) must be non-negative; s = 0 is the Dirac at mu, routed through as_random(mu) as with normal's sigma = 0.
Parameters
mulocation (the mean and median).
sscale (> 0); the variance is \(\pi^2 s^2 / 3\).
Returns
a random_variable token for Logistic(μ, s).
See also
Wikipedia: Logistic distribution
Source code
provsql.sql line 3198

◆ logistic() [2/4]

random_variable provsql.logistic ( DOUBLE PRECISION mu,
random_variable s )

◆ logistic() [3/4]

random_variable provsql.logistic ( random_variable mu,
DOUBLE PRECISION s )

logistic(mu, s)

◆ logistic() [4/4]

random_variable provsql.logistic ( random_variable mu,
random_variable s )

◆ lognormal() [1/4]

random_variable provsql.lognormal ( DOUBLE PRECISION mu,
DOUBLE PRECISION sigma )

Construct a log-normal random variable: exp of a Normal(mu, sigma), parameterised by the underlying normal (so its median is exp(mu) and its mean exp(mu + sigma^2/2)).

The multiplicative counterpart of normal: products of independent lognormals fold to a lognormal in the simplifier, and the exp(normal(...)) / ln(lognormal(...)) bridges fold in both directions, so log-scale models stay closed-form.

Validation mirrors normal: both parameters must be finite, sigma non-negative; the degenerate sigma = 0 case is silently routed through as_random (a Dirac at exp(mu)).

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Log-normal distribution
Source code
provsql.sql line 3236

◆ lognormal() [2/4]

random_variable provsql.lognormal ( DOUBLE PRECISION mu,
random_variable sigma )

◆ lognormal() [3/4]

random_variable provsql.lognormal ( random_variable mu,
DOUBLE PRECISION sigma )

lognormal(mu, sigma)

◆ lognormal() [4/4]

random_variable provsql.lognormal ( random_variable mu,
random_variable sigma )

◆ max()

VOID provsql.max ( random_variable )

◆ max_rv_ffunc()

random_variable provsql.max_rv_ffunc ( UUID[] state)

◆ min()

VOID provsql.min ( random_variable )

◆ min_rv_ffunc()

random_variable provsql.min_rv_ffunc ( UUID[] state)

◆ mixture() [1/2]

random_variable provsql.mixture ( DOUBLE PRECISION p_value,
random_variable x,
random_variable y )

Ad-hoc mixture constructor that mints a fresh anonymous gate_input Bernoulli with probability p_value.

Sugar over the mixture(UUID, x, y) form: when the caller doesn't care about reusing the Bernoulli token elsewhere in the circuit (which is the common case – "give me a 0.3 / 0.7 weighted GMM, I don't need to share the coin"), this overload creates the underlying gate_input on the fly with a fresh uuid_generate_v4() token, pins p_value via set_prob, and threads everything into the UUID-keyed constructor.

Each call mints a NEW Bernoulli, so two calls to mixture(0.5, X, Y) are independent mixtures whose branch selections are uncorrelated. When coupling is desired (e.g. two mixtures sharing a coin), use the mixture(UUID, x, y) form with a user-managed gate_input token.

Warning
VOLATILE is load-bearing for the same reason as normal and the other RV constructors – folding under STABLE / IMMUTABLE would collapse two independent draws into one shared gate.
See also
Wikipedia: Mixture distribution
Source code
provsql.sql line 4247

◆ mixture() [2/2]

random_variable provsql.mixture ( UUID p,
random_variable x,
random_variable y )

Construct a probabilistic-mixture random variable.

Returns a random_variable whose distribution is a Bernoulli mixture of two scalar RV roots: with probability P(p = true) the mixture samples x, with the complementary probability it samples y. The mixing token p is a gate_input Bernoulli whose probability has been pinned with set_prob, and the same p can be shared with other branches of the circuit – the Monte-Carlo sampler's per-iteration cache couples every reference to the same draw, so users can build joint conditional structures (e.g. mixture(p, X1, Y1) + mixture(p, X2, Y2) samples X1 + X2 with prob π and Y1 + Y2 with prob 1-π).

x and y may be any scalar RV root: a base gate_rv (normal / uniform / exponential / erlang), a gate_value Dirac (as_random), a gate_arith expression, or another mixture. N-ary mixtures are built by composition – mixture(p1, A, mixture(p2, B, C)) realises a 3-component mixture with effective weights π1, (1-π1)·π2, (1-π1)·(1-π2).

Validation:

  • p must point to a Boolean gate (input, mulinput, update, plus, times, monus, project, eq, cmp, zero, one). Compound Boolean gates derive their probability from their atoms via the active probability-evaluation method; a bare gate_input's probability is whatever set_prob pinned (set_prob is responsible for keeping it in [0, 1]).
  • x and y must be scalar RV roots; aggregate / Boolean roots are rejected at construction.

Two calls to mixture with the same (p, x, y) operands collapse to the same gate_mixture node by v5-hash, exactly like arith(PLUS, X, Y). Draw independence is controlled by p: sharing p couples branch selection across consumers via the sampler's bool_cache_; minting independent Bernoullis (e.g. via the mixture(p_value, …) overload) decouples them.

See also
Wikipedia: Mixture distribution
Source code
provsql.sql line 4247

◆ negative_binomial() [1/4]

random_variable provsql.negative_binomial ( DOUBLE PRECISION r,
DOUBLE PRECISION p )

Construct a negative-binomial random variable: the number of FAILURES before the r-th success (support starting at 0), with real r > 0 allowed (the Polya / overdispersed-count parameterisation, the Poisson-Gamma mixture).

P(X = k) = C(k+r-1, k) p^r (1-p)^k, enumerated by the log-space recurrence ln p(k+1) = ln p(k) + ln((k+r)/(k+1)) + ln(1-p) up to the 1e-15 relative-mass tail. p = 1 is a Dirac at 0.

See also
Wikipedia: Negative binomial distribution
Source code
provsql.sql line 4131

◆ negative_binomial() [2/4]

random_variable provsql.negative_binomial ( DOUBLE PRECISION r,
random_variable p )

◆ negative_binomial() [3/4]

random_variable provsql.negative_binomial ( random_variable r,
DOUBLE PRECISION p )

◆ negative_binomial() [4/4]

random_variable provsql.negative_binomial ( random_variable r,
random_variable p )

◆ normal() [1/4]

random_variable provsql.normal ( DOUBLE PRECISION mu,
DOUBLE PRECISION sigma )

Construct a normal-distribution random variable.

Creates a fresh gate_rv with "normal:μ,σ" stored in the gate's extra field, and returns a random_variable pointing at it.

Validation:

  • mu and sigma must be finite (no NaN, no ±Infinity).
  • sigma must be non-negative.
  • When sigma is zero the distribution degenerates to the Dirac at mu; the call is silently routed through as_random(mu), producing a gate_value rather than a zero-variance gate_rv. This keeps the sampler / moment / boundcheck paths free of σ=0 special cases and lets normal(x, 0) share its gate with as_random(x).
Warning
The VOLATILE marking is load-bearing and must not be weakened. Each call mints a fresh uuid_generate_v4 token because two calls to normal(0, 1) are independent random variables; if PostgreSQL were allowed to fold the function (which it would under STABLE / IMMUTABLE), two calls in the same query would share a UUID and collapse into a single dependent RV, silently breaking the c-table semantics. Same warning applies to uniform and exponential below.
See also
Wikipedia: Normal distribution
Source code
provsql.sql line 3187

◆ normal() [2/4]

random_variable provsql.normal ( DOUBLE PRECISION mu,
random_variable sigma )

◆ normal() [3/4]

random_variable provsql.normal ( random_variable mu,
DOUBLE PRECISION sigma )

normal(mu, sigma)

◆ normal() [4/4]

random_variable provsql.normal ( random_variable mu,
random_variable sigma )

◆ observe()

UUID provsql.observe ( random_variable x,
DOUBLE PRECISION datum )

Internal: bind an observed datum to a random-variable leaf – the likelihood-weighting evidence behind "X | (Y = d)".

x MUST be a bare gate_rv leaf (typically a latent-parameterised one, e.g. normal(mu, 1) sharing a latent mu across rows). Returns an evidence UUID – a gate_observe wrapping the leaf with the datum in extra – that composes with other evidence through and_agg (a gate_times conjunction) and is consumed by the importance-sampling weight walk, contributing the factor f_X(d).

Internal: the user-facing surface is the equality form "X | (Y = d)" (single conditioning) and "given(Y = d)" (per-row evidence for and_agg), both of which route here through evidence_as_observation.

A fresh gate is minted per call (each observation is a distinct evidence atom, so a repeated (leaf, datum) contributes its density factor once per row – and each is a separate Shapley atom). Observing a derived quantity (observe(X+Y, d)) is out of scope: it needs a change-of-variables density; a non-leaf argument is refused.

Source code
provsql.sql line 5428

◆ observe_atoms()

UUID[] provsql.observe_atoms ( UUID evidence)

The observe atoms of an evidence circuit.

Collects every gate_observe leaf reachable through the gate_times conjunction spine (the shape and_agg builds – a possibly left-nested tree, since provenance_times does not flatten). Used by shapley_observe to recover the flat observation set regardless of the conjunction's nesting.

Source code
provsql.sql line 5500

◆ pareto() [1/4]

random_variable provsql.pareto ( DOUBLE PRECISION xm,
DOUBLE PRECISION alpha )

Construct a Pareto random variable with scale (minimum) xm and shape alpha.

The canonical heavy-tailed power law. Raw moments are infinite for alpha <= k and reported as Infinity (the mean for alpha <= 1, the variance for alpha <= 2) rather than estimated; quantiles, truncated moments, conditional sampling (self-similarity: X | X > a is Pareto(a, alpha)), and Pareto-vs-Pareto comparisons are all exact.

Validation: both parameters must be finite and strictly positive.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Pareto distribution
Source code
provsql.sql line 3258

◆ pareto() [2/4]

random_variable provsql.pareto ( DOUBLE PRECISION xm,
random_variable alpha )

◆ pareto() [3/4]

random_variable provsql.pareto ( random_variable xm,
DOUBLE PRECISION alpha )

pareto(xm, alpha)

◆ pareto() [4/4]

random_variable provsql.pareto ( random_variable xm,
random_variable alpha )

◆ percentile_cont()

VOID provsql.percentile_cont ( DOUBLE PRECISION ORDER BY random_variable)

◆ percentile_cont_rv_ffunc()

random_variable provsql.percentile_cont_rv_ffunc ( UUID[] state,
DOUBLE PRECISION fraction )

Final function for the public ordered-set percentile_cont: receives the direct fraction argument after the state.

Source code
provsql.sql line 6536

◆ percentile_cont_rv_sfunc()

UUID[] provsql.percentile_cont_rv_sfunc ( UUID[] state,
random_variable x )

State transition for the public ordered-set percentile_cont(float8) WITHIN GROUP (ORDER BY random_variable): append the certain indicator and the row's RV.

Only reachable on untracked input (a provenance-tracked query is rewritten to rv_percentile_impl before planning), where the sort over random_variable raises the ordering-is-meaningless diagnostic first – so in practice this runs only for empty input.

Source code
provsql.sql line 6527

◆ poisson() [1/2]

random_variable provsql.poisson ( DOUBLE PRECISION lambda)

Construct a Poisson random variable with mean lambda, as a truncated categorical.

The pmf is enumerated over [max(0, λ-12√λ), λ+12√λ+30] (the omitted tails carry ~1e-30 of mass) by the log-space recurrence ln p(k+1) = ln p(k) + ln λ - ln(k+1) and handed to categorical_from_log_pmf, so moments, quantiles, and (in)equality comparisons are exact over the enumerated support. lambda = 0 is a Dirac at 0 (routed through as_random); supports up to 10000 outcomes (λ up to ~170000), beyond which it raises – approximate huge means by normal(λ, √λ) instead.

See also
Wikipedia: Poisson distribution
Source code
provsql.sql line 3862

◆ poisson() [2/2]

random_variable provsql.poisson ( random_variable lambda)

Poisson with a LATENT rate: poisson(random_variable).

A latent (token-valued) rate cannot be enumerated into a categorical at construction, so this builds a parametric gate_rv leaf (family "poisson") wiring the rate, exactly like the continuous latent constructors. Only the Monte Carlo sampler resolves the rate (per draw, then draws a Poisson); observe weights by the Poisson pmf; the mean is exact (E[Poisson(Λ)] = E[Λ], affine). Unblocks discrete-likelihood posteriors such as "R | (poisson(120*R) = observed_count)".

Source code
provsql.sql line 3862

◆ pow()

random_variable provsql.pow ( random_variable a,
random_variable b )

pow / power spellings of the ^ operator, mirroring PostgreSQL's NUMERIC surface.

Scalar exponents resolve through the implicit NUMERIC-to-rv casts: pow(x, 0.5) is x ^ 0.5.

Source code
provsql.sql line 4929

◆ power()

random_variable provsql.power ( random_variable a,
random_variable b )

◆ product()

VOID provsql.product ( random_variable )

◆ product_rv_ffunc()

random_variable provsql.product_rv_ffunc ( UUID[] state)

Final function for product(random_variable): fold a gate_arith TIMES root over the per-row contributions.

Multiplicative analogue of sum(random_variable):

\[ \mathrm{PRODUCT}(x) \;=\; \prod_i \big(\mathbf{1}\{\varphi_i\} \cdot X_i + \mathbf{1}\{\neg\varphi_i\} \cdot 1\big) \;=\; \prod_{i : \varphi_i} X_i. \]

Each per-row contribution already carries the multiplicative identity as its absent-row value: a provenance-tracked query wraps the argument as mixture(prov_i, X_i, as_random(1)) (identity baked in by the three-argument rv_aggregate_semimod), and an untracked call passes the raw RV through. So the FFUNC is a plain fold with no gate inspection: gate_arith(TIMES, state).

Reuses sum_rv_sfunc as the state-transition function. Empty group: the multiplicative identity as_random(1) – the counterpart to sum's empty-group as_random(0). Singleton group: the single child directly, without a one-child TIMES root.

Source code
provsql.sql line 6025

◆ random_variable_btree_cmp()

INTEGER provsql.random_variable_btree_cmp ( random_variable a,
random_variable b )

btree comparison support for random_variable – always an error.

A random_variable is a distribution, not a scalar, so it has no total order: sorting (ORDER BY), de-duplicating (DISTINCT), grouping, and the built-in GREATEST / LEAST all reduce to this btree comparison proc, which raises a clear diagnostic rather than a placeholder message.

The proc exists only so a DEFAULT btree operator class can be declared for random_variable – which is what lets PostgreSQL's GREATEST / LEAST grammar parse over random variables so the planner hook can lift it into a gate_arith MAX / MIN order statistic. When the hook is active the GREATEST / LEAST node is rewritten before it ever calls this proc.

Source code
provsql.sql line 5185

◆ random_variable_cmp_oid()

oid provsql.random_variable_cmp_oid ( TEXT sym)

Internal helper: float8-comparator OID for a given symbol.

Wraps the '<sym>(DOUBLE PRECISION,DOUBLE PRECISION)'::regoperator lookup so the per-comparator functions read uniformly. Marked IMMUTABLE because the resolved OID is fixed at catalog level (the float8 comparators are core PG and never re-installed).

Source code
provsql.sql line 4960

◆ random_variable_cmp_placeholder()

BOOLEAN provsql.random_variable_cmp_placeholder ( random_variable a,
random_variable b )

Placeholder body shared by every random_variable_* comparison procedure.

Raises with a uniform message.

Source code
provsql.sql line 4980

◆ random_variable_cond()

random_variable provsql.random_variable_cond ( random_variable rv,
UUID cond )

Condition a random variable on an event: "X | C".

Returns a conditioned distribution that flows onward like any other random_variable: it can be stored, re-conditioned, and queried with expected / variance / moment / support, which then report the conditional distribution. cond is a Boolean-event provenance token, typically a comparison over the variable itself ("X | rv_cmp_gt(X, as_random(3))" – a truncation) or any external event.

Unlike the UUID carrier's terminal cond, the random-variable form is a composable two-child gate_conditioned [target, condition]: the moment / support dispatchers unpack it and route through the existing conditional evaluator (rv_moment over the joint of the target and the condition). Nested conditioning folds: "(X|A)|B = X|(A∧B)".

Source code
provsql.sql line 5229

◆ random_variable_cond_predicate()

random_variable provsql.random_variable_cond_predicate ( random_variable rv,
BOOLEAN predicate )

Placeholder for "X | (predicate)" – conditioning a random variable on a Boolean comparison written naturally.

Lets one write "X | (X > 3)" instead of "X | rv_cmp_gt(X, as_random(3))". Never executes: the ProvSQL planner hook rewrites the Boolean operand (a combination of random_variable comparisons) into the corresponding condition gate and emits random_variable_cond. Reaching it at runtime means the rewriter was inactive or the predicate was not a random_variable comparison.

Source code
provsql.sql line 5287

◆ random_variable_div()

random_variable provsql.random_variable_div ( random_variable a,
random_variable b )

random_variable / random_variable (gate_arith DIV).

Source code
provsql.sql line 4858

◆ random_variable_eq()

BOOLEAN provsql.random_variable_eq ( random_variable a,
random_variable b )

◆ random_variable_eq_random_variable()

BOOLEAN provsql.random_variable_eq_random_variable ( random_variable left,
random_variable right )

◆ random_variable_ge()

BOOLEAN provsql.random_variable_ge ( random_variable a,
random_variable b )

◆ random_variable_ge_random_variable()

BOOLEAN provsql.random_variable_ge_random_variable ( random_variable left,
random_variable right )

◆ random_variable_gt()

BOOLEAN provsql.random_variable_gt ( random_variable a,
random_variable b )

◆ random_variable_gt_random_variable()

BOOLEAN provsql.random_variable_gt_random_variable ( random_variable left,
random_variable right )

◆ random_variable_in()

random_variable provsql.random_variable_in ( CSTRING )

Input function for the random_variable type.

Source code
provsql.sql line 3026

◆ random_variable_le()

BOOLEAN provsql.random_variable_le ( random_variable a,
random_variable b )

◆ random_variable_le_random_variable()

BOOLEAN provsql.random_variable_le_random_variable ( random_variable left,
random_variable right )

◆ random_variable_lt()

BOOLEAN provsql.random_variable_lt ( random_variable a,
random_variable b )

◆ random_variable_lt_random_variable()

BOOLEAN provsql.random_variable_lt_random_variable ( random_variable left,
random_variable right )

◆ random_variable_make()

random_variable provsql.random_variable_make ( UUID tok)

Build a random_variable from a UUID (internal).

Source code
provsql.sql line 3043

◆ random_variable_minus()

random_variable provsql.random_variable_minus ( random_variable a,
random_variable b )

random_variable - random_variable (gate_arith MINUS).

Source code
provsql.sql line 4834

◆ random_variable_ne()

BOOLEAN provsql.random_variable_ne ( random_variable a,
random_variable b )

◆ random_variable_ne_random_variable()

BOOLEAN provsql.random_variable_ne_random_variable ( random_variable left,
random_variable right )

◆ random_variable_neg()

random_variable provsql.random_variable_neg ( random_variable a)

Unary -random_variable (gate_arith NEG).

Source code
provsql.sql line 4870

◆ random_variable_op_boolean()

BOOLEAN provsql.random_variable_op_boolean ( random_variable left,
BOOLEAN right )

◆ random_variable_op_random_variable()

BOOLEAN provsql.random_variable_op_random_variable ( random_variable left,
random_variable right )

Prefix unary minus on random_variable.

Source code
provsql.sql line 5085

◆ random_variable_op_uuid()

BOOLEAN provsql.random_variable_op_uuid ( random_variable left,
UUID right )

◆ random_variable_out()

CSTRING provsql.random_variable_out ( random_variable )

Output function for the random_variable type.

Source code
provsql.sql line 3031

◆ random_variable_plus()

random_variable provsql.random_variable_plus ( random_variable a,
random_variable b )

random_variable + random_variable (gate_arith PLUS).

Source code
provsql.sql line 4822

◆ random_variable_pow()

random_variable provsql.random_variable_pow ( random_variable a,
random_variable b )

random_variable ^ random_variable (gate_arith POW).

Real-valued branch only: evaluation raises if a negative base is drawn together with a non-INTEGER exponent (write pow(greatest(x, 0), p) for the non-negative branch).

Source code
provsql.sql line 4886

◆ random_variable_times()

random_variable provsql.random_variable_times ( random_variable a,
random_variable b )

random_variable * random_variable (gate_arith TIMES).

Source code
provsql.sql line 4846

◆ rv_aggregate_indicator() [1/2]

random_variable provsql.rv_aggregate_indicator ( UUID prov)

Per-row denominator wrap for avg(random_variable): the provenance indicator \(\mathbf{1}\{\varphi\}\).

The row contributes 1 to the running count when present and 0 when absent, so sum over these wraps is the provenance-weighted count \(\sum_i \mathbf{1}\{\varphi_i\}\). The planner-hook rewrites avg(x) into rv_sum_or_null(rv_aggregate_semimod(prov, x)) / sum(rv_aggregate_indicator(prov)) – the "@c AVG @c = @c SUM @c / @c COUNT" identity lifted into the random_variable algebra – so avg rides entirely on sum's fold and never inspects a gate.

Source code
provsql.sql line 5818

◆ rv_aggregate_indicator() [2/2]

random_variable provsql.rv_aggregate_indicator ( UUID prov,
random_variable rv )

Value-aware presence indicator: NULL when the row's aggregated value is NULL.

SQL aggregates skip NULL inputs, so a NULL random_variable cell must not count in avg's denominator: the wrap yields NULL (which the sum fold skips) exactly when the value is NULL, and the plain one-argument indicator otherwise. The planner-hook avg rewrite emits this form; the one-argument indicator remains for the internal public-form defaults.

Source code
provsql.sql line 5818

◆ rv_aggregate_semimod() [1/2]

random_variable provsql.rv_aggregate_semimod ( UUID prov,
random_variable rv )

Per-row helper: wrap an RV in mixture(prov, rv, as_random(0)).

Internal helper used by the planner-hook rewriter to lift a sum(random_variable) argument into its provenance-aware form. Encodes one row's contribution to the SUM as a Bernoulli mixture over the row's provenance: with probability P(prov) the mixture samples rv, otherwise it samples the additive identity as_random(0). Exposed as a regular SQL function so the planner can construct a FuncExpr by name without needing to disambiguate mixture / as_random overloads at OID-lookup time.

Source code
provsql.sql line 5780

◆ rv_aggregate_semimod() [2/2]

random_variable provsql.rv_aggregate_semimod ( UUID prov,
random_variable rv,
DOUBLE PRECISION identity )

Identity-parameterised per-row wrap for an RV-returning aggregate.

Generalises the two-argument rv_aggregate_semimod. The else-branch (a row's contribution when its provenance is false) is as_random(identity) instead of the additive as_random(0). The planner-hook rewrite bakes each aggregate's own identity element into the wrap – 1 for product, \(-\infty\) / \(+\infty\) for max / min – so the aggregate's final function is a plain fold over the per-row mixtures with no gate inspection. sum keeps the two-argument form (identity = 0).

Source code
provsql.sql line 5780

◆ rv_cmp_eq()

UUID provsql.rv_cmp_eq ( random_variable a,
random_variable b )

Build a gate_cmp for a = b and return its UUID.

Source code
provsql.sql line 5046

◆ rv_cmp_ge()

UUID provsql.rv_cmp_ge ( random_variable a,
random_variable b )

Build a gate_cmp for a ≥ b and return its UUID.

Source code
provsql.sql line 5066

◆ rv_cmp_gt()

UUID provsql.rv_cmp_gt ( random_variable a,
random_variable b )

Build a gate_cmp for a > b and return its UUID.

Source code
provsql.sql line 5076

◆ rv_cmp_le()

UUID provsql.rv_cmp_le ( random_variable a,
random_variable b )

Build a gate_cmp for a ≤ b and return its UUID.

Source code
provsql.sql line 5036

◆ rv_cmp_lt()

UUID provsql.rv_cmp_lt ( random_variable a,
random_variable b )

Build a gate_cmp for a < b and return its UUID.

Source code
provsql.sql line 5026

◆ rv_cmp_ne()

UUID provsql.rv_cmp_ne ( random_variable a,
random_variable b )

Build a gate_cmp for a <> b and return its UUID.

Source code
provsql.sql line 5056

◆ rv_conditioned_prov()

UUID provsql.rv_conditioned_prov ( UUID token,
UUID prov )

Combine a conditioning gate's event with an explicit prov.

For a two-child gate_conditioned [target, condition] returns "condition ∧ prov"; otherwise returns prov unchanged. Lets a stored "X | C" be queried as expected(X|C) (prov defaulting to one) or have an extra condition conjoined as expected(X|C, extra_prov).

Source code
provsql.sql line 5329

◆ rv_conditioned_target()

UUID provsql.rv_conditioned_target ( UUID token)

Unpack the target of a random-variable conditioning gate.

For a two-child gate_conditioned [target, condition] (the "X | C" shape) returns target; for any other token returns it unchanged. Used by the moment / support dispatchers to route a conditioned distribution through the existing conditional evaluator.

Source code
provsql.sql line 5311

◆ rv_corr_impl()

VOID provsql.rv_corr_impl ( random_variable ,
random_variable ,
random_variable  )

◆ rv_covar_pop_impl()

VOID provsql.rv_covar_pop_impl ( random_variable ,
random_variable ,
random_variable  )

The indicator-carrying rewrite targets (planner hook only; never called directly by users).

◆ rv_covar_samp_impl()

VOID provsql.rv_covar_samp_impl ( random_variable ,
random_variable ,
random_variable  )

◆ rv_families()

TABLE provsql.rv_families ( )

Catalog of the registered continuous-distribution families.

One row per gate_rv family known to this build of the extension: name is the on-disk token (the part before the colon in the gate's extra encoding), nparams the parameter count, param_names the conventional parameter symbols in extra order (e.g. {μ, σ}), and label a short display glyph (e.g. "N", "Γ"). UI clients (ProvSQL Studio's circuit inspector) read this to render families they were not hard-coded for, so a newly added family shows up without a client release.

Source code
provsql.sql line 4203

◆ rv_parametric1()

random_variable provsql.rv_parametric1 ( TEXT family,
UUID p_tok )

Internal: build a one-parameter latent gate_rv (rate/scale).

Source code
provsql.sql line 3163

◆ rv_parametric2()

random_variable provsql.rv_parametric2 ( TEXT family,
UUID p1_tok,
DOUBLE PRECISION p1_lit,
UUID p2_tok,
DOUBLE PRECISION p2_lit )

Internal: build a two-parameter latent gate_rv.

Each parameter is supplied as EITHER a token (pN_tok, a scalar gate UUID) OR a literal (pN_lit); exactly one is non-NULL per parameter. Token parameters are appended to the gate's wire vector in order and referenced as "$i" in the extra TEXT; literal parameters keep their decimal TEXT. Not STRICT: the NULLs are the literal-vs-token sentinels.

Source code
provsql.sql line 3121

◆ rv_percentile_impl()

VOID provsql.rv_percentile_impl ( DOUBLE PRECISION ,
random_variable ,
random_variable  )

◆ rv_percentile_impl_ffunc()

random_variable provsql.rv_percentile_impl_ffunc ( rv_percentile_state state)

Final function for rv_percentile_impl.

Source code
provsql.sql line 6580

◆ rv_percentile_impl_sfunc()

rv_percentile_state provsql.rv_percentile_impl_sfunc ( rv_percentile_state state,
DOUBLE PRECISION fraction,
random_variable ind,
random_variable x )

State transition for rv_percentile_impl, the planner-hook rewrite target of a provenance-tracked percentile_cont: stashes the (group-constant) fraction and appends the indicator/value pair.

Source code
provsql.sql line 6563

◆ rv_percentile_make()

random_variable provsql.rv_percentile_make ( DOUBLE PRECISION fraction,
UUID[] pairs )

Mint the PROVSQL_ARITH_PERCENTILE gate: the continuous percentile (SQL percentile_cont) over a group of RV rows.

pairs is the interleaved wire list [ind_1, x_1, ..., ind_n, x_n] (each ind_i a 0/1 presence-indicator RV). The fraction is TEXT-encoded in the gate's extra and participates in the token UUID (two percentiles of the same group at different fractions are distinct gates). Per Monte Carlo draw, the sampler collects the values whose indicator draws 1, sorts them, and linearly interpolates at the fraction; a draw with no present row is NaN (undefined world).

Source code
provsql.sql line 6495

◆ rv_stat1_impl_sfunc()

UUID[] provsql.rv_stat1_impl_sfunc ( UUID[] state,
random_variable ind,
random_variable x )

Indicator-carrying state transition for the one-argument rv_*_impl statistic aggregates: the planner-hook rewrite passes the row's provenance indicator rv_aggregate_indicator(prov) as ind.

Source code
provsql.sql line 6166

◆ rv_stat1_sfunc()

UUID[] provsql.rv_stat1_sfunc ( UUID[] state,
random_variable x )

SQL-standard statistic aggregates over random_variable rows: covar_pop / covar_samp / corr (two-argument), stddev_pop / stddev_samp (one-argument), and the ordered-set percentile_cont.

Row presence is carried by a per-row 0/1 indicator RV: the public aggregates use the certain indicator as_random(1) (every row present), and a provenance-tracked query is rewritten by the planner hook (make_rv_aggregate_expression) to the rv_*_impl aggregates whose extra leading argument is rv_aggregate_indicator(prov), so a row absent in a world drops out of every sum, the count, and the percentile member set. The moment statistics are built from indicator-weighted power sums with existing gate_arith opcodes (e.g. covar_pop = SXY/N - (SX/N)(SY/N)); a world where the statistic is undefined (N = 0, or N = 1 for the sample forms) evaluates to NaN, the established undefined-world convention the moment estimators skip. percentile_cont is the one gate the arithmetic cannot express: it mints the PROVSQL_ARITH_PERCENTILE gate_arith (interleaved [ind_1, x_1, ...] wires, fraction in extra) that the Monte Carlo sampler evaluates by sorting each draw's present values and interpolating.

State transition for the one-argument RV statistic aggregates (stddev_pop / stddev_samp): append the certain indicator and the row's RV as a pair. NULL rows are skipped (standard SQL).

Source code
provsql.sql line 6138

◆ rv_stat2_impl_sfunc()

UUID[] provsql.rv_stat2_impl_sfunc ( UUID[] state,
random_variable ind,
random_variable x,
random_variable y )

Indicator-carrying state transition for the two-argument rv_*_impl statistic aggregates.

Source code
provsql.sql line 6180

◆ rv_stat2_sfunc()

UUID[] provsql.rv_stat2_sfunc ( UUID[] state,
random_variable x,
random_variable y )

State transition for the two-argument RV statistic aggregates (covar_pop / covar_samp / corr): append the certain indicator and the row's RV pair as a triple.

Rows with either side NULL are skipped (standard SQL covariance semantics).

Source code
provsql.sql line 6152

◆ rv_stat_covar_pop_token()

UUID provsql.rv_stat_covar_pop_token ( UUID n_tok,
UUID sx_tok,
UUID sy_tok,
UUID sxy_tok )

Population-covariance gate \(SXY/N - (SX/N)(SY/N)\) from the power-sum tokens.

Source code
provsql.sql line 6293

◆ rv_stat_sqrt_token()

UUID provsql.rv_stat_sqrt_token ( UUID v_tok)

\(\sqrt{\max(v, 0)}\) gate over a variance token: the max-clamp removes the tiny negative values float error can produce (variance is mathematically non-negative), so the POW domain guard never fires.

Source code
provsql.sql line 6282

◆ rv_stat_sum_tokens()

VOID provsql.rv_stat_sum_tokens ( UUID[] state,
INTEGER stride,
OUT UUID n_tok,
OUT UUID sx_tok,
OUT UUID sxx_tok,
OUT UUID sy_tok,
OUT UUID sxy_tok,
OUT UUID syy_tok )

Mint the indicator-weighted power-sum gates shared by the covariance / stddev final functions.

state is the flat interleaved aggregate state – pairs [ind, x, ...] (stride 2) or triples [ind, x, y, ...] (stride 3). Emits gate_arith tokens for \(N = \sum_i \mathbf{1}_i\), \(SX = \sum_i \mathbf{1}_i x_i\), \(SXX = \sum_i \mathbf{1}_i x_i^2\) and, at stride 3, \(SY\), \(SXY\), \(SYY\). The per-row indicator gate is shared between \(N\) and every product it weighs, so the Monte Carlo per-iteration cache keeps the row's presence coupled across all the sums (and a repeated child [ind, x, x] reuses the same draw of x, giving \(x^2\), not two independent draws).

Source code
provsql.sql line 6207

◆ rv_stat_var_pop_token()

UUID provsql.rv_stat_var_pop_token ( UUID n_tok,
UUID s_tok,
UUID ss_tok )

Population-variance gate \(SXX/N - (SX/N)^2\) from the power-sum tokens.

Source code
provsql.sql line 6252

◆ rv_stat_var_samp_token()

UUID provsql.rv_stat_var_samp_token ( UUID n_tok,
UUID s_tok,
UUID ss_tok )

Sample-variance gate \((SXX - SX^2/N) / (N - 1)\) from the power-sum tokens (NaN in a world with \(N \le 1\), the undefined-world convention).

Source code
provsql.sql line 6266

◆ rv_stddev_pop_impl()

VOID provsql.rv_stddev_pop_impl ( random_variable ,
random_variable  )

◆ rv_stddev_samp_impl()

VOID provsql.rv_stddev_samp_impl ( random_variable ,
random_variable  )

◆ rv_sum_or_null()

VOID provsql.rv_sum_or_null ( random_variable )

◆ rv_sum_or_null_ffunc()

random_variable provsql.rv_sum_or_null_ffunc ( UUID[] state)

Numerator final function for the avg rewrite: sum, but NULL on an empty group.

Identical to sum_rv_ffunc except that an empty group returns NULL rather than the additive identity as_random(0). The planner-hook avg rewrite emits rv_sum_or_null(rv_aggregate_semimod(prov, x)) / sum(rv_aggregate_indicator(prov)); random_variable_div is STRICT, so an empty group propagates the numerator's NULL and avg is NULL – the standard SQL AVG convention – while a non-empty group behaves exactly like sum.

Source code
provsql.sql line 5911

◆ shapley_observe()

TABLE provsql.shapley_observe ( UUID target,
UUID evidence,
TEXT payoff = 'expected' )

Shapley attribution of each observation to a posterior moment.

"Which observation most shifted my posterior?" Because the importance weight is a product of per-observation density factors, dropping an observation is dropping one factor: the classical Shapley value of each gate_observe atom over the coalitional value function "v(S) = payoff(target | observations in S)" is the attribution, a byproduct of the same likelihood-weighting machinery (see the explainable-inference angle in the continuous-distributions notes).

target is the latent (its UUID); evidence is the and_agg conjunction of observe atoms; payoff is 'expected' or 'variance'. Returns each observation atom with its Shapley value; the values sum to "payoff(target | all data) - payoff(target)" (Shapley efficiency: the total shift from prior to posterior).

Exact enumeration over the 2^n observation subsets, so it is capped at n = 12 observations (sampling-based attribution for larger sets is future work); pin provsql.monte_carlo_seed so the coalitional value functions share common random numbers (lower-variance differences).

Source code
provsql.sql line 5537

◆ sqrt()

random_variable provsql.sqrt ( random_variable a)

Square root of a random_variable: sugar for x ^ 0.5 (no gate or opcode of its own).

Evaluation raises on a negative draw, like any non-INTEGER exponent.

Source code
provsql.sql line 4946

◆ stddev_pop()

VOID provsql.stddev_pop ( random_variable )

◆ stddev_pop_rv_ffunc()

random_variable provsql.stddev_pop_rv_ffunc ( UUID[] state)

Final function for stddev_pop(random_variable).

Source code
provsql.sql line 6372

◆ stddev_samp()

VOID provsql.stddev_samp ( random_variable )

◆ stddev_samp_rv_ffunc()

random_variable provsql.stddev_samp_rv_ffunc ( UUID[] state)

Final function for stddev_samp(random_variable).

Source code
provsql.sql line 6390

◆ sum()

VOID provsql.sum ( random_variable )

◆ sum_rv_ffunc()

random_variable provsql.sum_rv_ffunc ( UUID[] state)

Final function for sum(random_variable): build a gate_arith PLUS root.

Empty group (state = '{}'): return as_random(0), the additive identity, so SUM over zero rows is the deterministic scalar 0 – matches the AGG_TOKEN convention in agg_raw_moment.

Singleton group: return the single child directly without minting a useless single-child gate_arith.

Otherwise: build gate_arith(PLUS, state) via provenance_arith.

Source code
provsql.sql line 5874

◆ sum_rv_sfunc()

UUID[] provsql.sum_rv_sfunc ( UUID[] state,
random_variable rv )

State-transition function for sum(random_variable).

Appends the input RV's UUID to the running array. NULL inputs are skipped (matching standard SUM semantics). The aggregate's INITCOND is '{}' so the FINALFUNC always runs even on an empty group, which is what lets us return as_random(0) (the additive identity) for an empty SUM rather than NULL.

Source code
provsql.sql line 5851

◆ uniform() [1/4]

random_variable provsql.uniform ( DOUBLE PRECISION a,
DOUBLE PRECISION b )

Construct a uniform-distribution random variable on [a, b].

Validation:

  • a and b must be finite.
  • a must be ≤ b (reversed bounds are rejected).
  • When a = b the distribution is the Dirac at a; the call is silently routed through as_random(a) for the same reason as normal with sigma = 0.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Continuous uniform distribution
Source code
provsql.sql line 3209

◆ uniform() [2/4]

random_variable provsql.uniform ( DOUBLE PRECISION a,
random_variable b )

◆ uniform() [3/4]

random_variable provsql.uniform ( random_variable a,
DOUBLE PRECISION b )

uniform(a, b)

◆ uniform() [4/4]

random_variable provsql.uniform ( random_variable a,
random_variable b )

◆ wald()

random_variable provsql.wald ( DOUBLE PRECISION mu,
DOUBLE PRECISION lambda )

Wald distribution: alias for inverse_gaussian.

See also
Wikipedia: Inverse Gaussian distribution
Source code
provsql.sql line 3786

◆ weibull() [1/4]

random_variable provsql.weibull ( DOUBLE PRECISION k,
DOUBLE PRECISION lambda )

Construct a Weibull random variable with shape k and scale lambda.

lambda is the SCALE (the 63.2% quantile), not a rate: k = 1 is the exponential with rate 1/lambda, and that case is silently routed through exponential to share its gate. The shape tunes the hazard: k < 1 infant mortality, k > 1 wear-out. Quantiles are exact, truncated moments are closed-form (via the regularised incomplete gamma), and the min of i.i.d. Weibulls has a closed-form mean (min-stability).

Validation: both parameters must be finite and strictly positive.

Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Weibull distribution
Source code
provsql.sql line 3247

◆ weibull() [2/4]

random_variable provsql.weibull ( DOUBLE PRECISION k,
random_variable lambda )

◆ weibull() [3/4]

random_variable provsql.weibull ( random_variable k,
DOUBLE PRECISION lambda )

weibull(k, lambda)

◆ weibull() [4/4]

random_variable provsql.weibull ( random_variable k,
random_variable lambda )

Variable Documentation

◆ OPERATOR

CREATE OPERATOR CLASS random_variable_ops DEFAULT FOR TYPE random_variable USING btree AS provsql.OPERATOR<, OPERATOR 2<=, OPERATOR 3=, OPERATOR 4 > FUNCTION random_variable_btree_cmp(random_variable, random_variable)