ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
dDNNF.h
Go to the documentation of this file.
1/**
2 * @file dDNNF.h
3 * @brief Decomposable Deterministic Negation Normal Form circuit.
4 *
5 * A **d-DNNF** (decomposable deterministic Negation Normal Form) is a
6 * Boolean circuit with two structural properties:
7 * - **Determinism**: for every OR gate, the two sub-formulae are
8 * mutually exclusive (their models are disjoint).
9 * - **Decomposability**: for every AND gate, the two sub-formulae share
10 * no variable.
11 *
12 * These properties enable:
13 * - Linear-time computation of the probability of satisfying assignments.
14 * - Polynomial computation of Shapley and Banzhaf power indices.
15 *
16 * @c dDNNF extends @c BooleanCircuit with:
17 * - A designated @c root gate.
18 * - A memoisation cache for probability evaluation.
19 * - Normalisation methods (@c makeSmooth(), @c makeGatesBinary(),
20 * @c simplify()) that transform the circuit into a canonical form
21 * required by the evaluation algorithms.
22 * - Conditioning methods (@c condition(), @c conditionAndSimplify())
23 * used during Shapley/Banzhaf computation.
24 *
25 * ### @c hash_gate_t
26 * A standard-library compatible hash functor for @c gate_t, required
27 * because @c gate_t is a scoped enum and has no built-in @c std::hash
28 * specialisation.
29 */
30#ifndef DDNNF_H
31#define DDNNF_H
32
33#include <functional>
34#include <string>
35#include <unordered_set>
36
37#include "BooleanCircuit.h"
38
39// Forward declaration for friend
42
43/**
44 * @brief @c std::hash functor for @c gate_t.
45 *
46 * Allows @c gate_t to be used as a key in @c std::unordered_map and
47 * @c std::unordered_set by delegating to @c std::hash on the underlying
48 * integer type.
49 */
51{
52 /**
53 * @brief Compute the hash of a gate identifier.
54 * @param g Gate to hash.
55 * @return Hash value suitable for use in unordered containers.
56 */
57 size_t operator()(gate_t g) const
58 {
59 return std::hash<typename std::underlying_type<gate_t>::type>()(
60 static_cast<typename std::underlying_type<gate_t>::type>(g));
61 }
62};
63
64/**
65 * @brief A d-DNNF circuit supporting exact probabilistic and game-theoretic evaluation.
66 *
67 * Inherits the full @c BooleanCircuit structure and adds a root gate and
68 * algorithms that exploit the d-DNNF structural properties for efficient
69 * computation.
70 */
71class dDNNF : public BooleanCircuit {
72private:
73/** @brief Memoisation cache mapping gates to their probability values. */
74mutable std::unordered_map<gate_t, double, hash_gate_t> probability_cache;
75
76/**
77 * @brief Compute the δ table used in the Shapley algorithm.
78 *
79 * Returns a map from each input gate to a vector of δ values (one per
80 * possible "defection count"), as described in the algorithm of
81 * Choicenet / Livshits et al.
82 * @return Map from each input gate to its vector of δ values.
83 */
84std::unordered_map<gate_t, std::vector<double> > shapley_delta() const;
85
86/**
87 * @brief Compute the α table used in the Shapley algorithm.
88 *
89 * Returns a 2-D vector of α coefficients that weight the δ values when
90 * computing the Shapley value of each input gate.
91 * @return 2-D vector of α coefficients (indexed by defection count).
92 */
93std::vector<std::vector<double> > shapley_alpha() const;
94
95/**
96 * @brief Compute the unnormalised Banzhaf value for the whole circuit.
97 *
98 * Used internally by @c banzhaf() to compute the Banzhaf power index
99 * for a specific variable after conditioning.
100 *
101 * @return Unnormalised Banzhaf value.
102 */
103double banzhaf_internal() const;
104
105/**
106 * @brief Compute a topological ordering of the circuit.
107 *
108 * @param reversedWires Adjacency list of the reversed wires.
109 * @return Gates in topological order (leaves first).
110 */
111std::vector<gate_t> topological_order(const std::vector<std::vector<gate_t> > &reversedWires) const;
112
113gate_t root{0}; ///< The root gate of the d-DNNF
114
115public:
116/**
117 * @brief Return the root gate of this d-DNNF.
118 * @return Gate identifier of the root.
119 */
121 return root;
122}
123/**
124 * @brief Set the root gate.
125 * @param g New root gate.
126 */
128 root=g;
129}
130
131/**
132 * @brief Return the set of all variable (IN) gates reachable from @p root.
133 * @param root Root gate of the sub-circuit.
134 * @return Set of reachable IN gate identifiers.
135 */
136std::unordered_set<gate_t> vars(gate_t root) const;
137
138/**
139 * @brief Make the d-DNNF smooth.
140 *
141 * A d-DNNF is smooth if every OR gate's children mention exactly the
142 * same set of variables. Smoothing is required before probability
143 * evaluation to ensure correctness.
144 */
145void makeSmooth();
146
147/**
148 * @brief Rewrite all n-ary AND/OR gates into binary trees.
149 *
150 * Some evaluation algorithms assume binary gates. This method replaces
151 * every AND (or OR, depending on @p type) gate with more than two
152 * children by a balanced binary tree of the same type.
153 *
154 * @param type The gate type (@c BooleanGate::AND or @c BooleanGate::OR)
155 * to binarise.
156 */
158
159/**
160 * @brief Simplify the d-DNNF by removing redundant constants.
161 *
162 * Propagates constant @c true / @c false values upward and removes
163 * gates that have become trivially constant after conditioning.
164 */
165void simplify();
166
167/**
168 * @brief Condition on variable @p var having value @p value and simplify.
169 *
170 * Sets input gate @p var to @p value and propagates the simplification
171 * through the circuit, returning a new (simplified) @c dDNNF.
172 *
173 * @param var Input gate to condition on.
174 * @param value Truth value to assign to @p var.
175 * @return A simplified copy of the conditioned circuit.
176 */
177dDNNF conditionAndSimplify(gate_t var, bool value) const;
178
179/**
180 * @brief Condition on variable @p var having value @p value (no simplification).
181 *
182 * @param var Input gate to condition on.
183 * @param value Truth value to assign to @p var.
184 * @return A copy of the circuit with @p var fixed to @p value.
185 */
186dDNNF condition(gate_t var, bool value) const;
187
188/**
189 * @brief Compute the exact probability of the d-DNNF being @c true.
190 *
191 * Requires the circuit to be smooth. Uses the structural properties of
192 * the d-DNNF to evaluate in time linear in the circuit size.
193 *
194 * @return Probability in [0, 1].
195 */
196double probabilityEvaluation() const;
197
198/**
199 * @brief Compute the Shapley value of input gate @p var.
200 *
201 * Implements the polynomial-time Shapley-value algorithm for d-DNNFs
202 * described in Livshits et al. (PODS 2021).
203 *
204 * @param var Input gate whose Shapley value is requested.
205 * @return Shapley value.
206 */
207double shapley(gate_t var) const;
208
209/**
210 * @brief Compute the Banzhaf power index of input gate @p var.
211 *
212 * Uses repeated conditioning and probability evaluation.
213 *
214 * @param var Input gate whose Banzhaf index is requested.
215 * @return Banzhaf power index.
216 */
217double banzhaf(gate_t var) const;
218
219/**
220 * @brief Structural statistics of a compiled d-DNNF.
221 *
222 * Counts are over the gates reachable from @c root. @c depth is the
223 * longest path (in gates) from the root; @c smooth is true iff every
224 * OR gate's children mention the same set of variables (the property
225 * @c makeSmooth() establishes, required by @c probabilityEvaluation).
226 */
227struct Stats {
228 std::size_t nodes = 0; ///< Total reachable gates.
229 std::size_t edges = 0; ///< Total wires among reachable gates.
230 std::size_t and_gates = 0; ///< AND (decomposition) gates.
231 std::size_t or_gates = 0; ///< OR (decision) gates.
232 std::size_t not_gates = 0; ///< NOT gates.
233 std::size_t inputs = 0; ///< IN (variable) leaves.
234 bool smooth = true; ///< Every OR gate's children share their variable set.
235 int depth = 0; ///< Longest path (in gates) from the root.
236};
237
238/**
239 * @brief Compute structural statistics over the gates reachable from @c root.
240 * @return Filled @c Stats.
241 */
242Stats nodeStats() const;
243
244/**
245 * @brief Return a GraphViz DOT representation of the d-DNNF.
246 *
247 * Walks gates reachable from @c root and emits a @c digraph with one
248 * node per gate (AND as @c "∧", OR as @c "∨", NOT as
249 * @c "¬", IN labelled by the short prefix of its UUID and its
250 * probability). The root node is rendered with a thicker border.
251 * Unreachable or unset gates are skipped.
252 *
253 * @return DOT source as a string.
254 */
255std::string toDot() const;
256
257/**
258 * @brief Serialise the d-DNNF in the c2d / d4 @c ".nnf" text format.
259 *
260 * Header @c "nnf <#nodes> <#edges> <#vars>", then one line per node in
261 * an order where children precede parents:
262 * - @c "L <lit>" --literal leaf: an IN gate is @c +var, a NOT over an
263 * input is @c -var.
264 * - @c "A <k> <c1>..<ck>" --AND over @c k earlier nodes (@c "A 0" is
265 * constant true).
266 * - @c "O <j> <k> <c1>..<ck>" --OR; @c j is the decision variable or
267 * @c 0 when none is recorded. ProvSQL does not track it, so @c j is
268 * always @c 0 (@c "O 0 0" is constant false).
269 *
270 * @param var_of_uuid optional map from an input's original-circuit UUID
271 * to its variable index. When supplied, input variables use this
272 * numbering (so a @c .nnf and the @c tseytin_cnf of the same
273 * circuit cross-reference, even when an external compiler
274 * renumbered the variables internally); a UUID it does not know,
275 * or an empty callback, falls back to the d-DNNF's own gate id.
276 * @return NNF text.
277 * @throws CircuitException if a NOT gate is not directly over an input
278 * (the circuit is then not in negation normal form).
279 */
280std::string toNNF(
281 const std::function<int(const std::string &)> &var_of_uuid = {}) const;
282
283friend dDNNFTreeDecompositionBuilder; ///< Allowed to construct and populate this d-DNNF
284friend StructuredDNNFBuilder; ///< Inversion-free structured builder: constructs and populates this d-DNNF
285friend dDNNF BooleanCircuit::compilation(gate_t g, std::string compiler, std::string *resolved) const; ///< Allowed to access internal d-DNNF state
286};
287
288#endif /* DDNNF_H */
Boolean provenance circuit with support for knowledge compilation.
BooleanGate
Gate types for a Boolean provenance circuit.
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
dDNNF compilation(gate_t g, std::string compiler, std::string *resolved=nullptr) const
Compile the sub-circuit rooted at g to a dDNNF via an external tool.
BooleanCircuit()
Construct an empty Boolean circuit.
Top-down structured-d-DNNF builder over a query-derived variable order.
Builds a d-DNNF from a Boolean circuit using a tree decomposition.
A d-DNNF circuit supporting exact probabilistic and game-theoretic evaluation.
Definition dDNNF.h:71
dDNNF conditionAndSimplify(gate_t var, bool value) const
Condition on variable var having value value and simplify.
std::string toNNF(const std::function< int(const std::string &)> &var_of_uuid={}) const
Serialise the d-DNNF in the c2d / d4 ".nnf" text format.
Definition dDNNF.cpp:811
gate_t root
The root gate of the d-DNNF.
Definition dDNNF.h:113
dDNNF condition(gate_t var, bool value) const
Condition on variable var having value value (no simplification).
Definition dDNNF.cpp:564
double banzhaf_internal() const
Compute the unnormalised Banzhaf value for the whole circuit.
Definition dDNNF.cpp:228
Stats nodeStats() const
Compute structural statistics over the gates reachable from root.
Definition dDNNF.cpp:744
double probabilityEvaluation() const
Compute the exact probability of the d-DNNF being true.
Definition dDNNF.cpp:141
void setRoot(gate_t g)
Set the root gate.
Definition dDNNF.h:127
void simplify()
Simplify the d-DNNF by removing redundant constants.
Definition dDNNF.cpp:604
void makeSmooth()
Make the d-DNNF smooth.
Definition dDNNF.cpp:61
void makeGatesBinary(BooleanGate type)
Rewrite all n-ary AND/OR gates into binary trees.
Definition dDNNF.cpp:108
std::vector< std::vector< double > > shapley_alpha() const
Compute the α table used in the Shapley algorithm.
Definition dDNNF.cpp:422
friend StructuredDNNFBuilder
Inversion-free structured builder: constructs and populates this d-DNNF.
Definition dDNNF.h:284
double shapley(gate_t var) const
Compute the Shapley value of input gate var.
Definition dDNNF.cpp:526
double banzhaf(gate_t var) const
Compute the Banzhaf power index of input gate var.
Definition dDNNF.cpp:554
std::vector< gate_t > topological_order(const std::vector< std::vector< gate_t > > &reversedWires) const
Compute a topological ordering of the circuit.
Definition dDNNF.cpp:581
friend dDNNFTreeDecompositionBuilder
Allowed to construct and populate this d-DNNF.
Definition dDNNF.h:283
std::unordered_set< gate_t > vars(gate_t root) const
Return the set of all variable (IN) gates reachable from root.
Definition dDNNF.cpp:33
std::unordered_map< gate_t, double, hash_gate_t > probability_cache
Memoisation cache mapping gates to their probability values.
Definition dDNNF.h:74
gate_t getRoot() const
Return the root gate of this d-DNNF.
Definition dDNNF.h:120
std::unordered_map< gate_t, std::vector< double > > shapley_delta() const
Compute the δ table used in the Shapley algorithm.
Definition dDNNF.cpp:320
std::string toDot() const
Return a GraphViz DOT representation of the d-DNNF.
Definition dDNNF.cpp:903
Structural statistics of a compiled d-DNNF.
Definition dDNNF.h:227
bool smooth
Every OR gate's children share their variable set.
Definition dDNNF.h:234
int depth
Longest path (in gates) from the root.
Definition dDNNF.h:235
std::size_t nodes
Total reachable gates.
Definition dDNNF.h:228
std::size_t or_gates
OR (decision) gates.
Definition dDNNF.h:231
std::size_t edges
Total wires among reachable gates.
Definition dDNNF.h:229
std::size_t not_gates
NOT gates.
Definition dDNNF.h:232
std::size_t inputs
IN (variable) leaves.
Definition dDNNF.h:233
std::size_t and_gates
AND (decomposition) gates.
Definition dDNNF.h:230
std::hash functor for gate_t.
Definition dDNNF.h:51
size_t operator()(gate_t g) const
Compute the hash of a gate identifier.
Definition dDNNF.h:57