101 SemiringT S = SemiringT{})
107 if (cmp_gates.empty())
117 auto certifiable_contributors =
118 [&](
const std::vector<typename SemiringT::value_type> &kv) ->
bool {
123 for (
size_t i = 0; i < kv.size(); ++i) {
124 if (!S.independent_literal(kv[i]))
128 if (kv[i] == S.one() || kv[i] == S.zero())
130 for (
size_t j = 0; j < i; ++j)
152 auto combine_exhaustive_worlds =
153 [&](
const std::vector<mask_t> &worlds,
154 const std::vector<typename SemiringT::value_type> &kvals,
155 bool upset,
bool monotone) ->
typename SemiringT::value_type {
159 if (certifiable_contributors(kvals)) {
160 std::vector<typename SemiringT::value_type> disjuncts;
161 disjuncts.reserve(worlds.size());
162 for (
const auto &mask : worlds) {
163 std::vector<typename SemiringT::value_type> present, missing;
164 for (
size_t i = 0; i < kvals.size(); ++i)
165 (mask[i] ? present : missing).push_back(kvals[i]);
166 disjuncts.push_back(S.certified_world_term(present, missing));
168 return S.certified_exclusive_plus(disjuncts);
171 std::vector<typename SemiringT::value_type> disjuncts;
172 disjuncts.reserve(worlds.size());
173 const size_t n = kvals.size();
174 const bool no_monus = upset || (monotone && S.idempotent());
176 for (
const auto &mask : worlds) {
177 std::vector<typename SemiringT::value_type> present, missing;
181 for (
size_t i = 0; i < n; ++i) {
183 if (kvals[i] != S.one())
184 present.push_back(kvals[i]);
185 }
else if (!no_monus) {
186 if (kvals[i] != S.zero())
187 missing.push_back(kvals[i]);
191 auto present_prod = S.times(present);
193 if (missing.empty()) {
194 disjuncts.push_back(std::move(present_prod));
196 auto monus_factor = S.monus(S.one(), S.plus(missing));
197 auto term = monus_factor;
198 if (present_prod != S.one())
199 term = S.times(std::vector<typename SemiringT::value_type>{
200 present_prod, monus_factor});
201 disjuncts.push_back(std::move(term));
205 return S.plus(disjuncts);
230 [&](
const std::vector<long> &mvals,
long C,
231 const std::vector<typename SemiringT::value_type> &kvals,
234 using V =
typename SemiringT::value_type;
235 std::vector<V> lt, le, ge, gt, eq;
236 for (
size_t i = 0; i < kvals.size(); ++i) {
237 if (kvals[i] == S.zero())
continue;
238 if (mvals[i] < C) lt.push_back(kvals[i]);
239 if (mvals[i] <= C) le.push_back(kvals[i]);
240 if (mvals[i] >= C) ge.push_back(kvals[i]);
241 if (mvals[i] > C) gt.push_back(kvals[i]);
242 if (mvals[i] == C) eq.push_back(kvals[i]);
244 auto sum = [&](
const std::vector<V> &v) -> V {
245 return v.empty() ? S.zero() : S.plus(v);
248 auto guarded = [&](
const std::vector<V> &spoilers,
249 const std::vector<V> &witnesses) -> V {
250 if (witnesses.empty())
return S.zero();
251 V w = S.plus(witnesses);
252 if (spoilers.empty())
return w;
253 return S.times(std::vector<V>{S.monus(S.one(), S.plus(spoilers)), w});
259 const std::vector<V> &below = is_max ? gt : lt;
260 const std::vector<V> &below_eq = is_max ? ge : le;
261 const std::vector<V> &above = is_max ? lt : gt;
262 const std::vector<V> &above_eq = is_max ? le : ge;
273 V b = guarded(below_eq, above);
274 if (a == S.zero())
return b;
275 if (b == S.zero())
return a;
276 return S.plus(std::vector<V>{a, b});
297 using fiber_t = std::pair<size_t, std::vector<size_t>>;
298 auto first_present_provenance =
299 [&](
const std::vector<fiber_t> &fibers,
300 const std::vector<typename SemiringT::value_type> &kvals,
301 bool monotone) ->
typename SemiringT::value_type {
302 using V =
typename SemiringT::value_type;
303 if (fibers.empty())
return S.zero();
305 if (S.absorptive() && S.mul_sub_left_distributive()) {
306 std::vector<V> terms;
307 for (
const auto &fb : fibers) {
308 const V &k = kvals[fb.first];
309 if (k == S.zero())
continue;
310 std::vector<V> absent;
311 for (
size_t j : fb.second)
312 if (kvals[j] != S.zero()) absent.push_back(kvals[j]);
313 if (absent.empty()) { terms.push_back(k);
continue; }
314 V guard = S.monus(S.one(), S.plus(absent));
315 terms.push_back(k == S.one() ? guard : S.times(std::vector<V>{guard, k}));
317 return terms.empty() ? S.zero() : S.plus(terms);
320 const size_t n = kvals.size();
321 std::vector<mask_t> worlds;
322 for (
const auto &fb : fibers) {
323 std::vector<bool> fixed(n,
false);
324 fixed[fb.first] =
true;
325 for (
size_t j : fb.second) fixed[j] =
true;
326 std::vector<size_t> free_idx;
327 for (
size_t j = 0; j < n; ++j)
328 if (!fixed[j]) free_idx.push_back(j);
329 const size_t m = free_idx.size();
330 for (
size_t sub = 0; sub < (size_t(1) << m); ++sub) {
332 mask[fb.first] =
true;
333 for (
size_t b = 0; b < m; ++b)
334 if (sub & (
size_t(1) << b)) mask[free_idx[b]] =
true;
335 worlds.push_back(std::move(mask));
338 return combine_exhaustive_worlds(worlds, kvals,
false, monotone);
341 auto pw_from_cmp_gate = [&](
gate_t cmp_gate,
typename SemiringT::value_type &pw_out) ->
bool {
342 const auto &cw = c.
getWires(cmp_gate);
343 if (cw.size() != 2)
return false;
350 if (!okop)
return false;
359 const bool is_scalar =
362 const auto &children = c.
getWires(agg_side);
377 std::vector<std::string> mvals_str;
378 std::vector<typename SemiringT::value_type> kvals;
379 mvals_str.reserve(children.size());
380 kvals.reserve(children.size());
381 for (
gate_t ch : children) {
386 mvals_str.push_back(m_str);
387 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
394 throw std::runtime_error(
395 "comparing an aggregate with a text constant in HAVING "
396 "is only implemented for choose()");
399 throw std::runtime_error(
400 "only = and <> are supported when comparing choose() "
401 "with a text constant");
412 if (certifiable_contributors(kvals)) {
413 std::vector<typename SemiringT::value_type> disjuncts;
414 std::vector<typename SemiringT::value_type> before;
415 for (
size_t i = 0; i < kvals.size(); ++i) {
417 ? (mvals_str[i] == C_str)
418 : (mvals_str[i] != C_str);
420 disjuncts.push_back(S.certified_world_term(
421 std::vector<typename SemiringT::value_type>{kvals[i]},
423 before.push_back(kvals[i]);
425 pw_out = disjuncts.empty() ? S.zero()
426 : S.certified_exclusive_plus(disjuncts);
429 std::vector<fiber_t> fibers;
430 std::vector<size_t> before;
431 for (
size_t i = 0; i < kvals.size(); ++i) {
433 ? (mvals_str[i] == C_str)
434 : (mvals_str[i] != C_str);
435 if (match) fibers.emplace_back(i, before);
438 pw_out = first_present_provenance(fibers, kvals,
false);
464 throw std::runtime_error(
465 "only = and <> are supported when comparing a boolean aggregate "
466 "(bool_or / bool_and / every) with a constant in HAVING");
468 auto parse_bool = [](
const std::string &s,
bool &ok) ->
bool {
470 if (s ==
"t" || s ==
"true" || s ==
"1")
return true;
471 if (s ==
"f" || s ==
"false" || s ==
"0")
return false;
472 ok =
false;
return false;
478 const bool C = parse_bool(C_str, okc);
479 if (!okc)
return false;
483 std::vector<bool> vals;
484 std::vector<typename SemiringT::value_type> kvals;
485 vals.reserve(children.size());
486 kvals.reserve(children.size());
487 for (
gate_t ch : children) {
493 const bool b = parse_bool(m_str, okv);
494 if (!okv)
return false;
496 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
500 std::vector<size_t> someE;
501 std::vector<size_t> noneF;
502 if (want_or == target) {
505 for (
size_t i = 0; i < vals.size(); ++i)
506 if (vals[i] == want_or) someE.push_back(i);
510 for (
size_t i = 0; i < vals.size(); ++i)
511 (vals[i] == want_or ? noneF : someE).push_back(i);
514 if (someE.empty()) { pw_out = S.zero();
return true; }
516 if (certifiable_contributors(kvals)) {
517 std::vector<typename SemiringT::value_type> disjuncts;
518 std::vector<typename SemiringT::value_type> before;
519 for (
size_t e : someE) {
520 std::vector<typename SemiringT::value_type> missing = before;
521 for (
size_t f : noneF) missing.push_back(kvals[f]);
522 disjuncts.push_back(S.certified_world_term(
523 std::vector<typename SemiringT::value_type>{kvals[e]}, missing));
524 before.push_back(kvals[e]);
526 pw_out = S.certified_exclusive_plus(disjuncts);
538 if (noneF.empty() && S.absorptive()) {
539 std::vector<typename SemiringT::value_type> witnesses;
540 for (
size_t e : someE)
541 if (kvals[e] != S.zero()) witnesses.push_back(kvals[e]);
542 pw_out = witnesses.empty() ? S.zero() : S.plus(witnesses);
546 std::vector<fiber_t> fibers;
547 std::vector<size_t> absent = noneF;
548 for (
size_t e : someE) {
549 fibers.emplace_back(e, absent);
552 pw_out = first_present_provenance(fibers, kvals,
566 throw std::runtime_error(
567 "only = and <> are supported when comparing array_agg() with a "
568 "constant array in HAVING");
572 std::vector<std::string> target;
575 std::vector<std::string> vals;
576 std::vector<typename SemiringT::value_type> kvals;
577 vals.reserve(children.size());
578 kvals.reserve(children.size());
579 for (
gate_t ch : children) {
586 m_str = array_null_element();
587 vals.push_back(m_str);
588 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
596 auto canon_bool = [](std::string &s) {
597 if (s ==
"t" || s ==
"true" || s ==
"1") s =
"true";
598 else if (s ==
"f" || s ==
"false" || s ==
"0") s =
"false";
600 for (
auto &e : target) canon_bool(e);
601 for (
auto &v : vals) canon_bool(v);
606 pw_out = combine_exhaustive_worlds(worlds, kvals,
false,
614 auto finish_domain = [&](
const std::vector<long> &mvals,
long C,
615 const std::vector<typename SemiringT::value_type> &kvals)
623 const bool certify = certifiable_contributors(kvals);
633 S.absorptive() && !certify) {
634 const bool existential =
640 if (existential || S.mul_sub_left_distributive()) {
641 pw_out = min_max_scan(mvals, C, kvals, effective_op, agg_kind);
648 certify ?
false : S.absorptive(),
659 bool monotone =
false;
666 std::all_of(mvals.begin(), mvals.end(), [](
long v) { return v >= 0; });
671 pw_out = combine_exhaustive_worlds(worlds, kvals, upset, monotone);
686 std::vector<std::string> m_strs;
687 std::vector<typename SemiringT::value_type> kvals;
688 for (
gate_t ch : children) {
693 m_strs.push_back(m_str);
694 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
696 std::vector<long> ranks;
700 return finish_domain(ranks, C_rank, kvals);
710 long C_mant = 0;
int C_scale = 0;
713 std::vector<long> m_mant;
714 std::vector<int> m_scale;
715 std::vector<typename SemiringT::value_type> kvals;
716 m_mant.reserve(children.size());
717 m_scale.reserve(children.size());
718 kvals.reserve(children.size());
719 for (
gate_t ch : children) {
724 long mm = 0;
int ms = 0;
726 m_mant.push_back(mm);
727 m_scale.push_back(ms);
728 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
732 int target_scale = C_scale;
733 for (
int ms : m_scale) target_scale = std::max(target_scale, ms);
735 if (!
rescale_to(C_mant, C_scale, target_scale, C))
return false;
736 std::vector<long> mvals(m_mant.size());
737 for (
size_t i = 0; i < m_mant.size(); ++i)
738 if (!
rescale_to(m_mant[i], m_scale[i], target_scale, mvals[i]))
return false;
740 return finish_domain(mvals, C, kvals);
758 std::vector<std::pair<int, double> > contribs;
761 auto text_is_int = [](
const std::string &s) ->
bool {
762 if (s.empty())
return false;
764 if (!((ch >=
'0' && ch <=
'9') || ch ==
'+' || ch ==
'-'))
768 std::map<gate_t, AggInfo> aggs;
769 std::map<gate_t, int> kindex;
770 std::vector<gate_t> kgates;
774 auto parse_number = [](
const std::string &s,
double &out) ->
bool {
777 out = std::stod(s, &pos);
778 return pos == s.size();
784 std::function<bool(
gate_t)> collect = [&](
gate_t gx) ->
bool {
818 auto it = kindex.find(kg);
819 if (it == kindex.end()) {
820 idx =
static_cast<int>(kgates.size());
822 kgates.push_back(kg);
826 if (!parse_number(ms, m))
return false;
827 ai.contribs.emplace_back(idx, m);
829 aggs.emplace(gx, std::move(ai));
850 if (!collect(Lx) || !collect(Rx))
854 const size_t n = kgates.size();
860 std::function<bool(
gate_t, uint64_t,
double &,
bool &)> eval =
861 [&](
gate_t gx, uint64_t world,
double &out,
bool &is_int) ->
bool {
865 if (!parse_number(s, out))
return false;
866 is_int = text_is_int(s);
870 std::string ms;
gate_t kg{};
872 if (!parse_number(ms, out))
return false;
873 is_int = text_is_int(ms);
877 const AggInfo &ai = aggs.at(gx);
878 double acc = 0, mn = 0, mx = 0, fst = 0;
881 for (
const auto &pr : ai.contribs)
882 if (world & (uint64_t(1) << pr.first)) {
883 double m = pr.second;
885 if (first) { mn = mx = fst = m; first =
false; }
886 else { mn = std::min(mn, m); mx = std::max(mx, m); }
908 if (cnt == 0 && !ai.is_scalar)
return false;
909 out = acc;
return true;
920 "having_semantics: aggregate kind not read per world");
925 unsigned aop =
static_cast<unsigned>(c.
getInfos(gx).first);
931 if (!eval(ch, world, v, vi))
return false;
933 all_int = all_int && vi;
935 out = r; is_int = all_int;
return true;
938 if (w.size() != 2)
return false;
939 double a, b;
bool ai, bi;
940 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
941 out = a - b; is_int = ai && bi;
return true;
944 if (w.size() != 2)
return false;
945 double a, b;
bool ai, bi;
946 if (!eval(w[0], world, a, ai) || !eval(w[1], world, b, bi))
return false;
947 if (b == 0)
return false;
949 out = std::trunc(a / b);
968 if (w.size() != 1)
return false;
970 if (!eval(w[0], world, a, ai))
return false;
971 out = -a; is_int = ai;
return true;
979 if (w.size() != 1 || !eval(w[0], world, a, ai))
return false;
981 ? a :
static_cast<double>(
static_cast<float>(a));
991 if (w.empty() || !eval(w[0], world, a, ai))
return false;
995 else if (w.size() == 1) out = std::round(a);
999 if (!eval(w[1], world, d, di))
return false;
1000 const double f = std::pow(10.0, d);
1001 out = std::round(a * f) / f;
1027 if (w.empty() || !eval(w[0], world, a, ai))
return false;
1029 if (!(a > 0))
return false;
1037 if (w.size() != 2 || !eval(w[1], world, e, ei))
return false;
1038 out = std::pow(a, e);
1039 if (std::isnan(out))
return false;
1041 if (!std::isfinite(out))
return false;
1046 if (w.empty())
return false;
1047 double r = 0;
bool all_int =
true, first =
true;
1050 if (!eval(ch, world, v, vi))
return false;
1051 if (first) { r = v; first =
false; }
1054 all_int = all_int && vi;
1056 out = r; is_int = all_int;
return true;
1068 std::vector<double> members;
1069 double fraction, pos, fp;
1072 if (w.empty() || w.size() % 2 != 0)
return false;
1074 fraction = std::stod(c.
getExtra(gx));
1075 }
catch (
const std::exception &) {
1078 for (std::size_t i = 0; i < w.size(); i += 2) {
1082 if (!eval(w[i], world, ind, ii))
return false;
1083 if (ind < 0.5)
continue;
1084 if (!eval(w[i + 1], world, x, xi))
return false;
1085 members.push_back(x);
1087 if (members.empty())
return false;
1088 std::sort(members.begin(), members.end());
1089 pos = fraction *
static_cast<double>(members.size() - 1);
1090 lo =
static_cast<std::size_t
>(pos);
1091 fp = pos -
static_cast<double>(lo);
1092 out = (lo + 1 < members.size())
1093 ? members[lo] + fp * (members[lo + 1] - members[lo])
1108 "having_semantics: unknown gate_arith operator tag: " +
1109 std::to_string(aop));
1114 std::vector<typename SemiringT::value_type> kval(n);
1115 for (
size_t i = 0; i < n; ++i)
1116 kval[i] = c.
evaluate<SemiringT>(kgates[i], mapping, S);
1120 const bool certify = certifiable_contributors(kval);
1130 const bool empty_world_valid =
1132 std::all_of(aggs.begin(), aggs.end(),
1133 [](
const std::pair<const gate_t, AggInfo> &e) {
1134 return e.second.is_scalar;
1139 if (n == 0 && !empty_world_valid)
1142 std::vector<typename SemiringT::value_type> disjuncts;
1143 const uint64_t total = uint64_t(1) << n;
1144 for (uint64_t world = empty_world_valid ? 0 : 1; world < total; ++world) {
1147 if (!eval(Lx, world, lv, lint) || !eval(Rx, world, rv, rint))
1161 std::vector<typename SemiringT::value_type> present, missing;
1162 for (
size_t i = 0; i < n; ++i) {
1163 if (world & (uint64_t(1) << i)) {
1164 if (certify || kval[i] != S.one()) present.push_back(kval[i]);
1166 if (certify || kval[i] != S.zero()) missing.push_back(kval[i]);
1170 disjuncts.push_back(S.certified_world_term(present, missing));
1173 auto present_prod = S.times(present);
1174 if (missing.empty())
1175 disjuncts.push_back(std::move(present_prod));
1177 auto monus_factor = S.monus(S.one(), S.plus(missing));
1178 disjuncts.push_back(
1179 present_prod == S.one()
1181 : S.times(std::vector<typename SemiringT::value_type>{
1182 present_prod, monus_factor}));
1186 pw_out = disjuncts.empty() ? S.zero()
1187 : certify ? S.certified_exclusive_plus(disjuncts)
1188 : S.plus(disjuncts);
1200 std::map<gate_t, std::size_t> bit;
1201 std::vector<typename SemiringT::value_type> kvals;
1202 std::vector<std::size_t> bits[2];
1203 std::vector<std::string> vals[2];
1204 const gate_t sides[2] = {Lx, Rx};
1206 for (
int side = 0; side < 2; ++side) {
1216 m_str = array_null_element();
1217 auto it = bit.find(k_gate);
1218 if (it == bit.end()) {
1219 if (kvals.size() >= 20)
1221 it = bit.emplace(k_gate, kvals.size()).first;
1222 kvals.push_back(c.
evaluate<SemiringT>(k_gate, mapping, S));
1224 bits[side].push_back(it->second);
1225 vals[side].push_back(m_str);
1232 bits[0], vals[0], bits[1], vals[1], kvals.size(),
1234 pw_out = combine_exhaustive_worlds(worlds, kvals,
false,
1244 build_array_pair(L, R, op))
1247 return build_general(L, R, op);
1259 for (
gate_t cmp_gate : cmp_gates) {
1260 typename SemiringT::value_type pw;
1261 if (!pw_from_cmp_gate(cmp_gate, pw))
1264 mapping[cmp_gate] = std::move(pw);