ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
probability_evaluate.cpp
Go to the documentation of this file.
1/**
2 * @file probability_evaluate.cpp
3 * @brief SQL function @c provsql.probability_evaluate() – probabilistic circuit evaluation.
4 *
5 * Implements @c provsql.probability_evaluate(), which computes the
6 * probability that a provenance circuit evaluates to @c true under the
7 * tuple-independent probabilistic-database model.
8 *
9 * The @p method argument selects the computation algorithm:
10 * - @c "possible-worlds": exact enumeration of all 2^n worlds.
11 * - @c "monte-carlo": approximate via random sampling (fast, inexact).
12 * - @c "weightmc": approximate using the @c weightmc model counter.
13 * - @c "tree-decomposition": exact via tree-decomposition-based d-DNNF.
14 * - @c "independent": exact evaluation for disconnected circuits.
15 * - Any external compiler name (@c "d4", @c "c2d", @c "minic2d", @c "dsharp").
16 *
17 * A SIGINT signal sets a process-local flag that causes the evaluation
18 * to abort and return @c NULL (used when the user cancels a long-running
19 * probability computation).
20 */
21extern "C" {
22#include "postgres.h"
23#include "fmgr.h"
24#include "catalog/pg_type.h"
25#include "utils/uuid.h"
26#include "executor/spi.h"
27#include "provsql_shmem.h"
28#include "provsql_utils.h"
29
30PG_FUNCTION_INFO_V1(probability_evaluate);
31}
32
33#include "c_cpp_compatibility.h"
34#include <set>
35#include <cmath>
36#include <csignal>
37
38#include "BooleanCircuit.h"
39#include "CircuitFromMMap.h"
40#include "GenericCircuit.h"
42#include "having_semantics.hpp"
43#include "provsql_mmap.h"
44#include "provsql_utils_cpp.h"
45#include "semiring/BoolExpr.h"
46
47using namespace std;
48
49/**
50 * @brief SIGINT handler that sets the global interrupted flag.
51 *
52 * The signal number argument is required by the @c signal() API but is
53 * not used.
54 */
55static void provsql_sigint_handler (int)
56{
58}
59
60/**
61 * @brief Core implementation of probability evaluation for a circuit token.
62 * @param token UUID of the root provenance gate.
63 * @param method Evaluation method name (e.g. "independent", "monte-carlo").
64 * @param args Additional arguments for the chosen method.
65 * @return Float8 Datum containing the computed probability.
66 */
68 (pg_uuid_t token, const string &method, const string &args)
69{
70 gate_t gate;
71 BooleanCircuit c = getBooleanCircuit(token, gate);
72
73 double result;
74
75 // Display the circuit for debugging:
76 // elog(WARNING, "%s", c.toString(gate).c_str());
77
78 provsql_interrupted = false;
79
80 void (*prev_sigint_handler)(int);
81 prev_sigint_handler = signal(SIGINT, provsql_sigint_handler);
82
83 try {
84 bool processed=false;
85
86 if(method=="independent") {
87 result = c.independentEvaluation(gate);
88 processed = true;
89 } else if(method=="") {
90 // Default evaluation, use independent, tree-decomposition, and
91 // compilation in order until one works
92 try {
93 result = c.independentEvaluation(gate);
94 processed = true;
95 } catch(CircuitException &) {}
96 }
97
98 if(!processed) {
99 // Other methods do not deal with multivalued input gates, they
100 // need to be rewritten
102
103 if(method=="monte-carlo") {
104 int samples=0;
105
106 try {
107 samples = stoi(args);
108 } catch(const std::invalid_argument &e) {
109 }
110
111 if(samples<=0)
112 provsql_error("Invalid number of samples: '%s'", args.c_str());
113
114 result = c.monteCarlo(gate, samples);
115 } else if(method=="possible-worlds") {
116 if(!args.empty())
117 provsql_warning("Argument '%s' ignored for method possible-worlds", args.c_str());
118
119 result = c.possibleWorlds(gate);
120 } else if(method=="weightmc") {
121 result = c.WeightMC(gate, args);
122 } else if(method=="compilation" || method=="tree-decomposition" || method=="") {
123 auto dd = c.makeDD(gate, method, args);
124 result = dd.probabilityEvaluation();
125 } else {
126 provsql_error("Wrong method '%s' for probability evaluation", method.c_str());
127 }
128 }
129 } catch(CircuitException &e) {
130 provsql_error("%s", e.what());
131 }
132
133 provsql_interrupted = false;
134 signal (SIGINT, prev_sigint_handler);
135
136 // Avoid rounding errors that make probability outside of [0,1]
137 if(result>1.)
138 result=1.;
139 else if(result<0.)
140 result=0.;
141
142 PG_RETURN_FLOAT8(result);
143}
144
145/** @brief PostgreSQL-callable wrapper for probability_evaluate(). */
146Datum probability_evaluate(PG_FUNCTION_ARGS)
147{
148 try {
149 Datum token = PG_GETARG_DATUM(0);
150 string method;
151 string args;
152
153 if(PG_ARGISNULL(0))
154 PG_RETURN_NULL();
155
156 if(!PG_ARGISNULL(1)) {
157 text *t = PG_GETARG_TEXT_P(1);
158 method = string(VARDATA(t),VARSIZE(t)-VARHDRSZ);
159 }
160
161 if(!PG_ARGISNULL(2)) {
162 text *t = PG_GETARG_TEXT_P(2);
163 args = string(VARDATA(t),VARSIZE(t)-VARHDRSZ);
164 }
165
166 return probability_evaluate_internal(*DatumGetUUIDP(token), method, args);
167 } catch(const std::exception &e) {
168 provsql_error("probability_evaluate: %s", e.what());
169 } catch(...) {
170 provsql_error("probability_evaluate: Unknown exception");
171 }
172
173 PG_RETURN_NULL();
174}
Boolean-expression (lineage formula) semiring.
Boolean provenance circuit with support for knowledge compilation.
BooleanCircuit getBooleanCircuit(pg_uuid_t token, gate_t &gate)
Build a BooleanCircuit from the mmap store rooted at token.
Build in-memory circuits from the mmap-backed persistent store.
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:48
Semiring-agnostic in-memory provenance circuit.
Fix gettext macro conflicts between PostgreSQL and the C++ STL.
Boolean circuit for provenance formula evaluation.
double WeightMC(gate_t g, std::string opt) const
Compute the probability using the weightmc model counter.
double possibleWorlds(gate_t g) const
Compute the probability by exact enumeration of all possible worlds.
dDNNF makeDD(gate_t g, const std::string &method, const std::string &args) const
Dispatch to the appropriate d-DNNF construction method.
double monteCarlo(gate_t g, unsigned samples) const
Estimate the probability via Monte Carlo sampling.
void rewriteMultivaluedGates()
Rewrite all MULVAR/MULIN gate clusters into standard AND/OR/NOT circuits.
double independentEvaluation(gate_t g) const
Compute the probability exactly when inputs are independent.
Exception type thrown by circuit operations on invalid input.
Definition Circuit.h:205
virtual char const * what() const noexcept
Return the error message as a C-string.
Definition Circuit.h:219
double probabilityEvaluation() const
Compute the exact probability of the d-DNNF being true.
Definition dDNNF.cpp:137
Constructs a d-DNNF from a Boolean circuit and its tree decomposition.
Provenance evaluation helpers for HAVING-clause circuits.
Datum probability_evaluate(PG_FUNCTION_ARGS)
PostgreSQL-callable wrapper for probability_evaluate().
static void provsql_sigint_handler(int)
SIGINT handler that sets the global interrupted flag.
static Datum probability_evaluate_internal(pg_uuid_t token, const string &method, const string &args)
Core implementation of probability evaluation for a circuit token.
bool provsql_interrupted
Global variable that becomes true if this particular backend received an interrupt signal.
Definition provsql.c:62
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
#define provsql_warning(fmt,...)
Emit a ProvSQL warning message (execution continues).
Background worker and IPC primitives for mmap-backed circuit storage.
Shared-memory segment and inter-process pipe management.
Core types, constants, and utilities shared across ProvSQL.
C++ utility functions for UUID manipulation.
UUID structure.