ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
AggMarginalEvaluator.h
Go to the documentation of this file.
1
/**
2
* @file AggMarginalEvaluator.h
3
* @brief Exact closed-form HAVING @c COUNT(*) @c op @c C probability over
4
* *safe-join* lineage -- the recursive marginal-vector engine of the
5
* Ré-Suciu HAVING trichotomy (see
6
* @c doc/source/dev/probability-evaluation.rst).
7
*
8
* @c CountCmpEvaluator (the flat Poisson-binomial pre-pass) is exact only
9
* when the @c gate_agg children are pairwise leaf-disjoint, i.e. flat
10
* single-table COUNT. A join makes two aggregate-input rows share a base
11
* tuple (fan-out, e.g. @c R(k,a),S(a,b) with several @c b per @c a), so the
12
* contributors stop being independent Bernoulli trials and
13
* @c CountCmpEvaluator bails to @c provsql_having's exponential enumeration.
14
*
15
* This pass generalises the flat case to any *hierarchical* (laminar) join:
16
* each contributor is a product (conjunction) of @c gate_input leaves
17
* (nested @c gate_times from SPJ subqueries / views is flattened, since
18
* @c times is AND on the probability path, so detection is invariant to
19
* join order and subquery nesting), and the count distribution is computed
20
* **recursively** down the hierarchy. At
21
* each level the contributors partition into independent **blocks** (by shared
22
* leaf); a block factors out the leaves common to *every* member (this level's
23
* shared "root" event) and the block count is the disjoint mixture
24
* @f$(1-p_{\text{root}})\,\delta_0 + p_{\text{root}}\,m_{\text{inner}}@f$ (the
25
* @c ⊥ combinator), where @f$m_{\text{inner}}@f$ is the same construction
26
* applied to the per-member residual leaf sets one level deeper; independent
27
* blocks combine by **convolution** (the @c ⊛^+ combinator). Single-level
28
* fan-out (@c R(k,a),S(a,b)) is the case where every residual is one leaf and
29
* @f$m_{\text{inner}}@f$ is a Poisson-binomial; deeper nesting (orders→items
30
* under a user) recurses further. The answer is
31
* @f$\sum_{c\ge 1,\;c\,\theta\,C} m[c]@f$ over the resulting count PMF @c m,
32
* with the empty group (@c c = 0) excluded exactly as in
33
* @c CountCmpEvaluator / SQL @c HAVING semantics.
34
*
35
* A multi-member block with *no* common leaf is the **join (Cartesian
36
* product)** node @c R(a),S(a,b),T(a,c): the contributors are the complete
37
* product of per-factor parts, so @c count is the product of the per-factor
38
* counts. A @c SUM whose value lives on one factor is @f$S_f\cdot M@f$ (that
39
* factor's weighted sum times the others' count product); a *branch-spanning*
40
* value that is **additively separable** across factors (e.g. @c sum(b+c)) is
41
* @f$\sum_f S_f\cdot\prod_{g\ne f} N_g@f$, folded exactly from the per-factor
42
* *joint* @c (sum,count) distributions (@c sumCountPMF); a
43
* **multiplicatively separable** value (e.g. @c sum(b*c)) is
44
* @f$\prod_f S_f@f$, the product of the per-factor weighted sums
45
* (@c mulSeparableSumPMF). A value that is neither (e.g. @c sum(b*c+b+c))
46
* couples the factors and self-gates back to enumeration.
47
*
48
* **Soundness is circuit-only and self-gating.** No planner-time skeleton
49
* certificate is consulted: the recursion is exact iff at every level each
50
* multi-member block has a leaf common to *all* its members (and every
51
* involved leaf is private to the cmp subtree). A non-laminar shape -- e.g.
52
* the triangle @c R(x,y),S(y,z),T(z,x) -- produces a multi-member block with
53
* no common leaf at some level, which clears the soundness flag and falls the
54
* cmp through to exact enumeration. This circuit-only recursion covers the
55
* tuple-independent hierarchical class at any depth.
56
*
57
* **BID blocks (@c COUNT / @c SUM / @c AVG / @c MIN / @c MAX).** A
58
* @c repair_key block surfaces in the circuit as a set of @c gate_mulinput
59
* contributors sharing a block-key child, mutually exclusive with
60
* per-alternative probabilities. Such a contributor is recognised and the
61
* block handled as a *categorical* (at most one alternative present, the null
62
* arm Σp_i<1 contributing 0), independent of the TID part and of other blocks:
63
* @c COUNT / @c SUM / @c AVG convolve the block's count / weighted-sum
64
* distribution, and @c MIN / @c MAX fold a per-block factor
65
* (1-Σ_{pred} p_alt) into each @c pAllAbsent over a value-thresholded subset.
66
* No planner certificate is needed, since the block *is* visible in the
67
* circuit. The residual genuinely certificate-only case is a declared key on a
68
* plain TID table (mutual exclusion in @c block_key metadata only, no
69
* @c mulinput): that would need a planner @c CERT_SAFE_AGG_PLAN.
70
*
71
* **Non-read-once UNION / EXCEPT contributors.** A @c UNION / @c EXCEPT over a
72
* join that re-uses a base tuple gives a contributor that is a @c gate_plus /
73
* @c gate_monus repeating the shared leaf -- @c (r∧s)∨(r∧t) or @c (r∧s)∖(r∧t)
74
* -- which @c contributorProb (read-once only) rejects. When the contributor's
75
* footprint is *private* (so it is independent of every other contributor),
76
* @c contributorExactMarginal computes its exact marginal by brute force over
77
* its private leaves (the internal sharing resolved exactly) and the
78
* contributor is modelled as a one-alternative BID block -- an independent
79
* event -- reusing the categorical machinery above. A base tuple shared
80
* *across* contributors of the same group is genuinely @f$\#P@f$-hard and bails.
81
*
82
* Runs as a probability-side pre-pass in @c probability_evaluate.cpp, *after*
83
* @c runCountCmpEvaluator (so the cheap flat path still wins where it
84
* applies; this pass only ever sees the join-shaped cmps the flat pass left
85
* behind), gated by the same @c provsql.cmp_probability_evaluation GUC and
86
* sharing its sound-only contract (replace the @c gate_cmp by a Bernoulli
87
* @c gate_input, meaningless to symbolic semirings).
88
*/
89
#ifndef PROVSQL_AGG_MARGINAL_EVALUATOR_H
90
#define PROVSQL_AGG_MARGINAL_EVALUATOR_H
91
92
#include "
GenericCircuit.h
"
93
94
namespace
provsql
{
95
96
/**
97
* @brief Run the safe-join aggregate marginal-vector pre-pass over @p gc.
98
*
99
* For every @c gate_cmp matching the hierarchical-join shape (see file
100
* docstring) over @c COUNT / @c SUM / @c MIN / @c MAX, computes the
101
* comparator's exact probability through the recursive hierarchical engine
102
* and replaces the cmp by a Bernoulli @c gate_input via
103
* @c GenericCircuit::resolveCmpToBernoulli. Leaves every other cmp
104
* untouched. COUNT / SUM use the count/weighted-sum distribution
105
* (block mixture + additive convolution); MIN / MAX reduce to a handful of
106
* "all of a value-thresholded subset absent" probabilities over the same
107
* hierarchical recursion.
108
*
109
* @param gc Circuit to mutate in place.
110
* @return Number of comparators resolved by this pass.
111
*/
112
unsigned
runAggMarginalEvaluator
(GenericCircuit &gc);
113
114
}
// namespace provsql
115
116
#endif
// PROVSQL_AGG_MARGINAL_EVALUATOR_H
GenericCircuit.h
Semiring-agnostic in-memory provenance circuit.
provsql
Definition
AggMarginalEvaluator.cpp:24
provsql::runAggMarginalEvaluator
unsigned runAggMarginalEvaluator(GenericCircuit &gc)
Run the safe-join aggregate marginal-vector pre-pass over gc.
Definition
AggMarginalEvaluator.cpp:1093
Home
·
Documentation
·
Publications
·
Contributors
·
Source
·
Cite