59 std::vector<gate_t> stack{g};
61 while(!stack.empty()) {
62 const gate_t u = stack.back();
79 "The requested semiring does not admit a homomorphism "
80 "from Boolean functions; this gate's wires were rewritten "
81 "under a Boolean-only rule (times-idempotence or "
82 "times-absorbs-plus, applied under the 'boolean' "
83 "provenance class) and the evaluation is unsound under "
84 "this semiring. Re-run under a more general provenance "
85 "class, or pick a Boolean-compatible semiring (boolean, "
86 "boolexpr, formula, ...).");
94 && !
semiring.compatibleWithBooleanRewrite())
96 "The requested semiring is not absorptive; this gate's "
97 "wires were rewritten under an absorptive rule "
98 "(plus-idempotence, plus-with-one absorber or "
99 "plus-absorbs-times, applied under the 'absorptive' or "
100 "'boolean' provenance class) and the evaluation is "
101 "unsound under this semiring. Re-run under the "
102 "'semiring' provenance class, or pick an absorptive "
103 "semiring (probability, boolean, nonnegative "
106 if(provenance_mapping.find(u) != provenance_mapping.end()) {
117 provenance_mapping.emplace(u,
semiring.one());
129 provenance_mapping.emplace(u,
semiring.zero());
161 const std::string assumption =
getExtra(u);
162 if(assumption.empty() || assumption ==
"boolean") {
163 if(!
semiring.compatibleWithBooleanRewrite())
165 "The requested semiring does not admit a homomorphism "
166 "from Boolean functions; the wrapped sub-circuit was "
167 "computed under a Boolean-provenance assumption "
168 "(typically by the safe-query rewrite, "
169 "provenance class 'boolean') and the evaluation is "
170 "unsound under this semiring. Re-run the query under "
171 "a more general provenance class, or pick a "
172 "Boolean-compatible semiring (boolean, boolexpr, "
174 }
else if(assumption ==
"absorptive") {
177 "The requested semiring is not absorptive; the "
178 "wrapped sub-circuit only represents the absorptive "
179 "quotient of a recursive query's provenance "
180 "(fixpoint truncation or compiled reachability "
181 "circuit), so its value is only defined for "
182 "absorptive semirings (probability, boolean, "
183 "formula-with-absorption, nonnegative tropical, "
184 "...). Counting and why-provenance of cyclic "
185 "recursion are genuinely infinite; on acyclic "
186 "data, re-run under the 'semiring' provenance "
212 "Unknown assumption marker '" + assumption +
"'");
221 "Comparison operator OID " +
234 if(provenance_mapping.find(c) == provenance_mapping.end()) {
242 const auto childValue = [&](
int i) ->
const typename S::value_type & {
243 return provenance_mapping.at(
getWires(u)[i]);
250 std::vector<typename S::value_type> childrenResult;
252 childrenResult.push_back(provenance_mapping.at(c));
254 childrenResult.erase(std::remove(std::begin(childrenResult), std::end(childrenResult),
semiring.zero()),
255 childrenResult.end());
256 provenance_mapping.emplace(u,
semiring.plus(childrenResult));
259 for(
const auto &c: childrenResult) {
266 provenance_mapping.emplace(u,
semiring.zero());
268 childrenResult.erase(std::remove(std::begin(childrenResult), std::end(childrenResult),
semiring.one()),
269 childrenResult.end());
270 provenance_mapping.emplace(u,
semiring.times(childrenResult));
273 if(childrenResult[0]==
semiring.zero() || childrenResult[0]==childrenResult[1])
274 provenance_mapping.emplace(u,
semiring.zero());
276 provenance_mapping.emplace(u,
semiring.monus(childrenResult[0], childrenResult[1]));
282 provenance_mapping.emplace(u,
semiring.delta(childValue(0)));
293 provenance_mapping.emplace(u, childValue(0));
300 provenance_mapping.emplace(u,
semiring.cmp(childValue(0), op, childValue(1)));
305 provenance_mapping.emplace(u,
semiring.semimod(childValue(0), childValue(1)));
314 std::vector<typename S::value_type> vec;
316 vec.push_back(provenance_mapping.at(c));
317 provenance_mapping.emplace(u,
semiring.agg(op, vec));
330 std::vector<typename S::value_type> vec;
332 vec.push_back(provenance_mapping.at(c));
333 provenance_mapping.emplace(u,
semiring.conditioned(vec));
349 const std::string key =
"L:";
350 std::size_t p = ex.find(key);
351 if(p != std::string::npos) {
352 std::size_t e = ex.find(
' ', p);
353 const std::string luid =
354 ex.substr(p + key.size(),
355 e == std::string::npos ? std::string::npos : e - p - key.size());
357 if(
getUUID(c) == luid) { lineage = c;
break; }
360 provenance_mapping.emplace(u, provenance_mapping.at(lineage));
362 provenance_mapping.emplace(u, childValue(0));
373 std::vector<typename S::value_type> vec;
375 vec.push_back(provenance_mapping.at(c));
376 provenance_mapping.emplace(u,
semiring.guarded_case(vec));
387 std::vector<typename S::value_type> params;
389 params.push_back(provenance_mapping.at(c));
399 "Arithmetic operator tag " +
402 std::vector<typename S::value_type> vec;
404 vec.push_back(provenance_mapping.at(c));
416 std::vector<double> probs;
417 std::vector<std::string> outcomes;
418 for(std::size_t i = 1; i < w.size(); ++i) {
419 probs.push_back(
getProb(w[i]));
422 provenance_mapping.emplace(
423 u,
semiring.categorical(childValue(0), probs, outcomes));
427 "gate_mixture must have exactly three children "
428 "[p_token, x_token, y_token]");
429 provenance_mapping.emplace(
430 u,
semiring.mixture(childValue(0), childValue(1), childValue(2)));
439 "gate_observe must have exactly one child (the observed leaf)");
440 provenance_mapping.emplace(u,
semiring.observe(childValue(0),
getExtra(u)));
451 return provenance_mapping.at(g);