68 SemiringT S = SemiringT{})
74 if (cmp_gates.empty())
84 auto certifiable_contributors =
85 [&](
const std::vector<typename SemiringT::value_type> &kv) ->
bool {
90 for (
size_t i = 0; i < kv.size(); ++i) {
91 if (!S.independent_literal(kv[i]))
95 if (kv[i] == S.one() || kv[i] == S.zero())
97 for (
size_t j = 0; j < i; ++j)
112 auto combine_exhaustive_worlds =
113 [&](
const std::vector<mask_t> &worlds,
114 const std::vector<typename SemiringT::value_type> &kvals,
120 if (certifiable_contributors(kvals)) {
121 std::vector<typename SemiringT::value_type> disjuncts;
122 disjuncts.reserve(worlds.size());
123 for (
const auto &mask : worlds) {
124 std::vector<typename SemiringT::value_type> present, missing;
125 for (
size_t i = 0; i < kvals.size(); ++i)
126 (mask[i] ? present : missing).push_back(kvals[i]);
127 disjuncts.push_back(S.certified_world_term(present, missing));
129 return S.certified_exclusive_plus(disjuncts);
132 std::vector<typename SemiringT::value_type> disjuncts;
133 disjuncts.reserve(worlds.size());
134 const size_t n = kvals.size();
136 for (
const auto &mask : worlds) {
137 std::vector<typename SemiringT::value_type> present, missing;
141 for (
size_t i = 0; i < n; ++i) {
143 if (kvals[i] != S.one())
144 present.push_back(kvals[i]);
154 if (kvals[i] != S.zero())
155 missing.push_back(kvals[i]);
159 auto present_prod = S.times(present);
161 if (missing.empty()) {
162 disjuncts.push_back(std::move(present_prod));
164 auto monus_factor = S.monus(S.one(), S.plus(missing));
165 auto term = monus_factor;
166 if (present_prod != S.one())
167 term = S.times(std::vector<typename SemiringT::value_type>{
168 present_prod, monus_factor});
169 disjuncts.push_back(std::move(term));
173 return S.plus(disjuncts);
176 auto pw_from_cmp_gate = [&](
gate_t cmp_gate,
typename SemiringT::value_type &pw_out) ->
bool {
177 const auto &cw = c.
getWires(cmp_gate);
178 if (cw.size() != 2)
return false;
185 if (!okop)
return false;
194 const bool is_scalar =
197 const auto &children = c.
getWires(agg_side);
210 std::vector<std::string> mvals_str;
211 std::vector<typename SemiringT::value_type> kvals;
212 mvals_str.reserve(children.size());
213 kvals.reserve(children.size());
214 for (
gate_t ch : children) {
219 mvals_str.push_back(m_str);
220 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
227 throw std::runtime_error(
228 "comparing an aggregate with a text constant in HAVING "
229 "is only implemented for choose()");
232 throw std::runtime_error(
233 "only = and <> are supported when comparing choose() "
234 "with a text constant");
246 if (certifiable_contributors(kvals)) {
247 std::vector<typename SemiringT::value_type> disjuncts;
248 std::vector<typename SemiringT::value_type> before;
249 for (
size_t i = 0; i < kvals.size(); ++i) {
251 ? (mvals_str[i] == C_str)
252 : (mvals_str[i] != C_str);
254 disjuncts.push_back(S.certified_world_term(
255 std::vector<typename SemiringT::value_type>{kvals[i]},
257 before.push_back(kvals[i]);
259 pw_out = disjuncts.empty() ? S.zero()
260 : S.certified_exclusive_plus(disjuncts);
263 const auto one = S.one();
264 std::vector<typename SemiringT::value_type> disjuncts;
266 for (
size_t i = 0; i < kvals.size(); ++i) {
268 ? (mvals_str[i] == C_str)
269 : (mvals_str[i] != C_str);
272 disjuncts.push_back(kvals[i]);
273 else if (kvals[i] == one)
274 disjuncts.push_back(prefix);
276 disjuncts.push_back(S.times(
277 std::vector<typename SemiringT::value_type>{kvals[i], prefix}));
279 auto absent = S.monus(one, kvals[i]);
280 prefix = (prefix == one)
282 : S.times(
std::vector<typename SemiringT::value_type>{
285 pw_out = disjuncts.empty() ? S.zero() : S.plus(disjuncts);
310 throw std::runtime_error(
311 "only = and <> are supported when comparing a boolean aggregate "
312 "(bool_or / bool_and / every) with a constant in HAVING");
314 auto parse_bool = [](
const std::string &s,
bool &ok) ->
bool {
316 if (s ==
"t" || s ==
"true" || s ==
"1")
return true;
317 if (s ==
"f" || s ==
"false" || s ==
"0")
return false;
318 ok =
false;
return false;
324 const bool C = parse_bool(C_str, okc);
325 if (!okc)
return false;
329 std::vector<bool> vals;
330 std::vector<typename SemiringT::value_type> kvals;
331 vals.reserve(children.size());
332 kvals.reserve(children.size());
333 for (
gate_t ch : children) {
339 const bool b = parse_bool(m_str, okv);
340 if (!okv)
return false;
342 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
346 std::vector<size_t> someE;
347 std::vector<size_t> noneF;
348 if (want_or == target) {
351 for (
size_t i = 0; i < vals.size(); ++i)
352 if (vals[i] == want_or) someE.push_back(i);
356 for (
size_t i = 0; i < vals.size(); ++i)
357 (vals[i] == want_or ? noneF : someE).push_back(i);
360 if (someE.empty()) { pw_out = S.zero();
return true; }
362 if (certifiable_contributors(kvals)) {
363 std::vector<typename SemiringT::value_type> disjuncts;
364 std::vector<typename SemiringT::value_type> before;
365 for (
size_t e : someE) {
366 std::vector<typename SemiringT::value_type> missing = before;
367 for (
size_t f : noneF) missing.push_back(kvals[f]);
368 disjuncts.push_back(S.certified_world_term(
369 std::vector<typename SemiringT::value_type>{kvals[e]}, missing));
370 before.push_back(kvals[e]);
372 pw_out = S.certified_exclusive_plus(disjuncts);
376 const auto one = S.one();
378 auto none_factor = one;
379 for (
size_t f : noneF) {
380 auto absent = S.monus(one, kvals[f]);
381 none_factor = (none_factor == one)
383 : S.times(
std::vector<typename SemiringT::value_type>{none_factor,
387 std::vector<typename SemiringT::value_type> disjuncts;
389 for (
size_t i : someE) {
391 disjuncts.push_back(kvals[i]);
392 else if (kvals[i] == one)
393 disjuncts.push_back(prefix);
395 disjuncts.push_back(S.times(
396 std::vector<typename SemiringT::value_type>{kvals[i], prefix}));
397 auto absent = S.monus(one, kvals[i]);
398 prefix = (prefix == one)
400 : S.times(
std::vector<typename SemiringT::value_type>{prefix, absent});
402 auto some_value = disjuncts.empty() ? S.zero() : S.plus(disjuncts);
403 if (none_factor == one)
405 else if (some_value == one)
406 pw_out = none_factor;
409 std::vector<typename SemiringT::value_type>{none_factor, some_value});
422 throw std::runtime_error(
423 "only = and <> are supported when comparing array_agg() with a "
424 "constant array in HAVING");
428 std::vector<std::string> target;
431 std::vector<std::string> vals;
432 std::vector<typename SemiringT::value_type> kvals;
433 vals.reserve(children.size());
434 kvals.reserve(children.size());
435 for (
gate_t ch : children) {
440 vals.push_back(m_str);
441 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
449 auto canon_bool = [](std::string &s) {
450 if (s ==
"t" || s ==
"true" || s ==
"1") s =
"true";
451 else if (s ==
"f" || s ==
"false" || s ==
"0") s =
"false";
453 for (
auto &e : target) canon_bool(e);
454 for (
auto &v : vals) canon_bool(v);
459 pw_out = combine_exhaustive_worlds(worlds, kvals,
false,
460 effective_op, agg_kind);
471 long C_mant = 0;
int C_scale = 0;
474 std::vector<long> m_mant;
475 std::vector<int> m_scale;
476 std::vector<typename SemiringT::value_type> kvals;
477 m_mant.reserve(children.size());
478 m_scale.reserve(children.size());
479 kvals.reserve(children.size());
480 for (
gate_t ch : children) {
485 long mm = 0;
int ms = 0;
487 m_mant.push_back(mm);
488 m_scale.push_back(ms);
489 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
493 int target_scale = C_scale;
494 for (
int ms : m_scale) target_scale = std::max(target_scale, ms);
496 if (!
rescale_to(C_mant, C_scale, target_scale, C))
return false;
497 std::vector<long> mvals(m_mant.size());
498 for (
size_t i = 0; i < m_mant.size(); ++i)
499 if (!
rescale_to(m_mant[i], m_scale[i], target_scale, mvals[i]))
return false;
507 const bool certify = certifiable_contributors(kvals);
511 certify ?
false : S.absorptive(),
514 pw_out = combine_exhaustive_worlds(worlds, kvals, upset, op, agg_kind);
533 std::vector<std::pair<int, double> > contribs;
536 auto text_is_int = [](
const std::string &s) ->
bool {
537 if (s.empty())
return false;
539 if (!((ch >=
'0' && ch <=
'9') || ch ==
'+' || ch ==
'-'))
543 std::map<gate_t, AggInfo> aggs;
544 std::map<gate_t, int> kindex;
545 std::vector<gate_t> kgates;
547 std::function<bool(
gate_t)> collect = [&](
gate_t gx) ->
bool {
565 auto it = kindex.find(kg);
566 if (it == kindex.end()) {
567 idx =
static_cast<int>(kgates.size());
569 kgates.push_back(kg);
573 try { m = std::stod(ms); }
catch (...) {
return false; }
574 ai.contribs.emplace_back(idx, m);
576 aggs.emplace(gx, std::move(ai));
597 if (!collect(Lx) || !collect(Rx))
601 const size_t n = kgates.size();
602 if (n == 0 || n > 24)
607 std::function<bool(
gate_t, uint64_t,
double &,
bool &)> eval =
608 [&](
gate_t gx, uint64_t world,
double &out,
bool &is_int) ->
bool {
612 try { out = std::stod(s); }
catch (...) {
return false; }
613 is_int = text_is_int(s);
617 std::string ms;
gate_t kg{};
619 try { out = std::stod(ms); }
catch (...) {
return false; }
620 is_int = text_is_int(ms);
624 const AggInfo &ai = aggs.at(gx);
625 double acc = 0, mn = 0, mx = 0;
628 for (
const auto &pr : ai.contribs)
629 if (world & (uint64_t(1) << pr.first)) {
630 double m = pr.second;
632 if (first) { mn = mx = m; first =
false; }
633 else { mn = std::min(mn, m); mx = std::max(mx, m); }
655 if (cnt == 0 && !ai.is_scalar)
return false;
656 out = acc;
return true;
660 default:
return false;
665 unsigned aop =
static_cast<unsigned>(c.
getInfos(gx).first);
671 if (!eval(ch, world, v, vi))
return false;
673 all_int = all_int && vi;
675 out = r; is_int = all_int;
return true;
678 if (w.size() != 2)
return false;
679 double a, b;
bool ai, bi;
680 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
681 out = a - b; is_int = ai && bi;
return true;
684 if (w.size() != 2)
return false;
685 double a, b;
bool ai, bi;
686 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
687 if (b == 0)
return false;
689 out =
static_cast<double>(
static_cast<long long>(a) /
690 static_cast<long long>(b));
693 out = a / b; is_int =
false;
698 if (w.size() != 1)
return false;
700 if (!eval(w[0], world, a, ai))
return false;
701 out = -a; is_int = ai;
return true;
704 if (w.empty())
return false;
705 double r = 0;
bool all_int =
true, first =
true;
708 if (!eval(ch, world, v, vi))
return false;
709 if (first) { r = v; first =
false; }
712 all_int = all_int && vi;
714 out = r; is_int = all_int;
return true;
721 std::vector<typename SemiringT::value_type> kval(n);
722 for (
size_t i = 0; i < n; ++i)
723 kval[i] = c.
evaluate<SemiringT>(kgates[i], mapping, S);
727 const bool certify = certifiable_contributors(kval);
737 const bool empty_world_valid =
739 std::all_of(aggs.begin(), aggs.end(),
740 [](
const std::pair<const gate_t, AggInfo> &e) {
741 return e.second.is_scalar;
744 std::vector<typename SemiringT::value_type> disjuncts;
745 const uint64_t total = uint64_t(1) << n;
746 for (uint64_t world = empty_world_valid ? 0 : 1; world < total; ++world) {
749 if (!eval(Lx, world, lv, lint) || !eval(Rx, world, rv, rint))
763 std::vector<typename SemiringT::value_type> present, missing;
764 for (
size_t i = 0; i < n; ++i) {
765 if (world & (uint64_t(1) << i)) {
766 if (certify || kval[i] != S.one()) present.push_back(kval[i]);
768 if (certify || kval[i] != S.zero()) missing.push_back(kval[i]);
772 disjuncts.push_back(S.certified_world_term(present, missing));
775 auto present_prod = S.times(present);
777 disjuncts.push_back(std::move(present_prod));
779 auto monus_factor = S.monus(S.one(), S.plus(missing));
781 present_prod == S.one()
783 : S.times(std::vector<typename SemiringT::value_type>{
784 present_prod, monus_factor}));
788 pw_out = disjuncts.empty() ? S.zero()
789 : certify ? S.certified_exclusive_plus(disjuncts)
799 return build_general(L, R, op);
811 for (
gate_t cmp_gate : cmp_gates) {
812 typename SemiringT::value_type pw;
813 if (!pw_from_cmp_gate(cmp_gate, pw))
816 mapping[cmp_gate] = std::move(pw);