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));
495 for (
size_t i = 0; i < m_mant.size(); ++i)
496 if (!(m_mant[i] == 1 && m_scale[i] == 0)) { all_one =
false;
break; }
501 int target_scale = C_scale;
502 for (
int ms : m_scale) target_scale = std::max(target_scale, ms);
504 if (!
rescale_to(C_mant, C_scale, target_scale, C))
return false;
505 std::vector<long> mvals(m_mant.size());
506 for (
size_t i = 0; i < m_mant.size(); ++i)
507 if (!
rescale_to(m_mant[i], m_scale[i], target_scale, mvals[i]))
return false;
515 const bool certify = certifiable_contributors(kvals);
519 certify ?
false : S.absorptive(),
522 pw_out = combine_exhaustive_worlds(worlds, kvals, upset, op, agg_kind);
540 std::vector<std::pair<int, double> > contribs;
543 auto text_is_int = [](
const std::string &s) ->
bool {
544 if (s.empty())
return false;
546 if (!((ch >=
'0' && ch <=
'9') || ch ==
'+' || ch ==
'-'))
550 std::map<gate_t, AggInfo> aggs;
551 std::map<gate_t, int> kindex;
552 std::vector<gate_t> kgates;
554 std::function<bool(
gate_t)> collect = [&](
gate_t gx) ->
bool {
570 auto it = kindex.find(kg);
571 if (it == kindex.end()) {
572 idx =
static_cast<int>(kgates.size());
574 kgates.push_back(kg);
578 try { m = std::stod(ms); }
catch (...) {
return false; }
579 ai.contribs.emplace_back(idx, m);
581 aggs.emplace(gx, std::move(ai));
602 if (!collect(Lx) || !collect(Rx))
606 const size_t n = kgates.size();
607 if (n == 0 || n > 24)
612 std::function<bool(
gate_t, uint64_t,
double &,
bool &)> eval =
613 [&](
gate_t gx, uint64_t world,
double &out,
bool &is_int) ->
bool {
617 try { out = std::stod(s); }
catch (...) {
return false; }
618 is_int = text_is_int(s);
622 std::string ms;
gate_t kg{};
624 try { out = std::stod(ms); }
catch (...) {
return false; }
625 is_int = text_is_int(ms);
629 const AggInfo &ai = aggs.at(gx);
630 double acc = 0, mn = 0, mx = 0;
633 for (
const auto &pr : ai.contribs)
634 if (world & (uint64_t(1) << pr.first)) {
635 double m = pr.second;
637 if (first) { mn = mx = m; first =
false; }
638 else { mn = std::min(mn, m); mx = std::max(mx, m); }
647 default:
return false;
652 unsigned aop =
static_cast<unsigned>(c.
getInfos(gx).first);
658 if (!eval(ch, world, v, vi))
return false;
660 all_int = all_int && vi;
662 out = r; is_int = all_int;
return true;
665 if (w.size() != 2)
return false;
666 double a, b;
bool ai, bi;
667 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
668 out = a - b; is_int = ai && bi;
return true;
671 if (w.size() != 2)
return false;
672 double a, b;
bool ai, bi;
673 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
674 if (b == 0)
return false;
676 out =
static_cast<double>(
static_cast<long long>(a) /
677 static_cast<long long>(b));
680 out = a / b; is_int =
false;
685 if (w.size() != 1)
return false;
687 if (!eval(w[0], world, a, ai))
return false;
688 out = -a; is_int = ai;
return true;
695 std::vector<typename SemiringT::value_type> kval(n);
696 for (
size_t i = 0; i < n; ++i)
697 kval[i] = c.
evaluate<SemiringT>(kgates[i], mapping, S);
701 const bool certify = certifiable_contributors(kval);
703 std::vector<typename SemiringT::value_type> disjuncts;
704 const uint64_t total = uint64_t(1) << n;
705 for (uint64_t world = 1; world < total; ++world) {
708 if (!eval(Lx, world, lv, lint) || !eval(Rx, world, rv, rint))
722 std::vector<typename SemiringT::value_type> present, missing;
723 for (
size_t i = 0; i < n; ++i) {
724 if (world & (uint64_t(1) << i)) {
725 if (certify || kval[i] != S.one()) present.push_back(kval[i]);
727 if (certify || kval[i] != S.zero()) missing.push_back(kval[i]);
731 disjuncts.push_back(S.certified_world_term(present, missing));
734 auto present_prod = S.times(present);
736 disjuncts.push_back(std::move(present_prod));
738 auto monus_factor = S.monus(S.one(), S.plus(missing));
740 present_prod == S.one()
742 : S.times(std::vector<typename SemiringT::value_type>{
743 present_prod, monus_factor}));
747 pw_out = disjuncts.empty() ? S.zero()
748 : certify ? S.certified_exclusive_plus(disjuncts)
758 return build_general(L, R, op);
761 for (
gate_t cmp_gate : cmp_gates) {
762 typename SemiringT::value_type pw;
763 if (!pw_from_cmp_gate(cmp_gate, pw))
766 mapping[cmp_gate] = std::move(pw);