ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
ProbabilityMethod.h
Go to the documentation of this file.
1/**
2 * @file ProbabilityMethod.h
3 * @brief Catalog of probability-evaluation methods (Strategy + registry).
4 *
5 * Each probability-evaluation algorithm is a first-class @c ProbabilityMethod
6 * object that declares its own guarantee, applicability and (eventually) cost,
7 * instead of that knowledge being smeared across a string-switch dispatcher.
8 * The @c MethodCatalog is the registry the dispatcher in
9 * @c probability_evaluate.cpp consults: a named request resolves through
10 * @c byName(); the default (empty-method) request runs @c chooseAndRun(), which
11 * runs the independent -> inversion-free -> compilation ladder
12 * as the @c Exact-tolerance instance of the chooser.
13 *
14 * This header carries only the public interface. The concrete method classes,
15 * the @c EvalContext that threads the per-evaluation circuit state, and the
16 * catalog registration all live in @c probability_evaluate.cpp, where the
17 * file-local evaluation helpers they need are in scope.
18 *
19 * The design (the method-catalog / three-path chooser) is documented at
20 * length in @c doc/source/dev/probability-evaluation.rst.
21 */
22#ifndef PROVSQL_PROBABILITY_METHOD_H
23#define PROVSQL_PROBABILITY_METHOD_H
24
25#include <memory>
26#include <string>
27#include <vector>
28
29// d-DNNF artifact (defined in dDNNF.h). The d-D-producing methods can return it
30// via buildDD(), and the catalog's chooseAndBuildDD / makeDDAuto cost-select a
31// construction route and return the artifact for makeDD's callers (shapley,
32// compile_to_ddnnf, ddnnf_stats) -- the same selection the probability chooser
33// already makes among interpret-as-dd / tree-decomposition / compilation.
34class dDNNF;
35class BooleanCircuit;
36enum class gate_t : size_t;
37
38namespace provsql {
39
40/**
41 * @brief The contract the user grants -- the "path".
42 *
43 * @c Exact is tolerance @c (0,0); @c Relative promises @c (1±epsilon) with
44 * confidence @c 1-delta; @c Additive promises @c |p̂-p| <= epsilon with the same
45 * confidence. Admissible method sets nest @c Exact ⊂ @c Relative ⊂ @c Additive.
46 *
47 * The tolerance is recorded but does not by itself drive method selection:
48 * named methods dispatch by name and the empty method set runs the exact
49 * ladder.
50 */
52
53struct Tolerance {
55 double epsilon = 0.;
56 double delta = 0.;
57};
58
59/**
60 * @brief A circuit feature a method's cost/applicability estimate depends on,
61 * but that is not free to acquire.
62 *
63 * Acquiring a feature has a cost (modelled by @c EvalContext::featureCost), and
64 * the chooser acquires one lazily only when no already-known method is cheaper
65 * than acquiring it -- so a circuit the cheap methods resolve (read-once via
66 * @c independent, certified via @c inversion-free) never pays for analysis that
67 * could not change the decision. Free/O(1) features (\#inputs, an inversion-free
68 * certificate) are not modelled here -- they are read eagerly.
69 *
70 * @c DnfShape is a linear @c dnfShape walk. @c TreewidthProxy is a cheap
71 * (@c O(V+E)) degeneracy lower bound on the circuit's treewidth that gates
72 * @c tree-decomposition's cost -- it rules the method out when the bound already
73 * exceeds the build's limit, while the bounded-treewidth build can still fail
74 * implicitly when the bound is inconclusive.
75 */
77
78/// Per-evaluation circuit state threaded to a method's @c evaluate (defined in
79/// @c probability_evaluate.cpp, where the Boolean/Generic circuit machinery is
80/// in scope).
81struct EvalContext;
82
83/**
84 * @brief Strategy interface: one concrete subclass per probability method.
85 *
86 * @c evaluate throws @c CircuitException when the method cannot be applied to
87 * the circuit; @c chooseAndRun relies on that to fall through the default
88 * ladder, while @c byName lets it propagate (an explicitly named method
89 * reports the failure instead of silently falling back).
90 */
92public:
93 virtual ~ProbabilityMethod() = default;
94
95 /// Stable identifier used for @c byName lookup and the
96 /// @c provsql.last_eval_method report.
97 virtual std::string name() const = 0;
98
99 /// Which user-facing path this method can serve.
100 virtual ToleranceKind guaranteeKind() const = 0;
101
102 /// True iff this method participates in the auto-chooser's portfolio (vs being
103 /// reachable only @c byName).
104 virtual bool inDefaultChain() const { return false; }
105
106 /// True iff the method's guarantee holds with CERTAINTY (no failure
107 /// probability). The exact methods and the d-tree's certified interval are
108 /// deterministic; the (eps,delta) samplers are not. A request with delta == 0
109 /// ("deterministic") admits only deterministic methods -- the samplers cannot
110 /// honour it (their sample count is proportional to ln(1/delta), so delta = 0
111 /// is infeasible, and their cost model masks this by falling back to a finite
112 /// delta). For delta > 0 the samplers stay admissible but their cost grows as
113 /// delta shrinks, so the chooser already migrates to the (delta-independent)
114 /// d-tree well before delta reaches 0.
115 virtual bool isDeterministic() const { return true; }
116
117 /// Features the method's @c estimatedCost / @c applicable need acquired before
118 /// they are meaningful (empty = a free estimate). The chooser will not call
119 /// @c estimatedCost / @c applicable until these are acquired, and acquires
120 /// them lazily per the cost rule above.
121 virtual std::vector<Feature> requiredFeatures() const { return {}; }
122
123 /// Heuristic estimate of this method's cost on the current circuit (lower is
124 /// cheaper). Only called once @c requiredFeatures are acquired. The chooser sorts admissible portfolio members by this and tries
125 /// them cheapest-first -- there is deliberately NO fixed ordinal: the order
126 /// emerges from the estimates, and a calibrated cost model can later replace
127 /// the heuristic bodies without touching the chooser. Only consulted for
128 /// portfolio members; by-name-only methods keep the default.
129 virtual double estimatedCost(const EvalContext &, const Tolerance &) const
130 { return 0.; }
131
132 /// Cheap admissibility check for the portfolio (e.g. an inversion-free
133 /// certificate must be present, or a 2^N method's N is within a sanity
134 /// bound). @c byName ignores it.
135 virtual bool applicable(const EvalContext &, const Tolerance &) const
136 { return true; }
137
138 /// True iff the method evaluates the *raw* circuit, including multivalued
139 /// (BID / @c gate_mulinput) gates, and must therefore NOT have them rewritten
140 /// to independent Booleans first. The dispatcher rewrites multivalued gates
141 /// (@c EvalContext::ensureMultivaluedRewritten) before every method that
142 /// returns @c false, so a Boolean-only method needs no per-@c evaluate rewrite
143 /// of its own and a new one is BID-correct by default. Only @c "independent"
144 /// overrides this: it interprets a @c mulinput block natively (summing the
145 /// mutually-exclusive alternatives) to keep the exact disjoint-OR structure
146 /// the rewrite would dissolve. (Methods gated to TID-only circuits -- the
147 /// DNF samplers via @c Feature::DnfShape, @c inversion-free via its
148 /// certificate -- never see a @c mulinput, so the central rewrite is a no-op
149 /// for them and they keep the default.)
150 virtual bool handlesMultivalued() const { return false; }
151
152 /// Run the method, returning the probability. May mutate @p ctx (build the
153 /// Boolean view lazily, trigger the multivalued rewrite, set the reported
154 /// method name).
155 virtual double evaluate(EvalContext &ctx, const Tolerance &tol) const = 0;
156
157 /// True iff this method constructs a d-DNNF artifact (and so can serve the
158 /// makeDD route-chooser via @c buildDD). The three d-D constructors --
159 /// interpret-as-dd, tree-decomposition, compilation -- override this; the
160 /// scalar methods (independent, possible-worlds, the samplers, the d-tree)
161 /// do not. This is the @c producesDD() portfolio @c chooseAndBuildDD ranks.
162 virtual bool producesDD() const { return false; }
163
164 /// Build the d-DNNF this method constructs (only when @c producesDD()).
165 /// @c evaluate() of a d-D method is exactly @c buildDD(ctx).probabilityEvaluation(),
166 /// so the cost/route logic stays single-sourced. Sets @c ctx.actual_method.
167 virtual dDNNF buildDD(EvalContext &ctx) const;
168};
169
170/**
171 * @brief Registry of @c ProbabilityMethod objects.
172 *
173 * Mirrors the external-tool registry: adding a method is a new subclass plus one
174 * @c registerMethod call -- the dispatcher never changes (open/closed).
175 */
177public:
178 /// The process-wide catalog, lazily populated with the built-in methods.
179 static const MethodCatalog &instance();
180
181 void registerMethod(std::unique_ptr<ProbabilityMethod> m);
182
183 /// Exact match on @c name(); nullptr if absent.
184 const ProbabilityMethod *byName(const std::string &name) const;
185
186 /// Run the auto-chooser for @p tol: the portfolio methods admissible for the
187 /// tolerance and @c applicable, sorted cheapest-first by @c estimatedCost and
188 /// tried until one succeeds. The costliest method's exception propagates (the
189 /// portfolio is exhausted).
190 double chooseAndRun(EvalContext &ctx, const Tolerance &tol) const;
191
192 /// The d-DNNF analogue of @c chooseAndRun: cost-select among the
193 /// @c producesDD() portfolio (interpret-as-dd / tree-decomposition /
194 /// compilation) with the same uniform-cost search and speculative budget, and
195 /// return the chosen d-DNNF artifact (rather than a probability). This is the
196 /// makeDD route optimizer -- the same selection the probability chooser makes
197 /// among these routes, surfaced for the d-D-artifact callers.
198 dDNNF chooseAndBuildDD(EvalContext &ctx, const Tolerance &tol) const;
199
200private:
201 std::vector<std::unique_ptr<ProbabilityMethod>> methods_;
202};
203
204/// Cost-select a d-DNNF construction route for gate @p g of Boolean circuit
205/// @p c and build it -- the default makeDD route. A thin entry point over
206/// @c MethodCatalog::chooseAndBuildDD that builds the @c EvalContext from the
207/// Boolean view alone (the d-D portfolio needs no generic-circuit state); the
208/// callers that have a method/compiler request route the empty / "default" /
209/// "auto" case here and keep @c BooleanCircuit::makeDD for the named routes
210/// (tree-decomposition / interpret-as-dd / compilation, plus makeDD's own
211/// internal interpret -> tree-decomposition -> compiler fallback chain).
213
214} // namespace provsql
215
216#endif // PROVSQL_PROBABILITY_METHOD_H
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
Boolean circuit for provenance formula evaluation.
A d-DNNF circuit supporting exact probabilistic and game-theoretic evaluation.
Definition dDNNF.h:71
Registry of ProbabilityMethod objects.
const ProbabilityMethod * byName(const std::string &name) const
Exact match on name(); nullptr if absent.
std::vector< std::unique_ptr< ProbabilityMethod > > methods_
double chooseAndRun(EvalContext &ctx, const Tolerance &tol) const
Run the auto-chooser for tol: the portfolio methods admissible for the tolerance and applicable,...
void registerMethod(std::unique_ptr< ProbabilityMethod > m)
static const MethodCatalog & instance()
The process-wide catalog, lazily populated with the built-in methods.
dDNNF chooseAndBuildDD(EvalContext &ctx, const Tolerance &tol) const
The d-DNNF analogue of chooseAndRun: cost-select among the producesDD() portfolio (interpret-as-dd / ...
Strategy interface: one concrete subclass per probability method.
virtual dDNNF buildDD(EvalContext &ctx) const
Build the d-DNNF this method constructs (only when producesDD()).
virtual double estimatedCost(const EvalContext &, const Tolerance &) const
Heuristic estimate of this method's cost on the current circuit (lower is cheaper).
virtual bool inDefaultChain() const
True iff this method participates in the auto-chooser's portfolio (vs being reachable only byName).
virtual ~ProbabilityMethod()=default
virtual bool applicable(const EvalContext &, const Tolerance &) const
Cheap admissibility check for the portfolio (e.g.
virtual bool isDeterministic() const
True iff the method's guarantee holds with CERTAINTY (no failure probability).
virtual ToleranceKind guaranteeKind() const =0
Which user-facing path this method can serve.
virtual double evaluate(EvalContext &ctx, const Tolerance &tol) const =0
Run the method, returning the probability.
virtual std::vector< Feature > requiredFeatures() const
Features the method's estimatedCost / applicable need acquired before they are meaningful (empty = a ...
virtual bool producesDD() const
True iff this method constructs a d-DNNF artifact (and so can serve the makeDD route-chooser via buil...
virtual bool handlesMultivalued() const
True iff the method evaluates the raw circuit, including multivalued (BID / gate_mulinput) gates,...
virtual std::string name() const =0
Stable identifier used for byName lookup and the provsql.last_eval_method report.
Feature
A circuit feature a method's cost/applicability estimate depends on, but that is not free to acquire.
ToleranceKind
The contract the user grants – the "path".
dDNNF makeDDAuto(BooleanCircuit &c, gate_t g)
Cost-select a d-DNNF construction route for gate g of Boolean circuit c and build it – the default ma...
Per-evaluation circuit state threaded to a method's evaluate().