ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
GenericCircuit.hpp
Go to the documentation of this file.
1/**
2 * @file GenericCircuit.hpp
3 * @brief Template implementation of @c GenericCircuit::evaluate().
4 *
5 * Provides the out-of-line definition of the @c evaluate() template method
6 * declared in @c GenericCircuit.h. This file must be included (directly
7 * or transitively) by any translation unit that instantiates
8 * @c GenericCircuit::evaluate<S>() for a specific semiring type @c S.
9 *
10 * The @c evaluate() method performs a post-order traversal of the sub-circuit
11 * rooted at gate @p g, looking up input-gate values from @p provenance_mapping
12 * and combining them using the semiring operations:
13 *
14 * | Gate type | Semiring operation |
15 * |-------------|-------------------------------|
16 * | gate_input | lookup in @p provenance_mapping|
17 * | gate_plus | @c semiring.plus(children) |
18 * | gate_times | @c semiring.times(children) |
19 * | gate_monus | @c semiring.monus(left, right) |
20 * | gate_delta | @c semiring.delta(child) |
21 * | gate_cmp | @c semiring.cmp(left, op, right)|
22 * | gate_semimod| @c semiring.semimod(x, s) |
23 * | gate_agg | @c semiring.agg(op, children) |
24 * | gate_value | @c semiring.value(string) |
25 * | gate_one | @c semiring.one() |
26 * | gate_zero | @c semiring.zero() |
27 */
28#include "GenericCircuit.h"
29
30extern "C" {
31#include "utils/lsyscache.h"
32}
33
34template<typename S, std::enable_if_t<std::is_base_of_v<semiring::Semiring<typename S::value_type>, S>, int> >
35typename S::value_type GenericCircuit::evaluate(gate_t g, std::unordered_map<gate_t, typename S::value_type> &provenance_mapping, S semiring) const
36{
37 const auto it = provenance_mapping.find(g);
38 if(it != provenance_mapping.end())
39 return it->second;
40
41 auto t = getGateType(g);
42
43 switch(t) {
44 case gate_one:
45 case gate_input:
46 case gate_update:
47 case gate_mulinput:
48 // If not in provenance mapping, return no provenance (one of the semiring)
49 return semiring.one();
50
51 case gate_zero:
52 return semiring.zero();
53
54 case gate_plus:
55 case gate_times:
56 case gate_monus: {
57 auto children = getWires(g);
58 std::vector<typename S::value_type> childrenResult;
59 std::transform(children.begin(), children.end(), std::back_inserter(childrenResult), [&](auto u) {
60 return evaluate<S>(u, provenance_mapping, semiring);
61 });
62 if(t==gate_plus) {
63 childrenResult.erase(std::remove(std::begin(childrenResult), std::end(childrenResult), semiring.zero()),
64 childrenResult.end());
65 return semiring.plus(childrenResult);
66 } else if(t==gate_times) {
67 for(const auto &c: childrenResult) {
68 if(c==semiring.zero())
69 return semiring.zero();
70 }
71 childrenResult.erase(std::remove(std::begin(childrenResult), std::end(childrenResult), semiring.one()),
72 childrenResult.end());
73 return semiring.times(childrenResult);
74 } else {
75 if(childrenResult[0]==semiring.zero() || childrenResult[0]==childrenResult[1])
76 return semiring.zero();
77 else
78 return semiring.monus(childrenResult[0], childrenResult[1]);
79 }
80 }
81
82 case gate_delta:
83 return semiring.delta(evaluate<S>(getWires(g)[0], provenance_mapping, semiring));
84
85 case gate_project:
86 case gate_eq:
87 // Where-provenance gates, ignored
88 return evaluate<S>(getWires(g)[0], provenance_mapping, semiring);
89
90 case gate_cmp:
91 {
92 auto infos = getInfos(g);
93 char * opname = get_opname(infos.first);
94 if(opname == nullptr)
95 provsql_error("Invalid OID for operator: %d", infos.first);
96
97 std::string func_name {opname};
98
100
101 if(func_name == "=") {
103 } else if(func_name == "<=") {
105 } else if(func_name == "<") {
107 } else if(func_name == ">") {
109 } else if(func_name == ">=") {
111 } else if(func_name == "<>") {
113 } else {
114 throw CircuitException("Comparison operator " + func_name + " not supported");
115 }
116
117 return semiring.cmp(evaluate<S>(getWires(g)[0], provenance_mapping, semiring), op, evaluate<S>(getWires(g)[1], provenance_mapping, semiring));
118 }
119
120 case gate_semimod:
121 return semiring.semimod(evaluate<S>(getWires(g)[0], provenance_mapping, semiring), evaluate<S>(getWires(g)[1], provenance_mapping, semiring));
122
123 case gate_agg:
124 {
125 auto infos = getInfos(g);
126
128
129 std::vector<typename S::value_type> vec;
130 for(auto it = getWires(g).begin(); it!=getWires(g).end(); ++it)
131 vec.push_back(evaluate<S>(*it, provenance_mapping, semiring));
132 return semiring.agg(op, vec);
133 break;
134 }
135
136 case gate_value:
137 return semiring.value(getExtra(g));
138
139 default:
140 throw CircuitException("Invalid gate type for semiring evaluation");
141 }
142}
AggregationOperator getAggregationOperator(Oid oid)
Map a PostgreSQL aggregate function OID to an AggregationOperator.
AggregationOperator
SQL aggregation functions tracked by ProvSQL.
Definition Aggregation.h:50
ComparisonOperator
SQL comparison operators used in gate_cmp circuit gates.
Definition Aggregation.h:38
@ LT
Less than (<)
@ GT
Greater than (>)
@ LE
Less than or equal (<=)
@ NE
Not equal (<>)
@ GE
Greater than or equal (>=)
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:48
Semiring-agnostic in-memory provenance circuit.
Exception type thrown by circuit operations on invalid input.
Definition Circuit.h:205
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:139
gate_type getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:129
std::map< gate_t, std::pair< unsigned, unsigned > > infos
Per-gate (info1, info2) annotations.
S::value_type evaluate(gate_t g, std::unordered_map< gate_t, typename S::value_type > &provenance_mapping, S semiring) const
Evaluate the sub-circuit rooted at gate g over semiring semiring.
std::string getExtra(gate_t g) const
Return the string extra for gate g.
std::pair< unsigned, unsigned > getInfos(gate_t g) const
Return the integer annotation pair for gate g.
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
@ gate_update
Update operation.
@ gate_monus
M-Semiring monus.
@ gate_eq
Equijoin gate (for where provenance)
@ gate_value
Scalar value (for aggregate provenance)
@ gate_delta
δ-semiring operator (see Amsterdamer, Deutch, Tannen, PODS 2011)
@ gate_mulinput
Multivalued input (for Boolean provenance)
@ gate_one
Semiring one.
@ gate_zero
Semiring zero.
@ gate_agg
Aggregation operator (for aggregate provenance)
@ gate_project
Project gate (for where provenance)
@ gate_times
Semiring times.
@ gate_cmp
Currently unused, meant for comparison of aggregate values.
@ gate_plus
Semiring plus.
@ gate_semimod
Semimodule scalar multiplication (for aggregate provenance)
@ gate_input
Input (variable) gate of the circuit.