20 if (cw.size() != 2)
return false;
24 if (!okop)
return false;
30 gate_t agg_side, const_side;
31 std::vector<gate_t> via;
32 std::vector<std::pair<int, std::string>> offsets;
37 const unsigned aop =
static_cast<unsigned>(gc.
getInfos(g).first);
43 if (non_const != 1)
return g;
45 if (ch != inner) offsets.emplace_back(sign, gc.
getExtra(ch));
49 offsets.emplace_back(-sign, gc.
getExtra(w[1]));
52 offsets.emplace_back(sign, gc.
getExtra(w[0]));
72 agg_side = peel(cw[0]);
75 via.clear(); offsets.clear(); sign = 1;
76 agg_side = peel(cw[1]);
90 const unsigned aggtype =
97 long c_mant = 0;
int c_scale = 0;
104 const auto &agg_children = gc.
getWires(agg_side);
105 if (agg_children.empty() &&
109 std::vector<gate_t> semimods, ks;
110 std::vector<long> m_mant;
111 std::vector<int> m_scale;
112 semimods.reserve(agg_children.size());
113 ks.reserve(agg_children.size());
114 m_mant.reserve(agg_children.size());
115 m_scale.reserve(agg_children.size());
117 for (
gate_t ch : agg_children) {
123 long mm = 0;
int sc = 0;
126 semimods.push_back(ch);
127 ks.push_back(k_gate);
128 m_mant.push_back(mm);
129 m_scale.push_back(sc);
138 std::vector<long> d_mant(offsets.size());
139 std::vector<int> d_scale(offsets.size());
140 for (std::size_t i = 0; i < offsets.size(); ++i)
142 d_mant[i], d_scale[i]))
147 int target = c_scale;
148 for (
int s : m_scale) target = std::max(target, s);
149 for (
int s : d_scale) target = std::max(target, s);
152 std::vector<long> ms(m_mant.size());
153 for (std::size_t i = 0; i < m_mant.size(); ++i)
159 for (std::size_t i = 0; i < offsets.size(); ++i) {
163 d += offsets[i].first * v;
172 out.
via = std::move(via);
175 out.
ks = std::move(ks);
176 out.
ms = std::move(ms);
185 if (ref[
static_cast<std::size_t
>(match.
agg)] != 1)
188 if (ref[
static_cast<std::size_t
>(g)] != 1)
196 std::vector<unsigned> ref(nb, 0);
197 for (std::size_t i = 0; i < nb; ++i) {
198 auto g =
static_cast<gate_t>(i);
200 const auto idx =
static_cast<std::size_t
>(w);
201 if (idx < ref.size()) ++ref[idx];
208 const std::vector<unsigned> &ref,
bool &ok)
214 if (ref[
static_cast<std::size_t
>(g)] != 1) { ok =
false;
return 0.0; }
217 if (ref[
static_cast<std::size_t
>(g)] != 1) { ok =
false;
return 0.0; }
226 if (ref[
static_cast<std::size_t
>(g)] != 1) { ok =
false;
return 0.0; }
238 if (ref[
static_cast<std::size_t
>(g)] != 1) { ok =
false;
return 0.0; }
240 if (w.size() != 2) { ok =
false;
return 0.0; }
245 return pa * (1.0 - pb);
AggregationOperator getAggregationOperator(Oid oid)
Map a PostgreSQL aggregate function OID to an AggregationOperator.
AggregationOperator
SQL aggregation functions tracked by ProvSQL.
ComparisonOperator
SQL comparison operators used in gate_cmp circuit gates.
gate_t
Strongly-typed gate identifier.
Shared machinery for the closed-form HAVING gate_cmp probability evaluators (Poisson-binomial COUNT,...
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
gateType getGateType(gate_t g) const
Return the type of gate g.
std::vector< gate_t >::size_type getNbGates() const
Return the total number of gates in the circuit.
In-memory provenance circuit with semiring-generic evaluation.
std::string getExtra(gate_t g) const
Return the string extra for gate g.
double getProb(gate_t g) const
Return the probability for gate g.
std::pair< unsigned, unsigned > getInfos(gate_t g) const
Return the integer annotation pair for gate g.
Provenance evaluation helper for HAVING-clause circuits.
bool rescale_to(long mantissa, int scale, int target_scale, long &out)
bool aggtype_is_text(unsigned oid)
ComparisonOperator flip_op(ComparisonOperator op)
bool parse_decimal_scaled(const std::string &s, long &mantissa, int &scale)
ComparisonOperator map_cmp_op(GenericCircuit &c, gate_t cmp_gate, bool &ok)
bool semimod_extract_string_and_K(GenericCircuit &c, gate_t semimod_gate, std::string &m_out, gate_t &k_gate_out)
bool extract_constant_string(GenericCircuit &c, gate_t x, std::string &C_out)
bool aggPrivateToCmp(const AggCmpMatch &match, const std::vector< unsigned > &ref)
Whether the aggregate of match is consumed by its comparison alone: agg and every gate of via has ref...
std::vector< unsigned > computeRefCounts(const GenericCircuit &gc)
Reference count of every gate as a wire-target across the whole circuit.
bool matchAggCmp(GenericCircuit &gc, gate_t cmp, AggCmpMatch &out)
Try to match cmp against gate_cmp(gate_agg(α, semimod_i(K_i, m_i)*), gate_value(C)).
double contributorProb(const GenericCircuit &gc, gate_t g, const std::vector< unsigned > &ref, bool &ok)
Read-once marginal probability of a count/aggregate contributor (the K side of a semimod).
Core types, constants, and utilities shared across ProvSQL.
@ PROVSQL_ARITH_ASFLOAT8
unary, child0 as double precision
@ PROVSQL_ARITH_PLUS
n-ary, sum of children
@ PROVSQL_ARITH_NEG
unary, -child0
@ PROVSQL_ARITH_MINUS
binary, child0 - child1
@ PROVSQL_ARITH_ASFLOAT4
unary, child0 as real reads it
#define PROVSQL_AGG_TYPE_MASK
@ gate_arith
n-ary arithmetic gate over scalar-valued children (info1 holds operator tag)
#define PROVSQL_AGG_SCALAR_FLAG
Scalar-aggregation flag, stored in the upper bit of a gate_agg's info2 (whose low 31 bits hold the ag...
Result of matching a gate_cmp against the canonical HAVING aggregate-comparison shape.
gate_t agg
the gate_agg operand of the cmp
long C
the constant threshold, on the same integer grid as ms
std::vector< gate_t > ks
the K side of each semimod (contributor root)
std::vector< gate_t > semimods
the per-child gate_semimod parents
std::vector< gate_t > via
the gate_arith gates of constant arithmetic between the cmp and agg, folded into op and C
std::vector< long > ms
the M side of each semimod (per-row value), scaled to a common integer grid (numeric / decimal-float ...
AggregationOperator agg_kind
effective aggregate (SUM-of-1s remapped to COUNT)
ComparisonOperator op
comparator, flipped if the agg sits on the right