ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
Circuit.h
Go to the documentation of this file.
1/**
2 * @file Circuit.h
3 * @brief Generic directed-acyclic-graph circuit template and gate identifier.
4 *
5 * This header provides two central abstractions:
6 *
7 * ### @c gate_t
8 * A strongly-typed wrapper around @c size_t used as a compact gate
9 * identifier within a circuit. Using a distinct type prevents accidental
10 * mixing of gate IDs with plain integers. Helper operators (increment,
11 * comparison, stream I/O, @c to_string) make it convenient to use in
12 * loops and containers.
13 *
14 * ### @c Circuit<gateType>
15 * A CRTP-style template base class for all circuit variants in ProvSQL
16 * (@c BooleanCircuit, @c GenericCircuit, @c DotCircuit, @c WhereCircuit).
17 * A circuit is a directed acyclic graph where:
18 * - Each **gate** has a type drawn from @c gateType (a user-supplied enum).
19 * - **Wires** are directed edges from parent gates to their children.
20 * - Each gate may optionally be associated with a UUID string, enabling
21 * round-tripping between the in-memory circuit and the persistent mmap
22 * representation.
23 *
24 * @c Circuit.hpp (included by subclass headers) provides the out-of-line
25 * template method implementations.
26 *
27 * ### @c CircuitException
28 * Exception type thrown when a circuit operation fails (e.g. UUID not
29 * found, type mismatch).
30 */
31#ifndef CIRCUIT_H
32#define CIRCUIT_H
33
34#include <unordered_map>
35#include <unordered_set>
36#include <iostream>
37#include <set>
38#include <vector>
39#include <type_traits>
40
41/**
42 * @brief Strongly-typed gate identifier.
43 *
44 * Wraps a @c size_t so that gate IDs are not accidentally used as plain
45 * integers. The underlying value is a zero-based index into the circuit's
46 * gate and wire vectors.
47 */
48enum class gate_t : size_t {};
49
50/**
51 * @brief Generic template base class for provenance circuits.
52 *
53 * A @c Circuit stores:
54 * - A vector of gate types indexed by @c gate_t.
55 * - A vector of child-wire lists (also indexed by @c gate_t).
56 * - Bidirectional maps between gate UUIDs (strings) and @c gate_t IDs.
57 *
58 * @tparam gateType Enumeration of gate kinds for this circuit variant.
59 */
60template<class gateType>
61class Circuit {
62public:
63/** @brief UUID type used in this circuit (always @c std::string). */
64using uuid = std::string;
65
66protected:
67std::unordered_map<uuid, gate_t> uuid2id; ///< UUID string → gate index
68std::unordered_map<gate_t, uuid> id2uuid; ///< Gate index → UUID string
69
70std::vector<gateType> gates; ///< Gate type for each gate
71std::vector<std::vector<gate_t> > wires; ///< Child wire lists for each gate
72
73/**
74 * @brief Update the type of an existing gate.
75 * @param g Gate to update.
76 * @param t New gate type.
77 */
78void setGateType(gate_t g, gateType t)
79{
80 gates[static_cast<std::underlying_type<gate_t>::type>(g)]=t;
81}
82
83protected:
84/**
85 * @brief Allocate a new gate with a default-initialised type.
86 *
87 * Derived classes override this to perform additional initialisation
88 * (e.g. resizing auxiliary vectors).
89 *
90 * @return The @c gate_t identifier of the newly created gate.
91 */
92virtual gate_t addGate();
93
94public:
95virtual ~Circuit() {
96}
97
98/**
99 * @brief Return the total number of gates in the circuit.
100 * @return Number of gates.
101 */
102std::vector<gate_t>::size_type getNbGates() const {
103 return gates.size();
104}
105
106/**
107 * @brief Return (or create) the gate associated with UUID @p u.
108 *
109 * If no gate with this UUID exists yet a new gate is allocated via
110 * @c addGate() and the UUID mapping is recorded.
111 *
112 * @param u UUID string.
113 * @return Gate identifier for @p u.
114 */
115gate_t getGate(const uuid &u);
116
117/**
118 * @brief Return the UUID string associated with gate @p g.
119 * @param g Gate identifier.
120 * @return UUID string, or empty if @p g has no UUID.
121 */
122uuid getUUID(gate_t g) const;
123
124/**
125 * @brief Return the type of gate @p g.
126 * @param g Gate identifier.
127 * @return The gate's type.
128 */
129gateType getGateType(gate_t g) const
130{
131 return gates[static_cast<std::underlying_type<gate_t>::type>(g)];
132}
133
134/**
135 * @brief Return a mutable reference to the child-wire list of gate @p g.
136 * @param g Gate identifier.
137 * @return Reference to the vector of child gate IDs.
138 */
139std::vector<gate_t> &getWires(gate_t g)
140{
141 return wires[static_cast<std::underlying_type<gate_t>::type>(g)];
142}
143
144/**
145 * @brief Return a const reference to the child-wire list of gate @p g.
146 * @param g Gate identifier.
147 * @return Const reference to the vector of child gate IDs.
148 */
149const std::vector<gate_t> &getWires(gate_t g) const
150{
151 return wires[static_cast<std::underlying_type<gate_t>::type>(g)];
152}
153
154/**
155 * @brief Create or update the gate associated with UUID @p u.
156 *
157 * If the UUID is already mapped the existing gate's type is updated.
158 * Otherwise a new gate is allocated.
159 *
160 * @param u UUID string to associate with the gate.
161 * @param type Gate type.
162 * @return Gate identifier.
163 */
164virtual gate_t setGate(const uuid &u, gateType type);
165
166/**
167 * @brief Allocate a new gate with type @p type and no UUID.
168 * @param type Gate type.
169 * @return Gate identifier.
170 */
171virtual gate_t setGate(gateType type);
172
173/**
174 * @brief Test whether a gate with UUID @p u exists.
175 * @param u UUID string.
176 * @return @c true if a gate with this UUID is present.
177 */
178bool hasGate(const uuid &u) const;
179
180/**
181 * @brief Add a directed wire from gate @p f (parent) to gate @p t (child).
182 * @param f Source (parent) gate.
183 * @param t Target (child) gate.
184 */
185void addWire(gate_t f, gate_t t);
186
187/**
188 * @brief Return a textual description of gate @p g for debugging.
189 *
190 * Pure virtual; each concrete circuit class provides its own formatting.
191 *
192 * @param g Gate to describe.
193 * @return Human-readable string.
194 */
195virtual std::string toString(gate_t g) const = 0;
196};
197
198/**
199 * @brief Exception type thrown by circuit operations on invalid input.
200 *
201 * Thrown when, for example, a UUID is not found in the circuit or a
202 * type constraint is violated.
203 */
204class CircuitException : public std::exception
205{
206std::string message; ///< Human-readable description of the error
207
208public:
209/**
210 * @brief Construct with a descriptive error message.
211 * @param m Error message string.
212 */
213CircuitException(const std::string &m) : message(m) {
214}
215/**
216 * @brief Return the error message as a C-string.
217 * @return Null-terminated error description.
218 */
219virtual char const * what() const noexcept {
220 return message.c_str();
221}
222};
223
224/**
225 * @brief Pre-increment operator for @c gate_t.
226 * @param g Gate to increment.
227 * @return Reference to the incremented gate.
228 */
230 return g=gate_t{static_cast<std::underlying_type<gate_t>::type>(g)+1};
231}
232
233/**
234 * @brief Compare a @c gate_t against a @c std::vector size type.
235 * @param t Gate identifier.
236 * @param u Vector size to compare against.
237 * @return @c true if the underlying integer of @p t is less than @p u.
238 */
239inline bool operator<(gate_t t, std::vector<gate_t>::size_type u)
240{
241 return static_cast<std::underlying_type<gate_t>::type>(t)<u;
242}
243
244/**
245 * @brief Convert a @c gate_t to its decimal string representation.
246 * @param g Gate identifier.
247 * @return Decimal string of the underlying integer.
248 */
249inline std::string to_string(gate_t g) {
250 return std::to_string(static_cast<std::underlying_type<gate_t>::type>(g));
251}
252
253/**
254 * @brief Read a @c gate_t from an input stream.
255 * @param i Input stream.
256 * @param g Gate to populate.
257 * @return Reference to @p i.
258 */
259inline std::istream &operator>>(std::istream &i, gate_t &g)
260{
261 std::underlying_type<gate_t>::type u;
262 i >> u;
263 g=gate_t{u};
264 return i;
265}
266
267/**
268 * @brief Write a @c gate_t to an output stream as its decimal value.
269 * @param o Output stream.
270 * @param g Gate identifier to write.
271 * @return Reference to @p o.
272 */
273inline std::ostream &operator<<(std::ostream &o, gate_t g)
274{
275 return o << static_cast<std::underlying_type<gate_t>::type>(g);
276}
277
278#endif /* CIRCUIT_H */
std::istream & operator>>(std::istream &i, gate_t &g)
Read a gate_t from an input stream.
Definition Circuit.h:259
gate_t & operator++(gate_t &g)
Pre-increment operator for gate_t.
Definition Circuit.h:229
std::ostream & operator<<(std::ostream &o, gate_t g)
Write a gate_t to an output stream as its decimal value.
Definition Circuit.h:273
bool operator<(gate_t t, std::vector< gate_t >::size_type u)
Compare a gate_t against a std::vector size type.
Definition Circuit.h:239
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:48
std::string to_string(gate_t g)
Convert a gate_t to its decimal string representation.
Definition Circuit.h:249
Exception type thrown by circuit operations on invalid input.
Definition Circuit.h:205
std::string message
Human-readable description of the error.
Definition Circuit.h:206
virtual char const * what() const noexcept
Return the error message as a C-string.
Definition Circuit.h:219
CircuitException(const std::string &m)
Construct with a descriptive error message.
Definition Circuit.h:213
Generic template base class for provenance circuits.
Definition Circuit.h:61
std::string uuid
UUID type used in this circuit (always std::string).
Definition Circuit.h:64
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:139
gateType getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:129
std::unordered_map< gate_t, uuid > id2uuid
Gate index → UUID string.
Definition Circuit.h:68
const std::vector< gate_t > & getWires(gate_t g) const
Return a const reference to the child-wire list of gate g.
Definition Circuit.h:149
virtual gate_t setGate(const uuid &u, gateType type)
Create or update the gate associated with UUID u.
Definition Circuit.hpp:73
virtual std::string toString(gate_t g) const =0
Return a textual description of gate g for debugging.
void addWire(gate_t f, gate_t t)
Add a directed wire from gate f (parent) to gate t (child).
Definition Circuit.hpp:81
std::unordered_map< uuid, gate_t > uuid2id
UUID string → gate index.
Definition Circuit.h:67
void setGateType(gate_t g, gateType t)
Update the type of an existing gate.
Definition Circuit.h:78
std::vector< gateType > gates
Gate type for each gate.
Definition Circuit.h:70
virtual ~Circuit()
Definition Circuit.h:95
uuid getUUID(gate_t g) const
Return the UUID string associated with gate g.
Definition Circuit.hpp:46
std::vector< std::vector< gate_t > > wires
Child wire lists for each gate.
Definition Circuit.h:71
gate_t getGate(const uuid &u)
Return (or create) the gate associated with UUID u.
Definition Circuit.hpp:33
bool hasGate(const uuid &u) const
Test whether a gate with UUID u exists.
Definition Circuit.hpp:27
std::vector< gate_t >::size_type getNbGates() const
Return the total number of gates in the circuit.
Definition Circuit.h:102
virtual gate_t addGate()
Allocate a new gate with a default-initialised type.
Definition Circuit.hpp:56