Qrack  9.13
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 <mutex>
22 
23 #if ENABLE_COMPLEX_X2
24 #if FPPOW == 5
26 #elif FPPOW == 6
28 #endif
29 #endif
30 
31 namespace Qrack {
32 
33 class QBdtNodeInterface;
34 typedef std::shared_ptr<QBdtNodeInterface> QBdtNodeInterfacePtr;
35 
37 protected:
38  static size_t SelectBit(bitCapInt perm, bitLenInt bit) { return (size_t)(bi_and_1(perm >> bit)); }
39  static void _par_for_qbdt(const bitCapInt& end, BdtFunc fn);
40 
41 public:
42 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
43 #if ENABLE_COMPLEX_X2
44  virtual void PushStateVector(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
45  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth,
46  bitLenInt parDepth = 1U)
47 #else
48  virtual void PushStateVector(const complex* mtrx, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1,
49  bitLenInt depth, bitLenInt parDepth = 1U)
50 #endif
51 #else
52 #if ENABLE_COMPLEX_X2
53  virtual void PushStateVector(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
54  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth)
55 #else
56  virtual void PushStateVector(
57  const complex* mtrx, QBdtNodeInterfacePtr& b0, QBdtNodeInterfacePtr& b1, bitLenInt depth)
58 #endif
59 #endif
60  {
61  throw std::out_of_range("QBdtNodeInterface::PushStateVector() not implemented! (You probably set "
62  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
63  }
64 
67 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
68  std::mutex mtx;
69 #endif
70 
72  : scale(ONE_CMPLX)
73  {
74  branches[0U] = NULL;
75  branches[1U] = NULL;
76  }
77 
79  : scale(scl)
80  {
81  branches[0U] = NULL;
82  branches[1U] = NULL;
83  }
84 
86  : scale(scl)
87  {
88  branches[0U] = b[0U];
89  branches[1U] = b[1U];
90  }
91 
93  {
94  // Virtual destructor for inheritance
95  }
96 
97 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
98  virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt& size, bitLenInt parDepth = 1U)
99 #else
100  virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt& size)
101 #endif
102  {
103  throw std::out_of_range("QBdtNodeInterface::InsertAtDepth() not implemented! (You probably set "
104  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
105  }
106 
107 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
109  bitLenInt depth, const bitLenInt& size, bitLenInt parDepth = 1U);
110 #else
112 #endif
113 
114  virtual void SetZero()
115  {
116  scale = ZERO_CMPLX;
117 
118 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
119  if (branches[0U]) {
121  std::lock_guard<std::mutex> lock(b0->mtx);
122  branches[0U] = NULL;
123  }
124 
125  if (branches[1U]) {
127  std::lock_guard<std::mutex> lock(b1->mtx);
128  branches[1U] = NULL;
129  }
130 #else
131  branches[0U] = NULL;
132  branches[1U] = NULL;
133 #endif
134  }
135 
136  virtual bool isEqual(QBdtNodeInterfacePtr r);
137 
138  virtual bool isEqualUnder(QBdtNodeInterfacePtr r);
139 
140  virtual bool isEqualBranch(QBdtNodeInterfacePtr r, const bool& b);
141 
143  {
144  throw std::out_of_range("QBdtNodeInterface::ShallowClone() not implemented! (You probably set "
145  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
146  }
147 
148 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
149  virtual void PopStateVector(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
150 #else
151  virtual void PopStateVector(bitLenInt depth = 1U)
152 #endif
153  {
154  if (!depth) {
155  return;
156  }
157 
158  throw std::out_of_range("QBdtNodeInterface::PopStateVector() not implemented! (You probably set "
159  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
160  }
161 
162 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
163  virtual void Branch(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
164 #else
165  virtual void Branch(bitLenInt depth = 1U)
166 #endif
167  {
168  if (!depth) {
169  return;
170  }
171 
172  throw std::out_of_range("QBdtNodeInterface::Branch() not implemented! (You probably set "
173  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
174  }
175 
176 #if ENABLE_QBDT_CPU_PARALLEL && ENABLE_PTHREAD
177  virtual void Prune(bitLenInt depth = 1U, bitLenInt parDepth = 1U)
178 #else
179  virtual void Prune(bitLenInt depth = 1U)
180 #endif
181  {
182  if (!depth) {
183  return;
184  }
185 
186  throw std::out_of_range("QBdtNodeInterface::Prune() not implemented! (You probably set "
187  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
188  }
189 
190  virtual void Normalize(bitLenInt depth = 1U)
191  {
192  if (!depth) {
193  return;
194  }
195 
196  throw std::out_of_range("QBdtNodeInterface::Normalize() not implemented! (You probably set "
197  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
198  }
199 
200 #if ENABLE_COMPLEX_X2
201  virtual void Apply2x2(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
202  const complex2& mtrxColShuff2, bitLenInt depth)
203 #else
204  virtual void Apply2x2(const complex* mtrx, bitLenInt depth)
205 #endif
206  {
207  if (!depth) {
208  return;
209  }
210 
211  throw std::out_of_range("QBdtNodeInterface::Apply2x2() not implemented! (You probably set "
212  "QRACK_QBDT_SEPARABILITY_THRESHOLD too high.)");
213  }
214 
215 #if ENABLE_COMPLEX_X2
216  virtual void PushSpecial(const complex2& mtrxCol1, const complex2& mtrxCol2, const complex2& mtrxColShuff1,
217  const complex2& mtrxColShuff2, QBdtNodeInterfacePtr& b1)
218 #else
219  virtual void PushSpecial(const complex* mtrx, QBdtNodeInterfacePtr& b1)
220 #endif
221  {
222  throw std::out_of_range("QBdtNodeInterface::PushSpecial() not implemented! (You probably called "
223  "PushStateVector() past terminal depth.)");
224  }
225 };
226 
229 } // namespace Qrack
int bi_and_1(const BigInteger &left)
Definition: big_integer.hpp:400
Definition: qbdt_node_interface.hpp:36
virtual void Normalize(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:190
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 PopStateVector(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:151
virtual ~QBdtNodeInterface()
Definition: qbdt_node_interface.hpp:92
virtual void Branch(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:165
virtual QBdtNodeInterfacePtr ShallowClone()
Definition: qbdt_node_interface.hpp:142
virtual void Apply2x2(const complex *mtrx, bitLenInt depth)
Definition: qbdt_node_interface.hpp:204
virtual void SetZero()
Definition: qbdt_node_interface.hpp:114
QBdtNodeInterface()
Definition: qbdt_node_interface.hpp:71
virtual void InsertAtDepth(QBdtNodeInterfacePtr b, bitLenInt depth, const bitLenInt &size)
Definition: qbdt_node_interface.hpp:100
QBdtNodeInterfacePtr branches[2U]
Definition: qbdt_node_interface.hpp:66
complex scale
Definition: qbdt_node_interface.hpp:65
QBdtNodeInterface(const complex &scl)
Definition: qbdt_node_interface.hpp:78
virtual void Prune(bitLenInt depth=1U)
Definition: qbdt_node_interface.hpp:179
virtual bool isEqualBranch(QBdtNodeInterfacePtr r, const bool &b)
Definition: node_interface.cpp:66
QBdtNodeInterface(const complex &scl, QBdtNodeInterfacePtr *b)
Definition: qbdt_node_interface.hpp:85
virtual void PushSpecial(const complex *mtrx, QBdtNodeInterfacePtr &b1)
Definition: qbdt_node_interface.hpp:219
static size_t SelectBit(bitCapInt perm, bitLenInt bit)
Definition: qbdt_node_interface.hpp:38
static void _par_for_qbdt(const bitCapInt &end, BdtFunc fn)
Definition: node_interface.cpp:177
virtual void PushStateVector(const complex *mtrx, QBdtNodeInterfacePtr &b0, QBdtNodeInterfacePtr &b1, bitLenInt depth)
Definition: qbdt_node_interface.hpp:56
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: qrack_types.hpp:138
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:1143
std::complex< real1 > complex
Definition: qrack_types.hpp:128
bool operator==(QBdtNodeInterfacePtr lhs, QBdtNodeInterfacePtr rhs)
Definition: node_interface.cpp:37
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:252
bool operator!=(QBdtNodeInterfacePtr lhs, QBdtNodeInterfacePtr rhs)
Definition: node_interface.cpp:46
std::shared_ptr< QBdtNodeInterface > QBdtNodeInterfacePtr
Definition: qbdt_node_interface.hpp:33
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:253
#define bitLenInt
Definition: qrack_types.hpp:38
#define bitCapInt
Definition: qrack_types.hpp:62
SIMD implementation of the double precision complex vector type of 2 complex numbers,...
Definition: complex16x2simd.hpp:30