ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
UCQJointCompiler.h
Go to the documentation of this file.
1/**
2 * @file UCQJointCompiler.h
3 * @brief Phase C of the joint-width UCQ compiler: a UCQ-specialised
4 * homomorphism-type DP that runs directly over a tree
5 * decomposition of the joint encoding, emitting a certified d-D
6 * (deterministic, decomposable circuit) by construction.
7 *
8 * This is the data-side counterpart of ProvSQL's circuit-side treewidth
9 * exploitation, and the UCQ counterpart of @c ReachabilityCompiler: a
10 * bag-by-bag dynamic program whose state carries, for each disjunct, the
11 * set of **partial homomorphisms** realised by the facts of the
12 * processed subtree (the correlated regime additionally carries in-bag
13 * **gate valuations**). It is the operational form of the thesis's
14 * @f$\exists T\, q''(T) \wedge q_{wf}(T)@f$ rewriting (Amarilli, PhD
15 * thesis tel-01345836, Prop. 4.2.9): rather than guessing the set @c T
16 * of true gates with a second-order variable, the DP enumerates
17 * per-bag valuations, with mutual exclusivity giving determinism for
18 * free.
19 *
20 * Each transition emits d-D gates directly:
21 *
22 * - states at a node are **mutually exclusive and exhaustive** over the
23 * valuations of the world variables introduced in its subtree (every
24 * world induces exactly one (hom-set, sat) state), so every OR gate is
25 * deterministic *by construction*;
26 * - each world variable is introduced at exactly one node, so the
27 * children of every AND gate mention disjoint variable sets and the
28 * circuit is decomposable *by construction*.
29 *
30 * No knowledge-compilation step is therefore needed: the result feeds
31 * straight to @c dDNNF::probabilityEvaluation() (the marginal of an
32 * irrelevant world variable folds to a unit factor, exactly as in the
33 * reachability compiler, so the strictly-non-smooth circuit still
34 * evaluates correctly). For a joint encoding of width @f$k@f$ and a
35 * UCQ whose disjuncts have at most @f$e@f$ enumerating variables, the
36 * DP state is bounded by a function of @f$k@f$ and @f$e@f$ alone, giving
37 * exact probability of a @c \#P-hard UCQ in time linear in the data.
38 *
39 * The exponential parameter is the number of **enumerating** variables
40 * (existential join variables outside the key/FD determination closure),
41 * not @c n_vars; the design target is queries with at most 4-5 of them.
42 */
43#ifndef UCQ_JOINT_COMPILER_H
44#define UCQ_JOINT_COMPILER_H
45
46#include <cstddef>
47#include <map>
48#include <unordered_map>
49#include <utility>
50#include <vector>
51
52#include "JointEncoding.h"
53#include "TreeDecomposition.h"
54#include "dDNNF.h"
55
56/**
57 * @brief One atom of a conjunctive query: a relation symbol applied to
58 * query variables.
59 *
60 * Constants are pre-filtered by the SQL layer (selection pushed down),
61 * so an atom mentions only variables; @c vars index into the disjunct's
62 * variable list. A repeated variable encodes an equality (a self-join
63 * on equal columns); two atoms may share a @c relation_id (a self-join).
64 */
65struct Atom {
66 unsigned relation_id = 0; ///< Dense id of the relation symbol.
67 std::vector<unsigned> vars; ///< Query-variable indices, one per column.
68};
69
70/**
71 * @brief One conjunctive query (a disjunct of the UCQ).
72 */
73struct CQ {
74 unsigned n_vars = 0; ///< Number of query variables.
75 std::vector<Atom> atoms; ///< The conjuncts.
76};
77
78/**
79 * @brief A union of conjunctive queries.
80 */
81struct UCQ {
82 std::vector<CQ> disjuncts; ///< The disjuncts (at least one).
83};
84
85/**
86 * @brief Compiles a Boolean UCQ over a joint encoding into a certified
87 * d-D, along a tree decomposition of the joint graph.
88 */
90public:
91/** @brief Structural statistics of a compilation, for diagnostics and tests. */
92struct Stats {
93 unsigned joint_treewidth = 0; ///< Treewidth of the min-fill decomposition of the joint graph.
94 unsigned data_treewidth_lb = 0; ///< Degeneracy lower bound of the data-only graph.
95 unsigned circuit_treewidth_lb = 0; ///< Degeneracy lower bound of the slice-only graph.
96 std::size_t nb_bags = 0; ///< Number of bags of the decomposition.
97 std::size_t max_states = 0; ///< Maximum number of DP states at any node.
98 std::size_t dd_size = 0; ///< Number of gates of the emitted d-D.
99 std::size_t nb_variables = 0; ///< Number of world variables (events).
100 std::vector<unsigned> n_enumerating;///< Per-disjunct static count of enumerating variables.
101};
102
103/** @brief A compiled UCQ: the d-D and its statistics. */
104struct Result {
105 dDNNF dd; ///< d-D whose root computes "the UCQ holds"; input gates carry the event tokens and probabilities.
106 Stats stats; ///< Compilation statistics.
107};
108
109/**
110 * @brief Default bound on the number of DP states at a single node.
111 *
112 * The cap (not the static enumerating-variable count) is the true
113 * safety net: the realised-state count is governed by data sparsity and
114 * the absorbing @c sat collapse, typically far below the a-priori bound.
115 */
116static constexpr std::size_t DEFAULT_MAX_STATES = 1u << 16;
117
118/**
119 * @brief Compile a Boolean UCQ over @p enc into a certified d-D.
120 *
121 * @param enc The joint encoding (facts, events, joint graph).
122 * @param ucq The Boolean UCQ.
123 * @param max_treewidth Reject (fall through to the ladder) when the
124 * joint width exceeds this.
125 * @param max_states Bound on the DP state count per node.
126 * @return The compiled d-D and statistics.
127 * @throws TreeDecompositionException if the joint width exceeds
128 * @p max_treewidth (the degeneracy
129 * screen or the min-fill build).
130 * @throws JointCompilerException on unsupported input shapes or
131 * when @p max_states is exceeded.
132 */
133static Result compile(const JointEncoding &enc,
134 const UCQ &ucq,
135 unsigned max_treewidth = TreeDecomposition::MAX_TREEWIDTH,
136 std::size_t max_states = DEFAULT_MAX_STATES);
137
138/**
139 * @brief Per-answer evaluation by a single top-down DP (data-graph regime).
140 *
141 * The full multi-output construction (Amarilli, tel-01345836, ยง4.2.9): ONE
142 * bottom-up sweep emits one circuit root per answer, rather than @c k
143 * head-pinned @c compile() sweeps. The head variables become a
144 * **state-level key** -- they are never existentially projected (a forgotten
145 * head element is recorded as a fixed value), completed answers are tracked
146 * per head-tuple in the state, and an answer is emitted as its own d-DNNF
147 * root when its head elements leave the tree decomposition. All answer roots
148 * share one circuit, so a single probability pass (with the gate cache) values
149 * them all. The candidate answers are **discovered** by the sweep -- no
150 * candidate list is needed. Equivalent answers and probabilities to
151 * @c k head-pinned @c compile() calls, in one pass instead of @c k.
152 *
153 * The compiler's job ends at the **circuit**: it returns the shared d-D and
154 * one root gate per answer (the materialisation / probability / Shapley is the
155 * caller's, on the returned roots), keeping a single evaluation pipeline.
156 *
157 * @param enc The joint encoding (data-graph / TID-BID or correlated).
158 * @param ucq The UCQ; the head variables must occur in every disjunct.
159 * @param head_vars Query-variable indices of the head.
160 */
162 std::vector<unsigned long> head; ///< Bound element value per head variable.
163 gate_t root; ///< This answer's d-D root in @c dd.
164};
166 dDNNF dd; ///< The shared certified d-D.
167 std::vector<AnswerRoot> answers; ///< One root per discovered answer.
168 std::size_t max_states = 0; ///< Peak DP state count.
169};
171 const JointEncoding &enc,
172 const UCQ &ucq,
173 const std::vector<unsigned> &head_vars,
174 unsigned max_treewidth = TreeDecomposition::MAX_TREEWIDTH,
175 std::size_t max_states = DEFAULT_MAX_STATES);
176};
177
178#endif /* UCQ_JOINT_COMPILER_H */
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
Phase A of the joint-width UCQ compiler: assemble the joint graph of the data and its correlation str...
Tree decomposition of a Boolean circuit for knowledge compilation.
The joint encoding of an instance: facts, world events, and the joint graph the screen and the DP run...
static constexpr int MAX_TREEWIDTH
Maximum supported treewidth.
Compiles a Boolean UCQ over a joint encoding into a certified d-D, along a tree decomposition of the ...
static constexpr std::size_t DEFAULT_MAX_STATES
Default bound on the number of DP states at a single node.
static AnswerCircuit compileAnswersOneDP(const JointEncoding &enc, const UCQ &ucq, const std::vector< unsigned > &head_vars, unsigned max_treewidth=TreeDecomposition::MAX_TREEWIDTH, std::size_t max_states=DEFAULT_MAX_STATES)
static Result compile(const JointEncoding &enc, const UCQ &ucq, unsigned max_treewidth=TreeDecomposition::MAX_TREEWIDTH, std::size_t max_states=DEFAULT_MAX_STATES)
Compile a Boolean UCQ over enc into a certified d-D.
A d-DNNF circuit supporting exact probabilistic and game-theoretic evaluation.
Definition dDNNF.h:71
Decomposable Deterministic Negation Normal Form circuit.
One atom of a conjunctive query: a relation symbol applied to query variables.
std::vector< unsigned > vars
Query-variable indices, one per column.
unsigned relation_id
Dense id of the relation symbol.
One conjunctive query (a disjunct of the UCQ).
std::vector< Atom > atoms
The conjuncts.
unsigned n_vars
Number of query variables.
std::size_t max_states
Peak DP state count.
dDNNF dd
The shared certified d-D.
std::vector< AnswerRoot > answers
One root per discovered answer.
Per-answer evaluation by a single top-down DP (data-graph regime).
std::vector< unsigned long > head
Bound element value per head variable.
gate_t root
This answer's d-D root in dd.
A compiled UCQ: the d-D and its statistics.
Stats stats
Compilation statistics.
dDNNF dd
d-D whose root computes "the UCQ holds"; input gates carry the event tokens and probabilities.
Structural statistics of a compilation, for diagnostics and tests.
std::size_t nb_variables
Number of world variables (events).
unsigned joint_treewidth
Treewidth of the min-fill decomposition of the joint graph.
std::vector< unsigned > n_enumerating
Per-disjunct static count of enumerating variables.
std::size_t dd_size
Number of gates of the emitted d-D.
std::size_t max_states
Maximum number of DP states at any node.
unsigned data_treewidth_lb
Degeneracy lower bound of the data-only graph.
unsigned circuit_treewidth_lb
Degeneracy lower bound of the slice-only graph.
std::size_t nb_bags
Number of bags of the decomposition.
A union of conjunctive queries.
std::vector< CQ > disjuncts
The disjuncts (at least one).