mqt-core 3.0.1__cp311-cp311-win_amd64.whl → 3.1.0__cp311-cp311-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.

Potentially problematic release.


This version of mqt-core might be problematic. Click here for more details.

Files changed (105) hide show
  1. mqt/core/__init__.py +3 -3
  2. mqt/core/_version.py +2 -2
  3. mqt/core/bin/mqt-core-algorithms.dll +0 -0
  4. mqt/core/bin/mqt-core-circuit-optimizer.dll +0 -0
  5. mqt/core/bin/mqt-core-dd.dll +0 -0
  6. mqt/core/bin/mqt-core-ds.dll +0 -0
  7. mqt/core/bin/mqt-core-ir.dll +0 -0
  8. mqt/core/bin/mqt-core-na.dll +0 -0
  9. mqt/core/bin/mqt-core-qasm.dll +0 -0
  10. mqt/core/bin/mqt-core-zx.dll +0 -0
  11. mqt/core/dd.cp311-win_amd64.pyd +0 -0
  12. mqt/core/include/mqt-core/dd/Approximation.hpp +45 -0
  13. mqt/core/include/mqt-core/dd/Complex.hpp +6 -0
  14. mqt/core/include/mqt-core/dd/ComplexNumbers.hpp +0 -18
  15. mqt/core/include/mqt-core/dd/ComputeTable.hpp +4 -1
  16. mqt/core/include/mqt-core/dd/DDDefinitions.hpp +0 -7
  17. mqt/core/include/mqt-core/dd/Edge.hpp +16 -0
  18. mqt/core/include/mqt-core/dd/Export.hpp +1 -2
  19. mqt/core/include/mqt-core/dd/Node.hpp +26 -49
  20. mqt/core/include/mqt-core/dd/Operations.hpp +27 -0
  21. mqt/core/include/mqt-core/dd/Package.hpp +138 -120
  22. mqt/core/include/mqt-core/dd/RealNumber.hpp +49 -66
  23. mqt/core/include/mqt-core/dd/RealNumberUniqueTable.hpp +14 -25
  24. mqt/core/include/mqt-core/dd/StateGeneration.hpp +143 -0
  25. mqt/core/include/mqt-core/dd/UnaryComputeTable.hpp +6 -4
  26. mqt/core/include/mqt-core/dd/UniqueTable.hpp +13 -39
  27. mqt/core/include/mqt-core/dd/statistics/PackageStatistics.hpp +8 -7
  28. mqt/core/include/mqt-core/dd/statistics/UniqueTableStatistics.hpp +0 -10
  29. mqt/core/include/mqt-core/ir/QuantumComputation.hpp +3 -0
  30. mqt/core/include/mqt-core/ir/operations/CompoundOperation.hpp +2 -0
  31. mqt/core/include/mqt-core/ir/operations/Operation.hpp +2 -2
  32. mqt/core/ir.cp311-win_amd64.pyd +0 -0
  33. mqt/core/lib/mqt-core-algorithms.lib +0 -0
  34. mqt/core/lib/mqt-core-circuit-optimizer.lib +0 -0
  35. mqt/core/lib/mqt-core-dd.lib +0 -0
  36. mqt/core/lib/mqt-core-ds.lib +0 -0
  37. mqt/core/lib/mqt-core-ir.lib +0 -0
  38. mqt/core/lib/mqt-core-na.lib +0 -0
  39. mqt/core/lib/mqt-core-qasm.lib +0 -0
  40. mqt/core/lib/mqt-core-zx.lib +0 -0
  41. mqt/core/plugins/__init__.py +0 -8
  42. mqt/core/plugins/qiskit/qiskit_to_mqt.py +6 -0
  43. mqt/core/share/cmake/mqt-core/AddMQTPythonBinding.cmake +52 -0
  44. mqt/core/share/cmake/mqt-core/PackageAddTest.cmake +4 -4
  45. mqt/core/share/cmake/mqt-core/mqt-core-config-version.cmake +3 -3
  46. mqt/core/share/cmake/mqt-core/mqt-core-config.cmake +1 -0
  47. mqt/core/share/cmake/mqt-core/mqt-core-targets.cmake +1 -1
  48. mqt_core-3.1.0.dist-info/DELVEWHEEL +2 -0
  49. {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/METADATA +54 -9
  50. {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/RECORD +54 -101
  51. {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/WHEEL +1 -1
  52. mqt_core.libs/msvcp140.dll +0 -0
  53. mqt/core/include/nlohmann/adl_serializer.hpp +0 -55
  54. mqt/core/include/nlohmann/byte_container_with_subtype.hpp +0 -103
  55. mqt/core/include/nlohmann/detail/abi_macros.hpp +0 -100
  56. mqt/core/include/nlohmann/detail/conversions/from_json.hpp +0 -497
  57. mqt/core/include/nlohmann/detail/conversions/to_chars.hpp +0 -1118
  58. mqt/core/include/nlohmann/detail/conversions/to_json.hpp +0 -446
  59. mqt/core/include/nlohmann/detail/exceptions.hpp +0 -257
  60. mqt/core/include/nlohmann/detail/hash.hpp +0 -129
  61. mqt/core/include/nlohmann/detail/input/binary_reader.hpp +0 -3009
  62. mqt/core/include/nlohmann/detail/input/input_adapters.hpp +0 -492
  63. mqt/core/include/nlohmann/detail/input/json_sax.hpp +0 -727
  64. mqt/core/include/nlohmann/detail/input/lexer.hpp +0 -1633
  65. mqt/core/include/nlohmann/detail/input/parser.hpp +0 -519
  66. mqt/core/include/nlohmann/detail/input/position_t.hpp +0 -37
  67. mqt/core/include/nlohmann/detail/iterators/internal_iterator.hpp +0 -35
  68. mqt/core/include/nlohmann/detail/iterators/iter_impl.hpp +0 -751
  69. mqt/core/include/nlohmann/detail/iterators/iteration_proxy.hpp +0 -242
  70. mqt/core/include/nlohmann/detail/iterators/iterator_traits.hpp +0 -61
  71. mqt/core/include/nlohmann/detail/iterators/json_reverse_iterator.hpp +0 -130
  72. mqt/core/include/nlohmann/detail/iterators/primitive_iterator.hpp +0 -132
  73. mqt/core/include/nlohmann/detail/json_custom_base_class.hpp +0 -39
  74. mqt/core/include/nlohmann/detail/json_pointer.hpp +0 -988
  75. mqt/core/include/nlohmann/detail/json_ref.hpp +0 -78
  76. mqt/core/include/nlohmann/detail/macro_scope.hpp +0 -482
  77. mqt/core/include/nlohmann/detail/macro_unscope.hpp +0 -45
  78. mqt/core/include/nlohmann/detail/meta/call_std/begin.hpp +0 -17
  79. mqt/core/include/nlohmann/detail/meta/call_std/end.hpp +0 -17
  80. mqt/core/include/nlohmann/detail/meta/cpp_future.hpp +0 -171
  81. mqt/core/include/nlohmann/detail/meta/detected.hpp +0 -70
  82. mqt/core/include/nlohmann/detail/meta/identity_tag.hpp +0 -21
  83. mqt/core/include/nlohmann/detail/meta/is_sax.hpp +0 -159
  84. mqt/core/include/nlohmann/detail/meta/std_fs.hpp +0 -29
  85. mqt/core/include/nlohmann/detail/meta/type_traits.hpp +0 -795
  86. mqt/core/include/nlohmann/detail/meta/void_t.hpp +0 -24
  87. mqt/core/include/nlohmann/detail/output/binary_writer.hpp +0 -1838
  88. mqt/core/include/nlohmann/detail/output/output_adapters.hpp +0 -147
  89. mqt/core/include/nlohmann/detail/output/serializer.hpp +0 -988
  90. mqt/core/include/nlohmann/detail/string_concat.hpp +0 -146
  91. mqt/core/include/nlohmann/detail/string_escape.hpp +0 -72
  92. mqt/core/include/nlohmann/detail/value_t.hpp +0 -118
  93. mqt/core/include/nlohmann/json.hpp +0 -5258
  94. mqt/core/include/nlohmann/json_fwd.hpp +0 -75
  95. mqt/core/include/nlohmann/ordered_map.hpp +0 -359
  96. mqt/core/include/nlohmann/thirdparty/hedley/hedley.hpp +0 -2045
  97. mqt/core/include/nlohmann/thirdparty/hedley/hedley_undef.hpp +0 -158
  98. mqt/core/nlohmann_json.natvis +0 -278
  99. mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfig.cmake +0 -15
  100. mqt/core/share/cmake/nlohmann_json/nlohmann_jsonConfigVersion.cmake +0 -20
  101. mqt/core/share/cmake/nlohmann_json/nlohmann_jsonTargets.cmake +0 -110
  102. mqt/core/share/pkgconfig/nlohmann_json.pc +0 -4
  103. mqt_core-3.0.1.dist-info/DELVEWHEEL +0 -2
  104. {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/entry_points.txt +0 -0
  105. {mqt_core-3.0.1.dist-info → mqt_core-3.1.0.dist-info}/licenses/LICENSE.md +0 -0
@@ -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), a next pointer
25
- * (used for chaining entries), and a reference count.
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 returns all entries with a
130
- * reference count of zero to the available list. If the force flag is set,
131
- * garbage collection is performed even if it is not necessary.
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
@@ -29,11 +29,13 @@ namespace dd {
29
29
  * @tparam OperandType type of the operation's operand
30
30
  * @tparam ResultType type of the operation's result
31
31
  */
32
- template <class OperandType, class ResultType, std::size_t NBUCKET = 32768>
33
- class UnaryComputeTable {
32
+ template <class OperandType, class ResultType> class UnaryComputeTable {
34
33
  public:
34
+ /// Default number of buckets for the compute table
35
+ static constexpr std::size_t DEFAULT_NUM_BUCKETS = 32768U;
36
+
35
37
  /// Default constructor
36
- explicit UnaryComputeTable(const size_t numBuckets = 32768U) {
38
+ explicit UnaryComputeTable(const size_t numBuckets = DEFAULT_NUM_BUCKETS) {
37
39
  // numBuckets must be a power of two
38
40
  if ((numBuckets & (numBuckets - 1)) != 0) {
39
41
  throw std::invalid_argument("Number of buckets must be a power of two.");
@@ -106,7 +108,7 @@ public:
106
108
  * @brief Clear the compute table
107
109
  * @details Sets all entries to invalid.
108
110
  */
109
- void clear() { valid = std::vector(NBUCKET, false); }
111
+ void clear() { valid = std::vector(stats.numBuckets, false); }
110
112
 
111
113
  private:
112
114
  /// The actual table storing the entries
@@ -96,10 +96,8 @@ public:
96
96
  }
97
97
  }
98
98
 
99
- // lookup a node in the unique table for the appropriate variable; insert it,
100
- // if it has not been found NOTE: reference counting is to be adjusted by
101
- // function invoking the table lookup and only normalized nodes shall be
102
- // stored.
99
+ // Lookup a node in the unique table for the appropriate variable and insert
100
+ // it if it has not been found. Only normalized nodes shall be stored.
103
101
  template <class Node> [[nodiscard]] Node* lookup(Node* p) {
104
102
  static_assert(std::is_base_of_v<NodeBase, Node>,
105
103
  "Node must be derived from NodeBase");
@@ -144,42 +142,19 @@ public:
144
142
  /// Get the total number of entries
145
143
  [[nodiscard]] std::size_t getNumEntries() const noexcept;
146
144
 
147
- /// Get the total number of active entries
148
- [[nodiscard]] std::size_t getNumActiveEntries() const noexcept;
145
+ /// Count the number of marked entries
146
+ [[nodiscard]] std::size_t countMarkedEntries() const noexcept;
149
147
 
150
- /// Get the peak total number of active entries
151
- [[nodiscard]] std::size_t getPeakNumActiveEntries() const noexcept;
152
-
153
- /**
154
- * @brief Increment the reference count of a node.
155
- * @details This is a pass-through function that calls the increment function
156
- * of the node. It additionally keeps track of the number of active entries
157
- * in the table (entries with a reference count greater than zero). Reference
158
- * counts saturate at the maximum value of RefCount.
159
- * @param p A pointer to the node to increase the reference count of.
160
- * @returns Whether the reference count was increased.
161
- * @see Node::incRef(Node*)
162
- */
163
- [[nodiscard]] bool incRef(NodeBase* p) noexcept;
164
148
  /**
165
- * @brief Decrement the reference count of a node.
166
- * @details This is a pass-through function that calls the decrement function
167
- * of the node. It additionally keeps track of the number of active entries
168
- * in the table (entries with a reference count greater than zero). Reference
169
- * counts saturate at the maximum value of RefCount.
170
- * @param p A pointer to the node to decrease the reference count of.
171
- * @returns Whether the reference count was decreased.
172
- * @see Node::decRef(Node*)
149
+ * @brief Determine whether the table possibly requires garbage collection.
173
150
  */
174
- [[nodiscard]] bool decRef(NodeBase* p) noexcept;
175
-
176
151
  [[nodiscard]] bool possiblyNeedsCollection() const;
177
152
 
178
153
  std::size_t garbageCollect(bool force = false);
179
154
 
180
155
  void clear();
181
156
 
182
- template <class Node> void print() {
157
+ template <class Node> void print() const {
183
158
  static_assert(std::is_base_of_v<NodeBase, Node>,
184
159
  "Node must be derived from NodeBase");
185
160
  auto q = cfg.nVars - 1U;
@@ -194,8 +169,8 @@ public:
194
169
  }
195
170
 
196
171
  while (p != nullptr) {
197
- std::cout << "\t\t" << std::hex << reinterpret_cast<std::uintptr_t>(p)
198
- << std::dec << " " << p->ref << std::hex;
172
+ std::cout << "\t\t" << std::hex
173
+ << reinterpret_cast<std::uintptr_t>(p);
199
174
  for (const auto& e : p->e) {
200
175
  std::cout << " p" << reinterpret_cast<std::uintptr_t>(e.p) << "(r"
201
176
  << reinterpret_cast<std::uintptr_t>(e.w.r) << " i"
@@ -235,12 +210,11 @@ private:
235
210
  std::vector<UniqueTableStatistics> stats;
236
211
 
237
212
  /**
238
- Searches for a node in the hash table with the given key.
239
- @param p The node to search for.
240
- @param key The hashed value used to search the table.
241
- @return The Edge<Node> found in the hash table or Edge<Node>::zero if not
242
- found.
243
- **/
213
+ * @brief Search for a node in the hash table with the given key.
214
+ * @param p The node to search for.
215
+ * @param key The hashed value used to search the table.
216
+ * @returns A pointer to the node if found or Node::getTerminal() otherwise.
217
+ */
244
218
  template <class Node>
245
219
  [[nodiscard]] Node* searchTable(Node& p, const std::size_t& key) {
246
220
  static_assert(std::is_base_of_v<NodeBase, Node>,
@@ -20,13 +20,14 @@ namespace dd {
20
20
 
21
21
  /**
22
22
  * @brief Computes an estimate for the memory usage of active DDs.
23
- * @details The estimate is based on the number of active entries in the
24
- * respective unique tables. It accounts for the memory used by DD nodes, DD
25
- * edges, and real numbers.
23
+ * @details The estimate is based on the number of active entries which are
24
+ * computed by temporarily marking all nodes reachable from the current root
25
+ * set and subsequently counting them in the unique tables. It accounts for the
26
+ * memory used by DD nodes, DD edges, and real numbers.
26
27
  * @param package The package instance
27
28
  * @return The estimated memory usage in MiB
28
29
  */
29
- [[nodiscard]] double computeActiveMemoryMiB(const Package& package);
30
+ [[nodiscard]] double computeActiveMemoryMiB(Package& package);
30
31
 
31
32
  /**
32
33
  * @brief Computes an estimate for the peak memory usage of DDs.
@@ -39,7 +40,7 @@ namespace dd {
39
40
  [[nodiscard]] double computePeakMemoryMiB(const Package& package);
40
41
 
41
42
  [[nodiscard]] nlohmann::basic_json<>
42
- getStatistics(const Package& package, bool includeIndividualTables = false);
43
+ getStatistics(Package& package, bool includeIndividualTables = false);
43
44
 
44
45
  /**
45
46
  * @brief Get some key statistics about data structures used by the DD package
@@ -47,8 +48,8 @@ getStatistics(const Package& package, bool includeIndividualTables = false);
47
48
  */
48
49
  [[nodiscard]] nlohmann::basic_json<> getDataStructureStatistics();
49
50
 
50
- [[nodiscard]] std::string getStatisticsString(const Package& package);
51
+ [[nodiscard]] std::string getStatisticsString(Package& package);
51
52
 
52
- void printStatistics(const Package& package, std::ostream& os = std::cout);
53
+ void printStatistics(Package& package, std::ostream& os = std::cout);
53
54
 
54
55
  } // namespace dd
@@ -18,19 +18,9 @@
18
18
  namespace dd {
19
19
  /// \brief A class for storing statistics of a unique table
20
20
  struct UniqueTableStatistics : public TableStatistics {
21
- /**
22
- * @brief The total number of active entries
23
- * @details An entry is considered active if it has a non-zero reference count
24
- */
25
- std::size_t numActiveEntries = 0U;
26
- /// The peak number of active entries in the table
27
- std::size_t peakNumActiveEntries = 0U;
28
21
  /// The number of garbage collection runs
29
22
  std::size_t gcRuns = 0U;
30
23
 
31
- /// Track a new active entry
32
- void trackActiveEntry() noexcept;
33
-
34
24
  /// Reset all statistics (except for the peak values)
35
25
  void reset() noexcept override;
36
26
 
@@ -124,6 +124,9 @@ public:
124
124
  [[nodiscard]] decltype(mt)& getGenerator() noexcept { return mt; }
125
125
 
126
126
  [[nodiscard]] fp getGlobalPhase() const noexcept { return globalPhase; }
127
+ [[nodiscard]] bool hasGlobalPhase() const noexcept {
128
+ return std::abs(getGlobalPhase()) > 0;
129
+ }
127
130
 
128
131
  [[nodiscard]] const std::unordered_set<sym::Variable>&
129
132
  getVariables() const noexcept {
@@ -48,6 +48,8 @@ public:
48
48
 
49
49
  [[nodiscard]] std::unique_ptr<Operation> clone() const override;
50
50
 
51
+ [[nodiscard]] size_t getNqubits() const override;
52
+
51
53
  [[nodiscard]] bool isCompoundOperation() const noexcept override;
52
54
 
53
55
  [[nodiscard]] bool isNonUnitaryOperation() const override;
@@ -68,8 +68,8 @@ public:
68
68
  [[nodiscard]] virtual std::size_t getNcontrols() const {
69
69
  return controls.size();
70
70
  }
71
- [[nodiscard]] std::size_t getNqubits() const {
72
- return getUsedQubits().size();
71
+ [[nodiscard]] virtual std::size_t getNqubits() const {
72
+ return getNcontrols() + getNtargets();
73
73
  }
74
74
 
75
75
  [[nodiscard]] const std::vector<fp>& getParameter() const {
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -7,11 +7,3 @@
7
7
  # Licensed under the MIT License
8
8
 
9
9
  """Plugins for the core package."""
10
-
11
- from __future__ import annotations
12
-
13
- from . import qiskit
14
-
15
- __all__ = [
16
- "qiskit",
17
- ]
@@ -150,6 +150,7 @@ _NATIVELY_SUPPORTED_GATES = frozenset({
150
150
  "sxdg",
151
151
  "csx",
152
152
  "mcx",
153
+ # we keep the "mcx_*" variants here for compatibility with Qiskit 1.x
153
154
  "mcx_gray",
154
155
  "mcx_recursive",
155
156
  "mcx_vchain",
@@ -207,6 +208,8 @@ def _emplace_operation(
207
208
  if name in {"i", "id", "iden"}:
208
209
  return _add_operation(qc, OpType.i, qargs, params, qubit_map)
209
210
 
211
+ # we keep "mcx_gray" here for compatibility reasons with older Qiskit versions, e.g., 1.0.0 where "noancilla"
212
+ # is the default for the argument "mode" which leads to the gate name "gray_code"
210
213
  if name in {"x", "cx", "ccx", "mcx", "mcx_gray"}:
211
214
  return _add_operation(qc, OpType.x, qargs, params, qubit_map)
212
215
 
@@ -234,6 +237,9 @@ def _emplace_operation(
234
237
  if name in {"sx", "csx"}:
235
238
  return _add_operation(qc, OpType.sx, qargs, params, qubit_map)
236
239
 
240
+ if name == "sxdg":
241
+ return _add_operation(qc, OpType.sxdg, qargs, params, qubit_map)
242
+
237
243
  if name == "mcx_recursive":
238
244
  if len(qargs) <= 5:
239
245
  return _add_operation(qc, OpType.x, qargs, params, qubit_map)