24#include "catalog/pg_type.h"
25#include "utils/jsonb.h"
26#include "utils/fmgrprotos.h"
27#include "utils/uuid.h"
41#include <unordered_map>
47json_escape(std::ostringstream &out,
const std::string &s)
51 case '"': out <<
"\\\"";
break;
52 case '\\': out <<
"\\\\";
break;
53 case '\b': out <<
"\\b";
break;
54 case '\f': out <<
"\\f";
break;
55 case '\n': out <<
"\\n";
break;
56 case '\r': out <<
"\\r";
break;
57 case '\t': out <<
"\\t";
break;
59 if (
static_cast<unsigned char>(c) < 0x20) {
61 snprintf(buf,
sizeof buf,
"\\u%04x", c);
71emit_str(std::ostringstream &out,
const std::string &s)
85emit_node_row(std::ostringstream &out,
89 const std::string &node_uuid,
90 const std::string *parent_uuid,
94 if (!first) out <<
',';
103 const unsigned NO_INFO =
static_cast<unsigned>(-1);
106 out <<
"\"node\":"; emit_str(out, node_uuid);
107 out <<
",\"parent\":";
108 if (parent_uuid) emit_str(out, *parent_uuid);
110 out <<
",\"child_pos\":";
111 if (parent_uuid) out << child_pos;
113 out <<
",\"gate_type\":"; emit_str(out, type_name);
114 out <<
",\"info1\":";
115 if (infos.first == NO_INFO) { out <<
"null"; }
116 else { out <<
'"' << infos.first <<
'"'; }
117 out <<
",\"info2\":";
118 if (infos.second == NO_INFO) { out <<
"null"; }
119 else { out <<
'"' << infos.second <<
'"'; }
120 out <<
",\"extra\":";
132 const double p = gc.
getProb(g);
134 if (p != p) out <<
"null";
144 out <<
",\"boolean_assumed\":true";
147 out <<
",\"absorptive_assumed\":true";
149 out <<
",\"depth\":" << depth;
159 int max_depth = PG_GETARG_INT32(1);
161 std::ostringstream out;
175 Datum json_datum = DirectFunctionCall1(
176 jsonb_in, CStringGetDatum(pstrdup(out.str().c_str())));
177 PG_RETURN_DATUM(json_datum);
202 std::unordered_set<gate_t> reachable;
204 std::queue<gate_t> q;
205 reachable.insert(root_gate);
208 gate_t g = q.front(); q.pop();
210 if (reachable.insert(c).second) q.push(c);
216 std::unordered_map<gate_t, int> indeg;
217 for (
gate_t g : reachable) indeg[g] = 0;
218 for (
gate_t g : reachable) {
220 if (reachable.count(c)) indeg[c]++;
223 std::unordered_map<gate_t, int> depth_of;
224 depth_of[root_gate] = 0;
225 std::queue<gate_t> bfs;
227 while (!bfs.empty()) {
228 gate_t g = bfs.front(); bfs.pop();
230 if (d >= max_depth)
continue;
232 if (!reachable.count(c))
continue;
233 auto it = depth_of.find(c);
234 int candidate = d + 1;
235 if (it == depth_of.end() || it->second < candidate) {
236 depth_of[c] = candidate;
238 if (--indeg[c] == 0) bfs.push(c);
246 const std::string root_uuid = gc.
getUUID(root_gate);
247 emit_node_row(out, first, gc, root_gate, root_uuid,
251 for (
const auto &[g, d] : depth_of) {
252 if (d >= max_depth)
continue;
253 const std::string parent_uuid = gc.
getUUID(g);
255 for (std::size_t i = 0; i < wires.size(); ++i) {
257 auto cit = depth_of.find(c);
258 if (cit == depth_of.end())
continue;
259 if (cit->second > max_depth)
continue;
260 const std::string child_uuid = gc.
getUUID(c);
261 emit_node_row(out, first, gc, c, child_uuid,
262 &parent_uuid,
static_cast<int>(i + 1),
266 }
catch (
const std::exception &e) {
269 provsql_error(
"simplified_circuit_subgraph: unknown exception");
274 Datum json_datum = DirectFunctionCall1(
275 jsonb_in, CStringGetDatum(pstrdup(out.str().c_str())));
276 PG_RETURN_DATUM(json_datum);
GenericCircuit getGenericCircuit(pg_uuid_t token)
Build a GenericCircuit from the mmap store rooted at token.
Build in-memory circuits from the mmap-backed persistent store.
gate_t
Strongly-typed gate identifier.
Semiring-agnostic in-memory provenance circuit.
Peephole simplifier for continuous gate_arith sub-circuits.
Datum simplified_circuit_subgraph(PG_FUNCTION_ARGS)
Exception type thrown by circuit operations on invalid input.
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
gateType getGateType(gate_t g) const
Return the type of gate g.
uuid getUUID(gate_t g) const
Return the UUID string associated with gate g.
gate_t getGate(const uuid &u)
Return (or create) the gate associated with UUID u.
In-memory provenance circuit with semiring-generic evaluation.
std::string getExtra(gate_t g) const
Return the string extra for gate g.
double getProb(gate_t g) const
Return the probability for gate g.
bool isAbsorptiveAssumed(gate_t g) const
Report whether g carries the absorptive-assumption flag.
bool isBooleanAssumed(gate_t g) const
Report whether g carries the Boolean-assumption flag.
std::pair< unsigned, unsigned > getInfos(gate_t g) const
Return the integer annotation pair for gate g.
unsigned runHybridSimplifier(GenericCircuit &gc)
Run the peephole simplifier over gc.
bool provsql_hybrid_evaluation
Run the hybrid-evaluator simplifier inside probability_evaluate; controlled by the provsql....
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
const char * gate_type_name[]
Names of gate types.
Core types, constants, and utilities shared across ProvSQL.
string uuid2string(pg_uuid_t uuid)
Format a pg_uuid_t as a std::string.
C++ utility functions for UUID manipulation.
static void json_escape(std::ostringstream &out, const std::string &s)