ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
ddnnf_stats.cpp
Go to the documentation of this file.
1/**
2 * @file ddnnf_stats.cpp
3 * @brief SQL function @c provsql.ddnnf_stats() – structural statistics
4 * of the d-DNNF a given compiler produces for a provenance
5 * circuit.
6 *
7 * Compiles the Boolean circuit with the requested compiler / meta-route
8 * (the same @c makeDDByName dispatch used by @c compile_to_ddnnf_dot),
9 * then reports node / edge / gate-type counts, smoothness, longest-path
10 * depth, the wall-clock compile time, and the circuit's treewidth (when
11 * computable). This makes "compare what each compiler produces on the
12 * same circuit" a measurable operation rather than an eyeball of DOT.
13 */
14extern "C" {
15#include "postgres.h"
16#include "fmgr.h"
17#if PG_VERSION_NUM >= 160000
18#include "varatt.h"
19#endif
20#include "catalog/pg_type.h"
21#include "utils/jsonb.h"
22#include "utils/fmgrprotos.h"
23#include "utils/uuid.h"
24#include "provsql_shmem.h"
25#include "provsql_utils.h"
26
27PG_FUNCTION_INFO_V1(ddnnf_stats);
28}
29
30#include "c_cpp_compatibility.h"
31#include "BooleanCircuit.h"
32#include "CircuitFromMMap.h"
33#include "dDNNF.h"
34#include "TreeDecomposition.h"
35#include "provsql_utils_cpp.h"
36#include "tool_registry_sync.h"
37
38#include <chrono>
39#include <sstream>
40#include <string>
41
42using namespace std;
43
44/**
45 * @brief PostgreSQL-callable entry point.
46 *
47 * Arguments: @c token (uuid), @c compiler (text, default @c "d4").
48 * Returns: jsonb object with the d-DNNF statistics.
49 */
50Datum ddnnf_stats(PG_FUNCTION_ARGS)
51{
52 provsql_sync_tool_registry(); // honour persisted tool-registry overrides
53 try {
54 if(PG_ARGISNULL(0))
55 PG_RETURN_NULL();
56 pg_uuid_t *token = DatumGetUUIDP(PG_GETARG_DATUM(0));
57
58 string compiler = ""; // empty => preference-ranked best available compiler
59 if(!PG_ARGISNULL(1)) {
60 text *t = PG_GETARG_TEXT_P(1);
61 compiler = string(VARDATA(t), VARSIZE(t)-VARHDRSZ);
62 }
63
64 gate_t root;
65 BooleanCircuit c = getBooleanCircuit(*token, root);
67
68 // Time only the compilation: the treewidth probe below is a
69 // separate, untimed introspection step. "inversion-free" builds the
70 // structured d-DNNF over the generic circuit's order keys (see
71 // buildInversionFreeDDNNF) rather than the BooleanCircuit dispatch; the
72 // treewidth probe below still runs on c, which is the point -- it shows the
73 // structured d-DNNF stays small even where the treewidth is large.
74 auto t0 = std::chrono::steady_clock::now();
75 // Keeps the external-compilation default (this surface reports d-DNNF
76 // compiler stats); the makeDD cost optimizer ('auto') is for shapley /
77 // banzhaf, not the KC-compiler inspection surfaces.
78 dDNNF d = (compiler == "inversion-free")
80 : c.makeDDByName(root, compiler);
81 auto t1 = std::chrono::steady_clock::now();
82 double compile_ms =
83 std::chrono::duration<double, std::milli>(t1 - t0).count();
84
85 dDNNF::Stats s = d.nodeStats();
86
87 // Best-effort treewidth of the circuit's primal graph: informative
88 // regardless of the chosen compiler, but may exceed the supported
89 // limit, in which case we report null rather than failing.
90 bool has_tw = false;
91 unsigned treewidth = 0;
92 try {
94 treewidth = td.getTreewidth();
95 has_tw = true;
96 } catch(...) {
97 has_tw = false;
98 }
99
100 std::ostringstream out;
101 out << '{';
102 out << "\"compiler\":\"";
103 for(char ch : compiler)
104 out << (ch == '"' || ch == '\\' ? std::string("\\") + ch : std::string(1, ch));
105 out << "\"";
106 out << ",\"nodes\":" << s.nodes;
107 out << ",\"edges\":" << s.edges;
108 out << ",\"and\":" << s.and_gates;
109 out << ",\"or\":" << s.or_gates;
110 out << ",\"not\":" << s.not_gates;
111 out << ",\"inputs\":" << s.inputs;
112 out << ",\"smooth\":" << (s.smooth ? "true" : "false");
113 out << ",\"depth\":" << s.depth;
114 out << ",\"treewidth\":";
115 if(has_tw) out << treewidth; else out << "null";
116 out << ",\"compile_ms\":" << compile_ms;
117 out << '}';
118
119 Datum json_datum = DirectFunctionCall1(
120 jsonb_in, CStringGetDatum(pstrdup(out.str().c_str())));
121 PG_RETURN_DATUM(json_datum);
122 } catch(const std::exception &e) {
123 provsql_error("%s", e.what());
124 } catch(...) {
125 provsql_error("Unknown exception");
126 }
127 PG_RETURN_NULL();
128}
Boolean provenance circuit with support for knowledge compilation.
BooleanCircuit getBooleanCircuit(GenericCircuit &gc, pg_uuid_t token, gate_t &gate, std::unordered_map< gate_t, gate_t > &gc_to_bc)
Build a BooleanCircuit from an already-loaded GenericCircuit.
Build in-memory circuits from the mmap-backed persistent store.
dDNNF buildInversionFreeDDNNF(pg_uuid_t token)
Compile a query certified inversion-free to its structured d-DNNF.
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
Tree decomposition of a Boolean circuit for knowledge compilation.
Fix macro conflicts between PostgreSQL headers and the C++ STL/Boost.
Boolean circuit for provenance formula evaluation.
void rewriteMultivaluedGates()
Rewrite all MULVAR/MULIN gate clusters into standard AND/OR/NOT circuits.
dDNNF makeDDByName(gate_t g, const std::string &name) const
Build a dDNNF from a single compiler/route name.
Tree decomposition of a Boolean circuit's primal graph.
unsigned getTreewidth() const
Return the treewidth of this decomposition.
A d-DNNF circuit supporting exact probabilistic and game-theoretic evaluation.
Definition dDNNF.h:71
Stats nodeStats() const
Compute structural statistics over the gates reachable from root.
Definition dDNNF.cpp:744
Decomposable Deterministic Negation Normal Form circuit.
Datum ddnnf_stats(PG_FUNCTION_ARGS)
PostgreSQL-callable entry point.
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
Shared-memory segment and inter-process pipe management.
Core types, constants, and utilities shared across ProvSQL.
C++ utility functions for UUID manipulation.
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
UUID structure.
void provsql_sync_tool_registry()
Rebuild the in-memory registry as "compiled seed overlaid with the provsql.tool_overrides rows"...
Reload the in-memory external-tool registry from its persistent overrides.