Qrack  10.0
General classical-emulating-quantum development framework
qbdt_node_interface.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // QBinaryDecision tree is an alternative approach to quantum state representation, as
6 // opposed to state vector representation. This is a compressed form that can be
7 // operated directly on while compressed. Inspiration for the Qrack implementation was
8 // taken from JKQ DDSIM, maintained by the Institute for Integrated Circuits at the
9 // Johannes Kepler University Linz:
10 //
11 // https://github.com/iic-jku/ddsim
12 //
13 // Licensed under the GNU Lesser General Public License V3.
14 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
15 // for details.
16 
17 #pragma once
18 
20 
21 #include <functional>
22 #include <mutex>
23 
24 #if ENABLE_COMPLEX_X2
25 #if FPPOW == 5
27 #elif FPPOW == 6
29 #endif
30 #endif
31 
32 namespace Qrack {
33 
34 class QBdtNodeInterface;
35 typedef std::shared_ptr<QBdtNodeInterface> QBdtNodeInterfacePtr;
36 
37 typedef std::function<bitCapInt(const bitCapInt&)> BdtFunc;
38 
40 protected:
41  static size_t SelectBit(bitCapInt perm, bitLenInt bit) { return (size_t)(bi_and_1(perm >> bit)); }
42  static void _par_for_qbdt(const bitCapInt& end, BdtFunc fn);
43 
44 public:
45 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
46 #if ENABLE_COMPLEX_X2
47  virtual void PushStateVector(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
48  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth,
49  bitLenInt parDepth = 1U)
50 #else
51  virtual void PushStateVector(const complex mtrx[4U], QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1,
52  bitLenInt depth, bitLenInt parDepth = 1U)
53 #endif
54 #else
55 #if ENABLE_COMPLEX_X2
56  virtual void PushStateVector(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
57  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth)
58 #else
59  virtual void PushStateVector(
60  const complex mtrx[4U], QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth)
61 #endif
62 #endif
63  {
64  throw std::out_of_range("QBdtNodeInterface::PushStateVector() not implemented! (You probably set "
65  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
66  }
67 
70 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
71  std::mutex mtx;
72 #endif
73 
75  : scale(ONE_CMPLX)
76  , branches{ nullptr, nullptr }
77  {
78  // Intentionally left blank
79  }
80 
82  : scale(scl)
83  , branches{ nullptr, nullptr }
84  {
85  // Intentionally left blank
86  }
87 
89  : scale(scl)
90  , branches{ b[0U], b[1U] }
91  {
92  // Intentionally left blank
93  }
94 
96  {
97  // Virtual destructor for inheritance
98  }
99 
100 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
101  virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt& size, bitLenInt parDepth = 1U)
102 #else
103  virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt& size)
104 #endif
105  {
106  throw std::out_of_range("QBdtNodeInterface::InsertAtDepth() not implemented! (You probably set "
107  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
108  }
109 
110 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
112  bitLenInt depth, const bitLenInt& size, bitLenInt parDepth = 1U);
113 #else
115 #endif
116 
117  virtual void SetZero()
118  {
119  scale = ZERO_CMPLX;
120 
121 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
122  if (branches[0U]) {
124  std::lock_guard<std::mutex> lock(b0->mtx);
125  branches[0U] = nullptr;
126  }
127 
128  if (branches[1U]) {
130  std::lock_guard<std::mutex> lock(b1->mtx);
131  branches[1U] = nullptr;
132  }
133 #else
134  branches[0U] = nullptr;
135  branches[1U] = nullptr;
136 #endif
137  }
138 
139  virtual bool isEqual(QBdtNodeInterfacePtr r);
140 
141  virtual bool isEqualUnder(QBdtNodeInterfacePtr r);
142 
143  virtual bool isEqualBranch(QBdtNodeInterfacePtr r, const bool& b);
144 
146  {
147  throw std::out_of_range("QBdtNodeInterface::ShallowClone() not implemented! (You probably set "
148  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
149  }
150 
151 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
152  virtual void PopStateVector(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
153 #else
154  virtual void PopStateVector(bitLenInt depth = 1U)
155 #endif
156  {
157  if (!depth) {
158  return;
159  }
160 
161  throw std::out_of_range("QBdtNodeInterface::PopStateVector() not implemented! (You probably set "
162  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
163  }
164 
165 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
166  virtual void Branch(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
167 #else
168  virtual void Branch(bitLenInt depth = 1U)
169 #endif
170  {
171  if (!depth) {
172  return;
173  }
174 
175  throw std::out_of_range("QBdtNodeInterface::Branch() not implemented! (You probably set "
176  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
177  }
178 
179 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
180  virtual void Prune(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
181 #else
182  virtual void Prune(bitLenInt depth = 1U)
183 #endif
184  {
185  if (!depth) {
186  return;
187  }
188 
189  throw std::out_of_range("QBdtNodeInterface::Prune() not implemented! (You probably set "
190  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
191  }
192 
193  virtual void Normalize(bitLenInt depth = 1U)
194  {
195  if (!depth) {
196  return;
197  }
198 
199  throw std::out_of_range("QBdtNodeInterface::Normalize() not implemented! (You probably set "
200  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
201  }
202 
203 #if ENABLE_COMPLEX_X2
204  virtual void Apply2x2(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
205  const complex2& mtrxColShuff2, bitLenInt depth)
206 #else
207  virtual void Apply2x2(const complex mtrx[4U], bitLenInt depth)
208 #endif
209  {
210  if (!depth) {
211  return;
212  }
213 
214  throw std::out_of_range("QBdtNodeInterface::Apply2x2() not implemented! (You probably set "
215  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
216  }
217 
218 #if ENABLE_COMPLEX_X2
219  virtual void PushSpecial(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
220  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b1)
221 #else
222  virtual void PushSpecial(const complex mtrx[4U], QBdtNodeInterfacePtr& b1)
223 #endif
224  {
225  throw std::out_of_range("QBdtNodeInterface::PushSpecial() not implemented! (You probably called "
226  "PushStateVector() past terminal depth.)");
227  }
228 };
229 
232 } // namespace Qrack
int bi_and_1(const BigInteger &left)
Definition: big_integer.hpp:418
Definition: qbdt_node_interface.hpp:39
virtual void Normalize(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:193
virtual QBdtNodeInterfacePtr RemoveSeparableAtDepth(bitLenInt depth, const bitLenInt &size)
Definition: node_interface.cpp:114
virtual bool isEqualUnder(QBdtNodeInterfacePtr r)
Definition: node_interface.cpp:57
virtual bool isEqual(QBdtNodeInterfacePtr r)
Definition: node_interface.cpp:48
virtual void PushStateVector(const complex mtrx[4U], QBdtNodeInterfacePtr &b0, QBdtNodeInterfacePtr &b1, bitLenInt depth)
Definition: qbdt_node_interface.hpp:59
virtual void PopStateVector(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:154
virtual ~QBdtNodeInterface()
Definition: qbdt_node_interface.hpp:95
virtual void Branch(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:168
virtual QBdtNodeInterfacePtr ShallowClone()
Definition: qbdt_node_interface.hpp:145
virtual void SetZero()
Definition: qbdt_node_interface.hpp:117
QBdtNodeInterface()
Definition: qbdt_node_interface.hpp:74
virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt &size)
Definition: qbdt_node_interface.hpp:103
QBdtNodeInterfacePtr branches[2U]
Definition: qbdt_node_interface.hpp:69
complex scale
Definition: qbdt_node_interface.hpp:68
QBdtNodeInterface(const complex &scl)
Definition: qbdt_node_interface.hpp:81
virtual void Prune(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:182
virtual void PushSpecial(const complex mtrx[4U], QBdtNodeInterfacePtr &b1)
Definition: qbdt_node_interface.hpp:222
virtual bool isEqualBranch(QBdtNodeInterfacePtr r, const bool &b)
Definition: node_interface.cpp:66
QBdtNodeInterface(const complex &scl, QBdtNodeInterfacePtr *b)
Definition: qbdt_node_interface.hpp:88
virtual void Apply2x2(const complex mtrx[4U], bitLenInt depth)
Definition: qbdt_node_interface.hpp:207
static size_t SelectBit(bitCapInt perm, bitLenInt bit)
Definition: qbdt_node_interface.hpp:41
static void _par_for_qbdt(const bitCapInt &end, BdtFunc fn)
Definition: node_interface.cpp:178
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
std::function< bitCapInt(const bitCapInt &)> BdtFunc
Definition: qbdt_node_interface.hpp:37
void U(quid sid, bitLenInt q, real1_f theta, real1_f phi, real1_f lambda)
(External API) 3-parameter unitary gate
Definition: wasm_api.cpp:1199
std::complex< real1 > complex
Definition: qrack_types.hpp:140
bool operator==(QBdtNodeInterfacePtr lhs, QBdtNodeInterfacePtr rhs)
Definition: node_interface.cpp:37
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:257
bool operator!=(QBdtNodeInterfacePtr lhs, QBdtNodeInterfacePtr rhs)
Definition: node_interface.cpp:46
std::shared_ptr< QBdtNodeInterface > QBdtNodeInterfacePtr
Definition: qbdt_node_interface.hpp:34
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:258
#define bitLenInt
Definition: qrack_types.hpp:41
#define bitCapInt
Definition: qrack_types.hpp:65
SIMD implementation of the double precision complex vector type of 2 complex numbers,...
Definition: complex16x2simd.hpp:30