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 int J =
static_cast<int>(dp.size())-1;
65 for (
int 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,
int C,
ComparisonOperator op,
bool absorptive,
bool &upset)
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());
121 std::vector<std::vector<mask_t> > dp(
static_cast<std::size_t
>(J) + 1);
122 dp[0].push_back(
mask_t(n));
126 for (std::size_t i=0; i<n; ++i)
128 const int w=values[i];
130 const int j_max=
MIN(J,pref_sum);
132 for (
int j = j_max; j >= w; --j) {
139 size_t s=dp[p].size();
140 for(
size_t k=0; k<s; ++k) {
150 append_range(R,dp,C,C);
154 append_range(R,dp,C+1,J);
159 append_range(R,dp,1,C-1);
163 append_range(R,dp,C,J);
167 append_range(R,dp,1,C);
178static void combinations(std::size_t start,
181 std::vector<mask_t> &out)
183 const size_t n = mask.size();
190 if (start >= n)
return;
192 const std::size_t remaining = n - start;
193 if (remaining <
static_cast<std::size_t
>(k_left))
return;
195 combinations(start + 1, k_left, mask, out);
198 combinations(start + 1, k_left - 1, mask, out);
201static std::vector<mask_t> count_enum(
const std::vector<long> &values,
int m,
ComparisonOperator op,
bool absorptive,
bool &upset)
203 const int n =
static_cast<int>(values.size());
204 std::vector<mask_t> out;
206 auto add_exact_k = [&](
int k) {
207 if (k < 0 || k > n)
return;
208 combinations(0, k,
mask_t(n), out);
214 if(m!=0) add_exact_k(m);
225 for (
int k = m; k <= n; ++k) add_exact_k(k);
232 for (
int k = 1; k <= m; ++k) add_exact_k(k);
236 for (
int k = 1; k <= n; ++k)
238 if (k != m) add_exact_k(k);
257template<
typename I,
typename J>
280 const std::vector<bool>& mask,
282 std::unique_ptr<Aggregator> aggregator)
284 for (std::size_t i = 0; i < values.size(); ++i) {
285 if (mask[i]) aggregator->add(
AggValue {values[i]});
287 auto res = aggregator->finalize();
288 switch(aggregator->resultType()) {
290 return compare(std::get<long>(res.v), op, constant);
292 return compare(std::get<bool>(res.v), op, constant);
294 return compare(std::get<double>(res.v), op, constant);
296 throw std::runtime_error(
"Cannot compare this kind of value");
311 const std::vector<long> &values,
318 const size_t n = values.size();
320 std::vector<mask_t> worlds;
323 bool all_worlds =
true;
325 while(increment(mask)) {
328 if(
evaluate(values, mask, constant, op, std::move(aggregator)))
329 worlds.push_back(mask);
334 if(all_worlds && absorptive)
340 combinations(0, 1,
mask_t(n), worlds);
348 const std::vector<long> &values,
357 return count_enum(values,constant,op, absorptive, upset);
361 return sum_dp(values, constant, op, absorptive, upset);
362 }
catch(DPException &e) {
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, int 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_exhaustive(const std::vector< long > &values, int constant, ComparisonOperator op, AggregationOperator agg_kind, bool absorptive, bool &upset)
Enumerate all subsets satisfying a HAVING predicate by exhaustive search.
#define MIN(x, y)
Return the minimum of two values.
std::vector< mask_t > enumerate_valid_worlds(const std::vector< long > &values, int constant, ComparisonOperator op, AggregationOperator agg_kind, bool absorptive, bool &upset)
Enumerate all subsets of n tuples satisfying an aggregate predicate.
static bool compare(I a, ComparisonOperator op, J b)
Apply a comparison operator to two values.
Enumerate tuple subsets satisfying an aggregate HAVING predicate.
std::vector< bool > mask_t
A bitmask over tuples representing one possible world.