mqt-core 3.0.1__cp39-cp39-win_amd64.whl → 3.1.0__cp39-cp39-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mqt/core/__init__.py +5 -5
- mqt/core/_version.py +2 -2
- mqt/core/bin/mqt-core-algorithms.dll +0 -0
- mqt/core/bin/mqt-core-circuit-optimizer.dll +0 -0
- mqt/core/bin/mqt-core-dd.dll +0 -0
- mqt/core/bin/mqt-core-ds.dll +0 -0
- mqt/core/bin/mqt-core-ir.dll +0 -0
- mqt/core/bin/mqt-core-na.dll +0 -0
- mqt/core/bin/mqt-core-qasm.dll +0 -0
- mqt/core/bin/mqt-core-zx.dll +0 -0
- mqt/core/dd.cp39-win_amd64.pyd +0 -0
- mqt/core/include/mqt-core/dd/Approximation.hpp +45 -0
- mqt/core/include/mqt-core/dd/Complex.hpp +6 -0
- mqt/core/include/mqt-core/dd/ComplexNumbers.hpp +0 -18
- mqt/core/include/mqt-core/dd/ComputeTable.hpp +4 -1
- mqt/core/include/mqt-core/dd/DDDefinitions.hpp +0 -7
- mqt/core/include/mqt-core/dd/Edge.hpp +16 -0
- mqt/core/include/mqt-core/dd/Export.hpp +1 -2
- mqt/core/include/mqt-core/dd/Node.hpp +26 -49
- mqt/core/include/mqt-core/dd/Operations.hpp +27 -0
- mqt/core/include/mqt-core/dd/Package.hpp +138 -120
- mqt/core/include/mqt-core/dd/RealNumber.hpp +49 -66
- mqt/core/include/mqt-core/dd/RealNumberUniqueTable.hpp +14 -25
- mqt/core/include/mqt-core/dd/StateGeneration.hpp +143 -0
- mqt/core/include/mqt-core/dd/UnaryComputeTable.hpp +6 -4
- mqt/core/include/mqt-core/dd/UniqueTable.hpp +13 -39
- mqt/core/include/mqt-core/dd/statistics/PackageStatistics.hpp +8 -7
- mqt/core/include/mqt-core/dd/statistics/UniqueTableStatistics.hpp +0 -10
- mqt/core/include/mqt-core/ir/QuantumComputation.hpp +3 -0
- mqt/core/include/mqt-core/ir/operations/CompoundOperation.hpp +2 -0
- mqt/core/include/mqt-core/ir/operations/Operation.hpp +2 -2
- mqt/core/ir.cp39-win_amd64.pyd +0 -0
- mqt/core/lib/mqt-core-algorithms.lib +0 -0
- mqt/core/lib/mqt-core-circuit-optimizer.lib +0 -0
- mqt/core/lib/mqt-core-dd.lib +0 -0
- mqt/core/lib/mqt-core-ds.lib +0 -0
- mqt/core/lib/mqt-core-ir.lib +0 -0
- mqt/core/lib/mqt-core-na.lib +0 -0
- mqt/core/lib/mqt-core-qasm.lib +0 -0
- mqt/core/lib/mqt-core-zx.lib +0 -0
- mqt/core/plugins/__init__.py +0 -8
- mqt/core/plugins/qiskit/qiskit_to_mqt.py +6 -0
- mqt/core/share/cmake/mqt-core/AddMQTPythonBinding.cmake +52 -0
- mqt/core/share/cmake/mqt-core/PackageAddTest.cmake +4 -4
- mqt/core/share/cmake/mqt-core/mqt-core-config-version.cmake +3 -3
- mqt/core/share/cmake/mqt-core/mqt-core-config.cmake +1 -0
- mqt/core/share/cmake/mqt-core/mqt-core-targets.cmake +1 -1
- mqt_core-3.1.0.dist-info/DELVEWHEEL +2 -0
- {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/METADATA +54 -9
- {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/RECORD +55 -102
- {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/WHEEL +1 -1
- mqt_core.libs/msvcp140.dll +0 -0
- mqt/core/include/nlohmann/adl_serializer.hpp +0 -55
- mqt/core/include/nlohmann/byte_container_with_subtype.hpp +0 -103
- mqt/core/include/nlohmann/detail/abi_macros.hpp +0 -100
- mqt/core/include/nlohmann/detail/conversions/from_json.hpp +0 -497
- mqt/core/include/nlohmann/detail/conversions/to_chars.hpp +0 -1118
- mqt/core/include/nlohmann/detail/conversions/to_json.hpp +0 -446
- mqt/core/include/nlohmann/detail/exceptions.hpp +0 -257
- mqt/core/include/nlohmann/detail/hash.hpp +0 -129
- mqt/core/include/nlohmann/detail/input/binary_reader.hpp +0 -3009
- mqt/core/include/nlohmann/detail/input/input_adapters.hpp +0 -492
- mqt/core/include/nlohmann/detail/input/json_sax.hpp +0 -727
- mqt/core/include/nlohmann/detail/input/lexer.hpp +0 -1633
- mqt/core/include/nlohmann/detail/input/parser.hpp +0 -519
- mqt/core/include/nlohmann/detail/input/position_t.hpp +0 -37
- mqt/core/include/nlohmann/detail/iterators/internal_iterator.hpp +0 -35
- mqt/core/include/nlohmann/detail/iterators/iter_impl.hpp +0 -751
- mqt/core/include/nlohmann/detail/iterators/iteration_proxy.hpp +0 -242
- mqt/core/include/nlohmann/detail/iterators/iterator_traits.hpp +0 -61
- mqt/core/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +0 -130
- mqt/core/include/nlohmann/detail/iterators/primitive_iterator.hpp +0 -132
- mqt/core/include/nlohmann/detail/json_custom_base_class.hpp +0 -39
- mqt/core/include/nlohmann/detail/json_pointer.hpp +0 -988
- mqt/core/include/nlohmann/detail/json_ref.hpp +0 -78
- mqt/core/include/nlohmann/detail/macro_scope.hpp +0 -482
- mqt/core/include/nlohmann/detail/macro_unscope.hpp +0 -45
- mqt/core/include/nlohmann/detail/meta/call_std/begin.hpp +0 -17
- mqt/core/include/nlohmann/detail/meta/call_std/end.hpp +0 -17
- mqt/core/include/nlohmann/detail/meta/cpp_future.hpp +0 -171
- mqt/core/include/nlohmann/detail/meta/detected.hpp +0 -70
- mqt/core/include/nlohmann/detail/meta/identity_tag.hpp +0 -21
- mqt/core/include/nlohmann/detail/meta/is_sax.hpp +0 -159
- mqt/core/include/nlohmann/detail/meta/std_fs.hpp +0 -29
- mqt/core/include/nlohmann/detail/meta/type_traits.hpp +0 -795
- mqt/core/include/nlohmann/detail/meta/void_t.hpp +0 -24
- mqt/core/include/nlohmann/detail/output/binary_writer.hpp +0 -1838
- mqt/core/include/nlohmann/detail/output/output_adapters.hpp +0 -147
- mqt/core/include/nlohmann/detail/output/serializer.hpp +0 -988
- mqt/core/include/nlohmann/detail/string_concat.hpp +0 -146
- mqt/core/include/nlohmann/detail/string_escape.hpp +0 -72
- mqt/core/include/nlohmann/detail/value_t.hpp +0 -118
- mqt/core/include/nlohmann/json.hpp +0 -5258
- mqt/core/include/nlohmann/json_fwd.hpp +0 -75
- mqt/core/include/nlohmann/ordered_map.hpp +0 -359
- mqt/core/include/nlohmann/thirdparty/hedley/hedley.hpp +0 -2045
- mqt/core/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +0 -158
- mqt/core/nlohmann_json.natvis +0 -278
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfig.cmake +0 -15
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfigVersion.cmake +0 -20
- mqt/core/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake +0 -110
- mqt/core/share/pkgconfig/nlohmann_json.pc +0 -4
- mqt_core-3.0.1.dist-info/DELVEWHEEL +0 -2
- {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/entry_points.txt +0 -0
- {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/licenses/LICENSE.md +0 -0
- /mqt_core.libs/{.load-order-mqt_core-3.0.1 → .load-order-mqt_core-3.1.0} +0 -0
|
@@ -194,63 +194,160 @@ public:
|
|
|
194
194
|
void clearUniqueTables();
|
|
195
195
|
|
|
196
196
|
/**
|
|
197
|
-
* @brief
|
|
198
|
-
* @details This is the main function for increasing reference counts within
|
|
199
|
-
* the DD package. It increases the reference count of the complex edge weight
|
|
200
|
-
* as well as the DD node itself. If the node newly becomes active, meaning
|
|
201
|
-
* that it had a reference count of zero beforehand, the reference count of
|
|
202
|
-
* all children is recursively increased.
|
|
197
|
+
* @brief Add the DD to a tracking hashset and update its reference count.
|
|
203
198
|
* @tparam Node The node type of the edge.
|
|
204
|
-
* @param e The edge to increase the reference count of
|
|
199
|
+
* @param e The edge to increase the reference count of.
|
|
205
200
|
*/
|
|
206
201
|
template <class Node> void incRef(const Edge<Node>& e) noexcept {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const auto inc = getUniqueTable<Node>().incRef(p);
|
|
210
|
-
if (inc && p->ref == 1U) {
|
|
211
|
-
for (const auto& child : p->e) {
|
|
212
|
-
incRef(child);
|
|
213
|
-
}
|
|
202
|
+
if (Edge<Node>::trackingRequired(e)) {
|
|
203
|
+
roots.addToRoots(e);
|
|
214
204
|
}
|
|
215
205
|
}
|
|
216
206
|
|
|
217
207
|
/**
|
|
218
|
-
* @brief
|
|
219
|
-
*
|
|
220
|
-
* the DD package. It decreases the reference count of the complex edge weight
|
|
221
|
-
* as well as the DD node itself. If the node newly becomes dead, meaning
|
|
222
|
-
* that its reference count hit zero, the reference count of all children is
|
|
223
|
-
* recursively decreased.
|
|
208
|
+
* @brief Decrease the DD's reference count and remove it from the tracking
|
|
209
|
+
* hashset if the count hits zero.
|
|
224
210
|
* @tparam Node The node type of the edge.
|
|
225
|
-
* @param e The edge to decrease the reference count of
|
|
211
|
+
* @param e The edge to decrease the reference count of.
|
|
212
|
+
* @throws std::invalid_argument If the edge is not part of the tracking
|
|
213
|
+
* hashset.
|
|
226
214
|
*/
|
|
227
|
-
template <class Node> void decRef(const Edge<Node>& e)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const auto dec = getUniqueTable<Node>().decRef(p);
|
|
231
|
-
if (dec && p->ref == 0U) {
|
|
232
|
-
for (const auto& child : p->e) {
|
|
233
|
-
decRef(child);
|
|
234
|
-
}
|
|
215
|
+
template <class Node> void decRef(const Edge<Node>& e) {
|
|
216
|
+
if (Edge<Node>::trackingRequired(e)) {
|
|
217
|
+
roots.removeFromRoots(e);
|
|
235
218
|
}
|
|
236
219
|
}
|
|
237
220
|
|
|
221
|
+
template <class Node> [[nodiscard]] auto& getRootSet() noexcept {
|
|
222
|
+
return roots.getRoots<Node>();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private:
|
|
226
|
+
struct RootSetManager {
|
|
227
|
+
public:
|
|
228
|
+
template <class Node>
|
|
229
|
+
using RootSet = std::unordered_map<Edge<Node>, std::size_t>;
|
|
230
|
+
|
|
231
|
+
/// @brief Add to respective root set.
|
|
232
|
+
template <class Node> void addToRoots(const Edge<Node>& e) noexcept {
|
|
233
|
+
getRoots<Node>()[e]++;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// @brief Remove from respective root set.
|
|
237
|
+
template <class Node> void removeFromRoots(const Edge<Node>& e) {
|
|
238
|
+
auto& set = getRoots<Node>();
|
|
239
|
+
auto it = set.find(e);
|
|
240
|
+
if (it == set.end()) {
|
|
241
|
+
throw std::invalid_argument("Edge is not part of the root set.");
|
|
242
|
+
}
|
|
243
|
+
if (--it->second == 0U) {
|
|
244
|
+
set.erase(it);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// @brief Execute mark() -> op() -> unmark().
|
|
249
|
+
template <class Result, typename Fn> Result execute(Fn& op) noexcept {
|
|
250
|
+
mark();
|
|
251
|
+
Result res = op();
|
|
252
|
+
unmark();
|
|
253
|
+
return res;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/// @brief Clear all root sets.
|
|
257
|
+
void reset() {
|
|
258
|
+
vRoots.clear();
|
|
259
|
+
mRoots.clear();
|
|
260
|
+
dRoots.clear();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private:
|
|
264
|
+
/// @brief Mark edges contained in @p roots.
|
|
265
|
+
template <class Node> static void mark(const RootSet<Node>& roots) {
|
|
266
|
+
for (auto& [edge, _] : roots) {
|
|
267
|
+
edge.mark();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// @brief Unmark edges contained in @p roots.
|
|
272
|
+
template <class Node> static void unmark(const RootSet<Node>& roots) {
|
|
273
|
+
for (auto& [edge, _] : roots) {
|
|
274
|
+
edge.unmark();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/// @brief Mark edges contained in all root sets.
|
|
279
|
+
void mark() noexcept {
|
|
280
|
+
RootSetManager::mark(vRoots);
|
|
281
|
+
RootSetManager::mark(mRoots);
|
|
282
|
+
RootSetManager::mark(dRoots);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// @brief Unmark edges contained in all root sets.
|
|
286
|
+
void unmark() noexcept {
|
|
287
|
+
RootSetManager::unmark(vRoots);
|
|
288
|
+
RootSetManager::unmark(mRoots);
|
|
289
|
+
RootSetManager::unmark(dRoots);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/// @brief Return vector roots.
|
|
293
|
+
template <class Node,
|
|
294
|
+
std::enable_if_t<std::is_same_v<Node, vNode>, bool> = true>
|
|
295
|
+
auto& getRoots() noexcept {
|
|
296
|
+
return vRoots;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/// @brief Return matrix roots.
|
|
300
|
+
template <class Node,
|
|
301
|
+
std::enable_if_t<std::is_same_v<Node, mNode>, bool> = true>
|
|
302
|
+
auto& getRoots() noexcept {
|
|
303
|
+
return mRoots;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/// @brief Return density roots.
|
|
307
|
+
template <class Node,
|
|
308
|
+
std::enable_if_t<std::is_same_v<Node, dNode>, bool> = true>
|
|
309
|
+
auto& getRoots() noexcept {
|
|
310
|
+
return dRoots;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
RootSet<vNode> vRoots;
|
|
314
|
+
RootSet<mNode> mRoots;
|
|
315
|
+
RootSet<dNode> dRoots;
|
|
316
|
+
|
|
317
|
+
template <class Node> friend auto& Package::getRootSet() noexcept;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
RootSetManager roots;
|
|
321
|
+
|
|
322
|
+
public:
|
|
238
323
|
/**
|
|
239
|
-
* @brief Trigger garbage collection
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
* unique tables
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* @
|
|
250
|
-
*
|
|
324
|
+
* @brief Trigger garbage collection on all unique tables.
|
|
325
|
+
* @details Mark-and-sweep algorithm: First, mark all nodes and complex
|
|
326
|
+
* numbers tracked in @p roots. Second, remove any unmarked nodes and numbers
|
|
327
|
+
* from the respective unique tables. Lastly, unmark all nodes and complex
|
|
328
|
+
* numbers again.
|
|
329
|
+
* @note By default, garbage collection is only triggered if the unique tables
|
|
330
|
+
* report that a collection might be necessary.
|
|
331
|
+
*
|
|
332
|
+
* @param force Force garbage collect, regardless of whether any
|
|
333
|
+
* table reports that it may need collecting.
|
|
334
|
+
* @returns Whether at least one vector, matrix, density-matrix node, or
|
|
335
|
+
* any complex number was reclaimed.
|
|
251
336
|
*/
|
|
252
337
|
bool garbageCollect(bool force = false);
|
|
253
338
|
|
|
339
|
+
struct ActiveCounts {
|
|
340
|
+
std::size_t vector = 0U;
|
|
341
|
+
std::size_t matrix = 0U;
|
|
342
|
+
std::size_t density = 0U;
|
|
343
|
+
std::size_t reals = 0U;
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* @brief Compute the active number of nodes and numbers
|
|
347
|
+
* @note This traverses every currently tracked DD twice.
|
|
348
|
+
*/
|
|
349
|
+
[[nodiscard]] ActiveCounts computeActiveCounts();
|
|
350
|
+
|
|
254
351
|
///
|
|
255
352
|
/// Vector nodes, edges and quantum states
|
|
256
353
|
///
|
|
@@ -263,60 +360,6 @@ public:
|
|
|
263
360
|
*/
|
|
264
361
|
dEdge makeZeroDensityOperator(std::size_t n);
|
|
265
362
|
|
|
266
|
-
/**
|
|
267
|
-
* @brief Construct the all-zero state \f$|0...0\rangle\f$
|
|
268
|
-
* @param n The number of qubits
|
|
269
|
-
* @param start The starting qubit index. Default is 0.
|
|
270
|
-
* @return A decision diagram for the all-zero state
|
|
271
|
-
*/
|
|
272
|
-
vEdge makeZeroState(std::size_t n, std::size_t start = 0);
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @brief Construct a computational basis state \f$|b_{n-1}...b_0\rangle\f$
|
|
276
|
-
* @param n The number of qubits
|
|
277
|
-
* @param state The state to construct
|
|
278
|
-
* @param start The starting qubit index. Default is 0.
|
|
279
|
-
* @return A decision diagram for the computational basis state
|
|
280
|
-
*/
|
|
281
|
-
vEdge makeBasisState(std::size_t n, const std::vector<bool>& state,
|
|
282
|
-
std::size_t start = 0);
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* @brief Construct a product state out of
|
|
286
|
-
* \f$\{0, 1, +, -, R, L\}^{\otimes n}\f$.
|
|
287
|
-
* @param n The number of qubits
|
|
288
|
-
* @param state The state to construct
|
|
289
|
-
* @param start The starting qubit index. Default is 0.
|
|
290
|
-
* @return A decision diagram for the product state
|
|
291
|
-
*/
|
|
292
|
-
vEdge makeBasisState(std::size_t n, const std::vector<BasisStates>& state,
|
|
293
|
-
std::size_t start = 0);
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* @brief Construct a GHZ state \f$|0...0\rangle + |1...1\rangle\f$
|
|
297
|
-
* @param n The number of qubits
|
|
298
|
-
* @return A decision diagram for the GHZ state
|
|
299
|
-
*/
|
|
300
|
-
vEdge makeGHZState(std::size_t n);
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* @brief Construct a W state
|
|
304
|
-
* @details The W state is defined as
|
|
305
|
-
* \f[
|
|
306
|
-
* |0...01\rangle + |0...10\rangle + |10...0\rangle
|
|
307
|
-
* \f]
|
|
308
|
-
* @param n The number of qubits
|
|
309
|
-
* @return A decision diagram for the W state
|
|
310
|
-
*/
|
|
311
|
-
vEdge makeWState(std::size_t n);
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* @brief Construct a decision diagram from an arbitrary state vector
|
|
315
|
-
* @param stateVector The state vector to convert to a DD
|
|
316
|
-
* @return A decision diagram for the state
|
|
317
|
-
*/
|
|
318
|
-
vEdge makeStateFromVector(const CVec& stateVector);
|
|
319
|
-
|
|
320
363
|
///
|
|
321
364
|
/// Matrix nodes, edges and quantum gates
|
|
322
365
|
///
|
|
@@ -399,30 +442,6 @@ public:
|
|
|
399
442
|
mEdge makeDDFromMatrix(const CMat& matrix);
|
|
400
443
|
|
|
401
444
|
private:
|
|
402
|
-
/**
|
|
403
|
-
* @brief Constructs a decision diagram (DD) from a state vector using a
|
|
404
|
-
* recursive algorithm.
|
|
405
|
-
*
|
|
406
|
-
* @param begin Iterator pointing to the beginning of the state vector.
|
|
407
|
-
* @param end Iterator pointing to the end of the state vector.
|
|
408
|
-
* @param level The current level of recursion. Starts at the highest level of
|
|
409
|
-
* the state vector (log base 2 of the vector size - 1).
|
|
410
|
-
* @return A vCachedEdge representing the root node of the created DD.
|
|
411
|
-
*
|
|
412
|
-
* @details This function recursively breaks down the state vector into halves
|
|
413
|
-
* until each half has only one element. At each level of recursion, two new
|
|
414
|
-
* edges are created, one for each half of the state vector. The two resulting
|
|
415
|
-
* decision diagram edges are used to create a new decision diagram node at
|
|
416
|
-
* the current level, and this node is returned as the result of the current
|
|
417
|
-
* recursive call. At the base case of recursion, the state vector has only
|
|
418
|
-
* two elements, which are converted into terminal nodes of the decision
|
|
419
|
-
* diagram.
|
|
420
|
-
*
|
|
421
|
-
* @note This function assumes that the state vector size is a power of two.
|
|
422
|
-
*/
|
|
423
|
-
vCachedEdge makeStateFromVector(const CVec::const_iterator& begin,
|
|
424
|
-
const CVec::const_iterator& end, Qubit level);
|
|
425
|
-
|
|
426
445
|
/**
|
|
427
446
|
* @brief Constructs a decision diagram (DD) from a complex matrix using a
|
|
428
447
|
* recursive algorithm.
|
|
@@ -477,7 +496,6 @@ public:
|
|
|
477
496
|
[[maybe_unused]] const bool generateDensityMatrix = false) {
|
|
478
497
|
auto& memoryManager = getMemoryManager<Node>();
|
|
479
498
|
auto p = memoryManager.template get<Node>();
|
|
480
|
-
assert(p->ref == 0U);
|
|
481
499
|
|
|
482
500
|
p->v = var;
|
|
483
501
|
if constexpr (std::is_same_v<Node, mNode> || std::is_same_v<Node, dNode>) {
|
|
@@ -21,18 +21,16 @@
|
|
|
21
21
|
namespace dd {
|
|
22
22
|
/**
|
|
23
23
|
* @brief A struct for representing real numbers as part of the DD package.
|
|
24
|
-
* @details Consists of a floating point number (the value)
|
|
25
|
-
* (used for chaining entries)
|
|
24
|
+
* @details Consists of a floating point number (the value) and a next pointer
|
|
25
|
+
* (used for chaining entries). Numbers are marked for garbage collection via
|
|
26
|
+
* the second least significant bit of pointers referencing them.
|
|
26
27
|
* @note Due to the way the sign of the value is encoded, special care has to
|
|
27
28
|
* be taken when accessing the value. The static functions in this struct
|
|
28
29
|
* provide safe access to the value of a RealNumber* pointer.
|
|
29
30
|
*/
|
|
30
31
|
struct RealNumber final : LLBase {
|
|
31
|
-
|
|
32
32
|
/// Getter for the next object.
|
|
33
|
-
[[nodiscard]] RealNumber* next() const noexcept
|
|
34
|
-
return reinterpret_cast<RealNumber*>(next_);
|
|
35
|
-
}
|
|
33
|
+
[[nodiscard]] RealNumber* next() const noexcept;
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
* @brief Check whether the number points to the zero number.
|
|
@@ -65,15 +63,6 @@ struct RealNumber final : LLBase {
|
|
|
65
63
|
*/
|
|
66
64
|
[[nodiscard]] static fp val(const RealNumber* e) noexcept;
|
|
67
65
|
|
|
68
|
-
/**
|
|
69
|
-
* @brief Get the reference count of the number.
|
|
70
|
-
* @param num A pointer to the number to get the reference count for.
|
|
71
|
-
* @returns The reference count of the number.
|
|
72
|
-
* @note This function accounts for the sign of the number embedded in the
|
|
73
|
-
* memory address of the number.
|
|
74
|
-
*/
|
|
75
|
-
[[nodiscard]] static RefCount refCount(const RealNumber* num) noexcept;
|
|
76
|
-
|
|
77
66
|
/**
|
|
78
67
|
* @brief Check whether two floating point numbers are approximately equal.
|
|
79
68
|
* @details This function checks whether two floating point numbers are
|
|
@@ -115,42 +104,6 @@ struct RealNumber final : LLBase {
|
|
|
115
104
|
*/
|
|
116
105
|
[[nodiscard]] static bool approximatelyZero(const RealNumber* e) noexcept;
|
|
117
106
|
|
|
118
|
-
/**
|
|
119
|
-
* @brief Indicates whether a given number needs reference count updates.
|
|
120
|
-
* @details This function checks whether a given number needs reference count
|
|
121
|
-
* updates. A number needs reference count updates if the pointer to it is
|
|
122
|
-
* not the null pointer, if it is not one of the special numbers (zero,
|
|
123
|
-
* one, 1/sqrt(2)), and if the reference count has saturated.
|
|
124
|
-
* @param num Pointer to the number to check.
|
|
125
|
-
* @returns Whether the number needs reference count updates.
|
|
126
|
-
* @note This function assumes that the pointer to the number is aligned.
|
|
127
|
-
*/
|
|
128
|
-
[[nodiscard]] static bool noRefCountingNeeded(const RealNumber* num) noexcept;
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* @brief Increment the reference count of a number.
|
|
132
|
-
* @details This function increments the reference count of a number. If the
|
|
133
|
-
* reference count has saturated (i.e. reached the maximum value of RefCount)
|
|
134
|
-
* the reference count is not incremented.
|
|
135
|
-
* @param num A pointer to the number to increment the reference count of.
|
|
136
|
-
* @returns Whether the reference count was incremented.
|
|
137
|
-
* @note Typically, you do not want to call this function directly. Instead,
|
|
138
|
-
* use the RealNumberUniqueTable::incRef(RelNumber*) function.
|
|
139
|
-
*/
|
|
140
|
-
[[nodiscard]] static bool incRef(const RealNumber* num) noexcept;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* @brief Decrement the reference count of a number.
|
|
144
|
-
* @details This function decrements the reference count of a number. If the
|
|
145
|
-
* reference count has saturated (i.e. reached the maximum value of RefCount)
|
|
146
|
-
* the reference count is not decremented.
|
|
147
|
-
* @param num A pointer to the number to decrement the reference count of.
|
|
148
|
-
* @returns Whether the reference count was decremented.
|
|
149
|
-
* @note Typically, you do not want to call this function directly. Instead,
|
|
150
|
-
* use the RealNumberUniqueTable::decRef(RelNumber*) function.
|
|
151
|
-
*/
|
|
152
|
-
[[nodiscard]] static bool decRef(const RealNumber* num) noexcept;
|
|
153
|
-
|
|
154
107
|
/**
|
|
155
108
|
* @brief Write a binary representation of the number to a stream.
|
|
156
109
|
* @param e The number to write.
|
|
@@ -195,13 +148,6 @@ struct RealNumber final : LLBase {
|
|
|
195
148
|
[[nodiscard]] static RealNumber*
|
|
196
149
|
getNegativePointer(const RealNumber* e) noexcept;
|
|
197
150
|
|
|
198
|
-
/**
|
|
199
|
-
* @brief Check whether the number is a negative pointer.
|
|
200
|
-
* @param e The number to check.
|
|
201
|
-
* @returns Whether the number is a negative pointer.
|
|
202
|
-
*/
|
|
203
|
-
[[nodiscard]] static bool isNegativePointer(const RealNumber* e) noexcept;
|
|
204
|
-
|
|
205
151
|
/**
|
|
206
152
|
* @brief Flip the sign of the number pointer.
|
|
207
153
|
* @param e The number to flip the sign of.
|
|
@@ -214,6 +160,48 @@ struct RealNumber final : LLBase {
|
|
|
214
160
|
[[nodiscard]] static RealNumber*
|
|
215
161
|
flipPointerSign(const RealNumber* e) noexcept;
|
|
216
162
|
|
|
163
|
+
/**
|
|
164
|
+
* @brief Mark @p e for garbage collection.
|
|
165
|
+
* @details Sets the 2nd least significant bit of the next_ pointer.
|
|
166
|
+
* @param e The number to mark.
|
|
167
|
+
*/
|
|
168
|
+
static void mark(RealNumber* e) noexcept;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @brief Unmark @p e after garbage collection.
|
|
172
|
+
* @details Unsets the 2nd least significant bit of the next_ pointer.
|
|
173
|
+
* @param e The number to unmark.
|
|
174
|
+
*/
|
|
175
|
+
static void unmark(RealNumber* e) noexcept;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @brief Immortalize @p e.
|
|
179
|
+
* @details Sets the 3rd least significant bit of the next_ pointer.
|
|
180
|
+
* @param e The number to immortalize.
|
|
181
|
+
*/
|
|
182
|
+
static void immortalize(RealNumber* e) noexcept;
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* @brief Check whether the number is flagged as negative.
|
|
186
|
+
* @param e The number to check.
|
|
187
|
+
* @returns Whether the number is negative.
|
|
188
|
+
*/
|
|
189
|
+
[[nodiscard]] static bool isNegativePointer(const RealNumber* e) noexcept;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @brief Check whether the number is flagged as marked.
|
|
193
|
+
* @param e The number to check.
|
|
194
|
+
* @returns Whether the number is marked.
|
|
195
|
+
*/
|
|
196
|
+
[[nodiscard]] static bool isMarked(const RealNumber* e) noexcept;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @brief Check whether the number is flagged as immortal.
|
|
200
|
+
* @param e The number to check.
|
|
201
|
+
* @returns Whether the number is immortal.
|
|
202
|
+
*/
|
|
203
|
+
[[nodiscard]] static bool isImmortal(const RealNumber* e) noexcept;
|
|
204
|
+
|
|
217
205
|
/**
|
|
218
206
|
* @brief The value of the number.
|
|
219
207
|
* @details The value of the number is a floating point number. The sign of
|
|
@@ -224,19 +212,14 @@ struct RealNumber final : LLBase {
|
|
|
224
212
|
*/
|
|
225
213
|
fp value{};
|
|
226
214
|
|
|
227
|
-
/**
|
|
228
|
-
* @brief The reference count of the number.
|
|
229
|
-
* @details The reference count is used to determine whether a number is
|
|
230
|
-
* still in use. If the reference count is zero, the number is not in use
|
|
231
|
-
* and can be garbage collected.
|
|
232
|
-
*/
|
|
233
|
-
RefCount ref{};
|
|
234
|
-
|
|
235
215
|
/// numerical tolerance to be used for floating point values
|
|
236
216
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
|
237
217
|
static inline fp eps = std::numeric_limits<dd::fp>::epsilon() * 1024;
|
|
238
218
|
};
|
|
239
219
|
|
|
220
|
+
static_assert(sizeof(RealNumber) == 16);
|
|
221
|
+
static_assert(alignof(RealNumber) == 8);
|
|
222
|
+
|
|
240
223
|
namespace constants {
|
|
241
224
|
// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
|
|
242
225
|
/// The constant zero.
|
|
@@ -23,6 +23,14 @@ namespace dd {
|
|
|
23
23
|
|
|
24
24
|
struct RealNumber;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @brief Immortal numbers that will never be garbage collected.
|
|
28
|
+
*/
|
|
29
|
+
namespace immortals {
|
|
30
|
+
constexpr std::array<fp, 1> get() { return {.5}; }
|
|
31
|
+
constexpr std::size_t size() { return get().size(); }
|
|
32
|
+
} // namespace immortals
|
|
33
|
+
|
|
26
34
|
/**
|
|
27
35
|
* @brief A unique table for real numbers.
|
|
28
36
|
* @details A hash table that stores real numbers. The hash table is implemented
|
|
@@ -93,28 +101,6 @@ public:
|
|
|
93
101
|
*/
|
|
94
102
|
[[nodiscard]] RealNumber* lookup(fp val);
|
|
95
103
|
|
|
96
|
-
/**
|
|
97
|
-
* @brief Increment the reference count of a number.
|
|
98
|
-
* @details This is a pass-through function that calls the increment function
|
|
99
|
-
* of the number. It additionally keeps track of the number of active entries
|
|
100
|
-
* in the table (entries with a reference count greater than zero). Reference
|
|
101
|
-
* counts saturate at the maximum value of RefCount.
|
|
102
|
-
* @param num A pointer to the number to increase the reference count of.
|
|
103
|
-
* @see RealNumber::incRef(RealNumber*)
|
|
104
|
-
*/
|
|
105
|
-
void incRef(RealNumber* num) noexcept;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* @brief Decrement the reference count of a number.
|
|
109
|
-
* @details This is a pass-through function that calls the decrement function
|
|
110
|
-
* of the number. It additionally keeps track of the number of active entries
|
|
111
|
-
* in the table (entries with a reference count greater than zero). Reference
|
|
112
|
-
* counts saturate at the maximum value of RefCount.
|
|
113
|
-
* @param num A pointer to the number to decrease the reference count of.
|
|
114
|
-
* @see RealNumber::decRef(RealNumber*)
|
|
115
|
-
*/
|
|
116
|
-
void decRef(RealNumber* num) noexcept;
|
|
117
|
-
|
|
118
104
|
/**
|
|
119
105
|
* @brief Check whether the table possibly needs garbage collection.
|
|
120
106
|
* @returns Whether the number of entries in the table has reached the garbage
|
|
@@ -126,9 +112,9 @@ public:
|
|
|
126
112
|
* @brief Perform garbage collection.
|
|
127
113
|
* @details This function performs garbage collection. It first checks whether
|
|
128
114
|
* garbage collection is necessary. If not, it does nothing. Otherwise, it
|
|
129
|
-
* iterates over all entries in the table and
|
|
130
|
-
*
|
|
131
|
-
*
|
|
115
|
+
* iterates over all entries in the table and removes all numbers whose
|
|
116
|
+
* pointers are unmarked. If the force flag is set, garbage collection is
|
|
117
|
+
* performed even if it is not strictly necessary.
|
|
132
118
|
* Based on how many entries are returned to the available list, the garbage
|
|
133
119
|
* collection limit is dynamically adjusted.
|
|
134
120
|
* @param force Whether to force garbage collection.
|
|
@@ -156,6 +142,9 @@ public:
|
|
|
156
142
|
*/
|
|
157
143
|
std::ostream& printBucketDistribution(std::ostream& os = std::cout);
|
|
158
144
|
|
|
145
|
+
/// Count the marked entries in the table
|
|
146
|
+
[[nodiscard]] std::size_t countMarkedEntries() const noexcept;
|
|
147
|
+
|
|
159
148
|
private:
|
|
160
149
|
/// Typedef for a bucket in the table.
|
|
161
150
|
using Bucket = RealNumber*;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023 - 2025 Chair for Design Automation, TUM
|
|
3
|
+
* Copyright (c) 2025 Munich Quantum Software Company GmbH
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* SPDX-License-Identifier: MIT
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the MIT License
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include "dd/Node.hpp"
|
|
14
|
+
#include "dd/Package.hpp"
|
|
15
|
+
|
|
16
|
+
#include <cstddef>
|
|
17
|
+
#include <cstdint>
|
|
18
|
+
#include <vector>
|
|
19
|
+
|
|
20
|
+
namespace dd {
|
|
21
|
+
/**
|
|
22
|
+
* @brief Construct the all-zero state \f$|0...0\rangle\f$
|
|
23
|
+
* @param n The number of qubits.
|
|
24
|
+
* @param dd The DD package to use for making the vector DD.
|
|
25
|
+
* @param start The starting qubit index. Default is 0.
|
|
26
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < n`.
|
|
27
|
+
* @return A vector DD for the all-zero state.
|
|
28
|
+
*/
|
|
29
|
+
VectorDD makeZeroState(std::size_t n, Package& dd, std::size_t start = 0);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @brief Construct a computational basis state \f$|b_{n-1}...b_0\rangle\f$
|
|
33
|
+
* @param n The number of qubits.
|
|
34
|
+
* @param state The state to construct.
|
|
35
|
+
* @param dd The DD package to use for making the vector DD.
|
|
36
|
+
* @param start The starting qubit index. Default is 0.
|
|
37
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < n` or `size(state) < n`.
|
|
38
|
+
* @return A vector DD for the computational basis state.
|
|
39
|
+
*/
|
|
40
|
+
VectorDD makeBasisState(std::size_t n, const std::vector<bool>& state,
|
|
41
|
+
Package& dd, std::size_t start = 0);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @brief Construct a product state out of
|
|
45
|
+
* \f$\{0, 1, +, -, R, L\}^{\otimes n}\f$.
|
|
46
|
+
* @param n The number of qubits
|
|
47
|
+
* @param state The state to construct.
|
|
48
|
+
* @param dd The DD package to use for making the vector DD.
|
|
49
|
+
* @param start The starting qubit index. Default is 0.
|
|
50
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < n` or `size(state) < n`.
|
|
51
|
+
* @return A vector DD for the product state.
|
|
52
|
+
*/
|
|
53
|
+
VectorDD makeBasisState(std::size_t n, const std::vector<BasisStates>& state,
|
|
54
|
+
Package& dd, std::size_t start = 0);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @brief Construct a GHZ state \f$|0...0\rangle + |1...1\rangle\f$.
|
|
58
|
+
* @param n The number of qubits.
|
|
59
|
+
* @param dd The DD package to use for making the vector DD.
|
|
60
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < n`.
|
|
61
|
+
* @return A vector DD for the GHZ state.
|
|
62
|
+
*/
|
|
63
|
+
VectorDD makeGHZState(std::size_t n, Package& dd);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @brief Construct a W state.
|
|
67
|
+
* @details The W state is defined as
|
|
68
|
+
* \f[
|
|
69
|
+
* |0...01\rangle + |0...10\rangle + |10...0\rangle
|
|
70
|
+
* \f]
|
|
71
|
+
* @param n The number of qubits.
|
|
72
|
+
* @param dd The DD package to use for making the vector DD.
|
|
73
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < n` or the number of qubits
|
|
74
|
+
* and currently set tolerance would lead to an underflow.
|
|
75
|
+
* @return A vector DD for the W state.
|
|
76
|
+
*/
|
|
77
|
+
VectorDD makeWState(std::size_t n, Package& dd);
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @brief Construct a decision diagram from an arbitrary state vector.
|
|
81
|
+
* @param vec The state vector to convert to a DD.
|
|
82
|
+
* @param dd The DD package to use for making the vector DD.
|
|
83
|
+
* @throws `std::invalid_argument`, if `vec.size()` is not a power of two or
|
|
84
|
+
* `dd.qubits() < log2(vec.size()) - 1`.
|
|
85
|
+
* @return A vector DD representing the state.
|
|
86
|
+
*/
|
|
87
|
+
VectorDD makeStateFromVector(const CVec& vec, Package& dd);
|
|
88
|
+
|
|
89
|
+
/// @brief The strategy to wire two layers.
|
|
90
|
+
enum GenerationWireStrategy : std::uint8_t {
|
|
91
|
+
ROUNDROBIN, // Choose nodes in the next layer in a round-robin fashion.
|
|
92
|
+
RANDOM // Randomly choose nodes in the next layer.
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @brief Generate exponentially large vector DD.
|
|
97
|
+
* @param levels The number of levels in the vector DD.
|
|
98
|
+
* @param dd The DD package to use for generating the vector DD.
|
|
99
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < levels`.
|
|
100
|
+
* @return The exponentially large vector DD.
|
|
101
|
+
*/
|
|
102
|
+
VectorDD generateExponentialState(std::size_t levels, Package& dd);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @brief Generate exponentially large vector DD. Use @p seed for randomization.
|
|
106
|
+
* @param levels The number of levels in the vector DD.
|
|
107
|
+
* @param dd The DD package to use for generating the vector DD.
|
|
108
|
+
* @param seed The seed used for randomization.
|
|
109
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < levels`.
|
|
110
|
+
* @return The exponentially large vector DD.
|
|
111
|
+
*/
|
|
112
|
+
VectorDD generateExponentialState(std::size_t levels, Package& dd,
|
|
113
|
+
std::size_t seed);
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @brief Generate random vector DD.
|
|
117
|
+
* @param levels The number of levels in the vector DD.
|
|
118
|
+
* @param nodesPerLevel The number of nodes per level.
|
|
119
|
+
* @param strategy The strategy to wire two layers.
|
|
120
|
+
* @param dd The DD package to use for generating the vector DD.
|
|
121
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < levels`.
|
|
122
|
+
* @return The random vector DD.
|
|
123
|
+
*/
|
|
124
|
+
VectorDD generateRandomState(std::size_t levels,
|
|
125
|
+
const std::vector<std::size_t>& nodesPerLevel,
|
|
126
|
+
GenerationWireStrategy strategy, Package& dd);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @brief Generate random vector DD. Use @p seed for randomization.
|
|
130
|
+
* @param levels The number of levels in the vector DD.
|
|
131
|
+
* @param nodesPerLevel The number of nodes per level.
|
|
132
|
+
* @param strategy The strategy to wire two layers.
|
|
133
|
+
* @param dd The DD package to use for generating the vector DD.
|
|
134
|
+
* @param seed The seed used for randomization.
|
|
135
|
+
* @throws `std::invalid_argument`, if `dd.qubits() < levels`, `levels <= 0`, or
|
|
136
|
+
* `nodesPerLevel.size() != levels`.
|
|
137
|
+
* @return The random vector DD.
|
|
138
|
+
*/
|
|
139
|
+
VectorDD generateRandomState(std::size_t levels,
|
|
140
|
+
const std::vector<std::size_t>& nodesPerLevel,
|
|
141
|
+
GenerationWireStrategy strategy, Package& dd,
|
|
142
|
+
std::size_t seed);
|
|
143
|
+
}; // namespace dd
|