33static bool increment(
mask_t &v)
35 for(
size_t i=0; i<v.size(); ++i)
44static std::vector<mask_t> all_worlds(
const std::vector<long> &values)
46 std::vector<mask_t> worlds;
47 mask_t mask(values.size());
49 while(increment(mask))
50 worlds.push_back(mask);
54static void append_range(std::vector<mask_t> &out,
55 const std::vector<std::vector<mask_t> > &dp,
59 if (dp.empty())
return;
60 const long long J =
static_cast<long long>(dp.size())-1;
61 lo = std::max(lo, 0LL);
65 for (
long long j = lo; j <= hi; ++j) {
66 out.insert(out.end(), dp[j].begin(), dp[j].end());
70class DPException :
public std::exception {};
73#define MIN(x,y) ((x)<(y)?(x):(y))
75static std::vector<mask_t> sum_dp(
const std::vector<long> &values,
long C,
ComparisonOperator op,
bool absorptive,
bool &upset,
bool keep_empty=
false)
77 const std::size_t n = values.size();
79 std::vector<mask_t> R;
85 R.reserve(lt.size()+gt.size());
86 R.insert(R.end(),lt.begin(),lt.end());
87 R.insert(R.end(),gt.begin(),gt.end());
92 for (
long w: values) {
125 static const long long SUM_DP_MAX_J = 10000000LL;
126 if (J > SUM_DP_MAX_J)
129 std::vector<std::vector<mask_t> > dp(
static_cast<std::size_t
>(J) + 1);
130 dp[0].push_back(
mask_t(n));
132 long long pref_sum=0;
134 for (std::size_t i=0; i<n; ++i)
136 const long w=values[i];
138 const long long j_max=
MIN(J,pref_sum);
140 for (
long long j = j_max; j >= w; --j) {
141 const long long p = j - w;
147 size_t s=dp[p].size();
148 for(
size_t k=0; k<s; ++k) {
158 append_range(R,dp,C,C);
162 append_range(R,dp,C+1,J);
167 append_range(R,dp,0,C-1);
171 append_range(R,dp,C,J);
175 append_range(R,dp,0,C);
191 R.erase(std::remove_if(R.begin(), R.end(),
193 for(size_t i=0; i<m.size(); ++i) if(m[i]) return false;
205 bool zero_sat =
false;
222static void combinations(std::size_t start,
225 std::vector<mask_t> &out)
227 const size_t n = mask.size();
234 if (start >= n)
return;
236 const std::size_t remaining = n - start;
237 if (remaining <
static_cast<std::size_t
>(k_left))
return;
239 combinations(start + 1, k_left, mask, out);
242 combinations(start + 1, k_left - 1, mask, out);
245static std::vector<mask_t> count_enum(
const std::vector<long> &values,
long m,
ComparisonOperator op,
bool absorptive,
bool &upset,
bool is_scalar)
247 const int n =
static_cast<int>(values.size());
248 std::vector<mask_t> out;
250 auto add_exact_k = [&](
long k) {
251 if (k < 0 || k > n)
return;
252 combinations(0,
static_cast<int>(k),
mask_t(n), out);
264 const long lo = is_scalar ? 0 : 1;
269 if (m >= lo) add_exact_k(m);
277 const long mink = std::max(m, lo);
282 for (
long k = mink; k <= n; ++k) add_exact_k(k);
292 for (
long k = lo; k <= m; ++k) add_exact_k(k);
298 for (
long k = lo; k <= n; ++k)
299 if (k != m) add_exact_k(k);
317template<
typename I,
typename J>
340 const std::vector<bool>& mask,
342 std::unique_ptr<Aggregator> aggregator)
344 for (std::size_t i = 0; i < values.size(); ++i) {
345 if (mask[i]) aggregator->add(
AggValue {values[i]});
347 auto res = aggregator->finalize();
348 switch(aggregator->resultType()) {
350 return compare(std::get<long>(res.v), op, constant);
352 return compare(std::get<bool>(res.v), op, constant);
354 return compare(std::get<double>(res.v), op, constant);
356 throw std::runtime_error(
"Cannot compare this kind of value");
361 const std::vector<long> &values,
371 for (
bool b : present)
372 if (b) { any =
true;
break; }
376 return evaluate(values, present, constant, op,
391 const std::vector<long> &values,
398 const size_t n = values.size();
400 std::vector<mask_t> worlds;
403 bool all_worlds =
true;
405 while(increment(mask)) {
407 worlds.push_back(mask);
412 if(all_worlds && absorptive)
418 combinations(0, 1,
mask_t(n), worlds);
426 const std::vector<long> &values,
444 for (
long v : values)
if (v != 1) { all_one =
false;
break; }
446 return count_enum(values,constant,op, absorptive, upset, is_scalar);
448 return sum_dp(values, constant, op, absorptive, upset, is_scalar);
449 }
catch(DPException &e) {
457 return sum_dp(values, constant, op, absorptive, upset);
458 }
catch(DPException &e) {
466 const std::vector<std::string> &vals,
467 const std::vector<std::string> &target,
470 const size_t n = vals.size();
471 std::vector<mask_t> worlds;
476 while(increment(mask)) {
477 std::vector<std::string> present;
479 for(
size_t i = 0; i < n; ++i)
480 if(mask[i]) present.push_back(vals[i]);
481 if((present == target) == want_equal)
482 worlds.push_back(mask);
std::unique_ptr< Aggregator > makeAggregator(AggregationOperator op, ValueType t)
Create a concrete Aggregator for the given operator and value type.
AggregationOperator
SQL aggregation functions tracked by ProvSQL.
@ COUNT
COUNT(*) or COUNT(expr) → integer.
@ SUM
SUM → integer or float.
ComparisonOperator
SQL comparison operators used in gate_cmp circuit gates.
@ LE
Less than or equal (<=).
@ GE
Greater than or equal (>=).
@ INT
Signed 64-bit integer.
@ FLOAT
Double-precision float.
A dynamically-typed aggregate value.
bool evaluate(const std::vector< long > &values, const std::vector< bool > &mask, long constant, ComparisonOperator op, std::unique_ptr< Aggregator > aggregator)
Evaluate whether the aggregation of values masked by mask satisfies op constant.
std::vector< mask_t > enumerate_valid_worlds(const std::vector< long > &values, long constant, ComparisonOperator op, AggregationOperator agg_kind, bool absorptive, bool &upset, bool is_scalar)
Enumerate all subsets of n tuples satisfying an aggregate predicate.
#define MIN(x, y)
Return the minimum of two values.
static bool compare(I a, ComparisonOperator op, J b)
Apply a comparison operator to two values.
bool agg_cmp_holds_in_world(const std::vector< long > &values, const mask_t &present, long constant, ComparisonOperator op, AggregationOperator agg_kind)
Canonical per-world decision: does agg(present) op constant hold in the world where exactly the prese...
std::vector< mask_t > enumerate_exhaustive(const std::vector< long > &values, long constant, ComparisonOperator op, AggregationOperator agg_kind, bool absorptive, bool &upset)
Enumerate all subsets satisfying a HAVING predicate by exhaustive search.
std::vector< mask_t > enumerate_array_agg_worlds(const std::vector< std::string > &vals, const std::vector< std::string > &target, bool want_equal)
Enumerate the non-empty worlds whose ordered present elements equal (want_equal true) or differ from ...
Enumerate tuple subsets satisfying an aggregate HAVING predicate.
std::vector< bool > mask_t
A bitmask over tuples representing one possible world.