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