Qrack  9.0
General classical-emulating-quantum development framework
qbdt.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 
19 #include "mpsshard.hpp"
20 #include "qbdt_node.hpp"
21 #include "qengine.hpp"
22 
23 #define QINTERFACE_TO_QALU(qReg) std::dynamic_pointer_cast<QAlu>(qReg)
24 #define QINTERFACE_TO_QPARITY(qReg) std::dynamic_pointer_cast<QParity>(qReg)
25 
26 namespace Qrack {
27 
28 class QBdt;
29 typedef std::shared_ptr<QBdt> QBdtPtr;
30 
31 #if ENABLE_ALU
32 class QBdt : public QAlu, public QParity, public QInterface {
33 #else
34 class QBdt : public QParity, public QInterface {
35 #endif
36 protected:
38  int64_t devID;
41  std::vector<int64_t> deviceIDs;
42  std::vector<QInterfaceEngine> engines;
43  std::vector<MpsShardPtr> shards;
44 
45  void DumpBuffers()
46  {
47  for (size_t i = 0; i < shards.size(); ++i) {
48  shards[i] = NULL;
49  }
50  }
52  {
53  const MpsShardPtr shard = shards[t];
54  if (shard) {
55  shards[t] = NULL;
56  ApplySingle(shard->gate, t);
57  }
58  }
59  void FlushBuffers()
60  {
61  for (size_t i = 0U; i < shards.size(); ++i) {
62  FlushBuffer(i);
63  }
64  }
65  void FlushIfBlocked(bitLenInt target, const std::vector<bitLenInt>& controls = std::vector<bitLenInt>())
66  {
67  FlushIfBlocked(controls);
68  FlushBuffer(target);
69  }
70  void FlushIfBlocked(const std::vector<bitLenInt>& controls)
71  {
72  for (const bitLenInt& control : controls) {
73  const MpsShardPtr shard = shards[control];
74  if (shard && !shard->IsPhase()) {
75  shards[control] = NULL;
76  ApplySingle(shard->gate, control);
77  }
78  }
79  }
81  {
82  for (size_t i = 0U; i < shards.size(); ++i) {
83  const MpsShardPtr shard = shards[i];
84  if (shard && !shard->IsPhase()) {
85  shards[i] = NULL;
86  ApplySingle(shard->gate, i);
87  }
88  }
89  }
90 
91  QEnginePtr MakeQEngine(bitLenInt qbCount, bitCapInt perm = 0U);
92 
93  template <typename Fn> void GetTraversal(Fn getLambda)
94  {
95  FlushBuffers();
96 
97  for (bitCapInt i = 0U; i < maxQPower; ++i) {
99  complex scale = leaf->scale;
100  for (bitLenInt j = 0U; j < qubitCount; ++j) {
101  if (norm(leaf->scale) <= _qrack_qbdt_sep_thresh) {
102  break;
103  }
104  leaf = leaf->branches[SelectBit(i, j)];
105  scale *= leaf->scale;
106  }
107 
108  getLambda((bitCapIntOcl)i, scale);
109  }
110  }
111  template <typename Fn> void SetTraversal(Fn setLambda)
112  {
113  DumpBuffers();
114 
115  root = std::make_shared<QBdtNode>();
116  root->Branch(qubitCount);
117 
118  _par_for(maxQPower, [&](const bitCapInt& i, const unsigned& cpu) {
119  QBdtNodeInterfacePtr prevLeaf = root;
120  QBdtNodeInterfacePtr leaf = root;
121  for (bitLenInt j = 0U; j < qubitCount; ++j) {
122  prevLeaf = leaf;
123  leaf = leaf->branches[SelectBit(i, j)];
124  }
125 
126  setLambda((bitCapIntOcl)i, leaf);
127  });
128 
129  root->PopStateVector(qubitCount);
130  root->Prune(qubitCount);
131  }
132  template <typename Fn> void ExecuteAsStateVector(Fn operation)
133  {
135  GetQuantumState(qReg);
136  operation(qReg);
137  SetQuantumState(qReg);
138  }
139 
140  template <typename Fn> bitCapInt BitCapIntAsStateVector(Fn operation)
141  {
143  GetQuantumState(qReg);
144  const bitCapInt toRet = operation(qReg);
145  SetQuantumState(qReg);
146 
147  return toRet;
148  }
149 
150  void par_for_qbdt(const bitCapInt& end, bitLenInt maxQubit, BdtFunc fn, bool branch = true);
151  void _par_for(const bitCapInt& end, ParallelFuncBdt fn);
152 
153  void DecomposeDispose(bitLenInt start, bitLenInt length, QBdtPtr dest);
154 
155  void ApplyControlledSingle(const complex* mtrx, std::vector<bitLenInt> controls, bitLenInt target, bool isAnti);
156 
157  static size_t SelectBit(bitCapInt perm, bitLenInt bit) { return (size_t)((perm >> bit) & 1U); }
158 
160  {
161  bitCapInt mask = power - ONE_BCI;
162  return (perm & mask) | ((perm >> ONE_BCI) & ~mask);
163  }
164 
165  void ApplySingle(const complex* mtrx, bitLenInt target);
166 
167  void Init();
168 
169 public:
170  QBdt(std::vector<QInterfaceEngine> eng, bitLenInt qBitCount, bitCapInt initState = 0,
171  qrack_rand_gen_ptr rgp = nullptr, complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false,
172  bool randomGlobalPhase = true, bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true,
173  bool useSparseStateVec = false, real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> ignored = {},
174  bitLenInt qubitThreshold = 0, real1_f separation_thresh = FP_NORM_EPSILON_F);
175 
176  QBdt(bitLenInt qBitCount, bitCapInt initState = 0U, qrack_rand_gen_ptr rgp = nullptr,
177  complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
178  bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true, bool useSparseStateVec = false,
179  real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devList = {}, bitLenInt qubitThreshold = 0U,
180  real1_f separation_thresh = FP_NORM_EPSILON_F)
181  : QBdt({ QINTERFACE_OPTIMAL_BASE }, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase, useHostMem,
182  deviceId, useHardwareRNG, useSparseStateVec, norm_thresh, devList, qubitThreshold, separation_thresh)
183  {
184  }
185 
186  size_t CountBranches();
187 
188  bool isBinaryDecisionTree() { return true; };
189 
190  void SetDevice(int64_t dID) { devID = dID; }
191 
193  {
194  // Intentionally left blank.
195  }
196 
198  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
199  {
200  root->Normalize(qubitCount);
201  }
202 
203  real1_f SumSqrDiff(QInterfacePtr toCompare) { return SumSqrDiff(std::dynamic_pointer_cast<QBdt>(toCompare)); }
204  real1_f SumSqrDiff(QBdtPtr toCompare);
205 
206  void SetPermutation(bitCapInt initState, complex phaseFac = CMPLX_DEFAULT_ARG);
207 
209 
211  {
212  GetTraversal([state](bitCapIntOcl i, complex scale) { state[i] = scale; });
213  }
215  {
216  GetTraversal([eng](bitCapIntOcl i, complex scale) { eng->SetAmplitude(i, scale); });
217  }
218  void SetQuantumState(const complex* state)
219  {
220  SetTraversal([state](bitCapIntOcl i, QBdtNodeInterfacePtr leaf) { leaf->scale = state[i]; });
221  }
223  {
224  SetTraversal([eng](bitCapIntOcl i, QBdtNodeInterfacePtr leaf) { leaf->scale = eng->GetAmplitude(i); });
225  }
226  void GetProbs(real1* outputProbs)
227  {
228  GetTraversal([outputProbs](bitCapIntOcl i, complex scale) { outputProbs[i] = norm(scale); });
229  }
230 
233  {
234  ExecuteAsStateVector([&](QInterfacePtr eng) { eng->SetAmplitude(perm, amp); });
235  }
236 
237  using QInterface::Compose;
238  bitLenInt Compose(QBdtPtr toCopy, bitLenInt start);
240  {
241  return Compose(std::dynamic_pointer_cast<QBdt>(toCopy), start);
242  }
244  {
245  QBdtPtr d = std::dynamic_pointer_cast<QBdt>(dest);
246  DecomposeDispose(start, dest->GetQubitCount(), d);
247  }
249  void Dispose(bitLenInt start, bitLenInt length) { DecomposeDispose(start, length, NULL); }
250 
251  void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm)
252  {
253  ForceMReg(start, length, disposedPerm);
254  DecomposeDispose(start, length, NULL);
255  }
256 
257  using QInterface::Allocate;
258  bitLenInt Allocate(bitLenInt start, bitLenInt length);
259 
260  real1_f Prob(bitLenInt qubitIndex);
261  real1_f ProbAll(bitCapInt fullRegister);
262 
263  bool ForceM(bitLenInt qubit, bool result, bool doForce = true, bool doApply = true);
264  bitCapInt MAll();
265 
266  void Mtrx(const complex* mtrx, bitLenInt target);
267  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target);
268  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target);
269  void MCPhase(const std::vector<bitLenInt>& controls, complex topLeft, complex bottomRight, bitLenInt target);
270  void MCInvert(const std::vector<bitLenInt>& controls, complex topRight, complex bottomLeft, bitLenInt target);
271 
272  void FSim(real1_f theta, real1_f phi, bitLenInt qubitIndex1, bitLenInt qubitIndex2);
273 
274  void Swap(bitLenInt q1, bitLenInt q2)
275  {
276  if (q2 < q1) {
277  std::swap(q1, q2);
278  }
279  QInterface::Swap(q1, q2);
280  }
281  void ISwap(bitLenInt q1, bitLenInt q2)
282  {
283  if (q2 < q1) {
284  std::swap(q1, q2);
285  }
286  QInterface::ISwap(q1, q2);
287  }
289  {
290  if (q2 < q1) {
291  std::swap(q1, q2);
292  }
293  QInterface::IISwap(q1, q2);
294  }
296  {
297  if (q2 < q1) {
298  std::swap(q1, q2);
299  }
300  QInterface::SqrtSwap(q1, q2);
301  }
303  {
304  if (q2 < q1) {
305  std::swap(q1, q2);
306  }
307  QInterface::ISqrtSwap(q1, q2);
308  }
309  void CSwap(const std::vector<bitLenInt>& controls, bitLenInt q1, bitLenInt q2)
310  {
311  if (q2 < q1) {
312  std::swap(q1, q2);
313  }
314  QInterface::CSwap(controls, q1, q2);
315  }
316  void CSqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt q1, bitLenInt q2)
317  {
318  if (q2 < q1) {
319  std::swap(q1, q2);
320  }
321  QInterface::CSqrtSwap(controls, q1, q2);
322  }
323  void CISqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt q1, bitLenInt q2)
324  {
325  if (q2 < q1) {
326  std::swap(q1, q2);
327  }
328  QInterface::CISqrtSwap(controls, q1, q2);
329  }
330 
332  {
333  if (!mask) {
334  return ZERO_R1_F;
335  }
336 
337  if (!(mask & (mask - ONE_BCI))) {
338  return Prob(log2(mask));
339  }
340 
341  real1_f toRet;
342  ExecuteAsStateVector([&](QInterfacePtr eng) { toRet = QINTERFACE_TO_QPARITY(eng)->ProbParity(mask); });
343 
344  return toRet;
345  }
346  void CUniformParityRZ(const std::vector<bitLenInt>& controls, bitCapInt mask, real1_f angle)
347  {
349  [&](QInterfacePtr eng) { QINTERFACE_TO_QPARITY(eng)->CUniformParityRZ(controls, mask, angle); });
350  }
351  bool ForceMParity(bitCapInt mask, bool result, bool doForce = true)
352  {
353  // If no bits in mask:
354  if (!mask) {
355  return false;
356  }
357 
358  // If only one bit in mask:
359  if (!(mask & (mask - ONE_BCI))) {
360  return ForceM(log2(mask), result, doForce);
361  }
362 
363  bool toRet;
365  [&](QInterfacePtr eng) { toRet = QINTERFACE_TO_QPARITY(eng)->ForceMParity(mask, result, doForce); });
366 
367  return toRet;
368  }
369 
370 #if ENABLE_ALU
371  using QInterface::M;
372  bool M(bitLenInt q) { return QInterface::M(q); }
373  using QInterface::X;
374  void X(bitLenInt q) { QInterface::X(q); }
375  void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length) { QInterface::INC(toAdd, start, length); }
376  void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length) { QInterface::DEC(toSub, start, length); }
377  void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
378  {
379  QInterface::INCC(toAdd, start, length, carryIndex);
380  }
381  void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
382  {
383  QInterface::DECC(toSub, start, length, carryIndex);
384  }
385  void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
386  {
387  QInterface::INCS(toAdd, start, length, overflowIndex);
388  }
389  void DECS(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
390  {
391  QInterface::DECS(toSub, start, length, overflowIndex);
392  }
393  void CINC(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
394  {
395  QInterface::CINC(toAdd, inOutStart, length, controls);
396  }
397  void CDEC(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
398  {
399  QInterface::CDEC(toSub, inOutStart, length, controls);
400  }
401  void INCDECC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
402  {
403  QInterface::INCDECC(toAdd, start, length, carryIndex);
404  }
405  void MULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
406  {
407  QInterface::MULModNOut(toMul, modN, inStart, outStart, length);
408  }
409  void IMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
410  {
411  QInterface::IMULModNOut(toMul, modN, inStart, outStart, length);
412  }
413  void CMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
414  const std::vector<bitLenInt>& controls)
415  {
416  QInterface::CMULModNOut(toMul, modN, inStart, outStart, length, controls);
417  }
418  void CIMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
419  const std::vector<bitLenInt>& controls)
420  {
421  QInterface::CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
422  }
423  void PhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length)
424  {
426  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->PhaseFlipIfLess(greaterPerm, start, length); });
427  }
428  void CPhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
429  {
431  QINTERFACE_TO_QALU(eng)->CPhaseFlipIfLess(greaterPerm, start, length, flagIndex);
432  });
433  }
434  void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
435  {
437  QINTERFACE_TO_QALU(eng)->INCDECSC(toAdd, start, length, overflowIndex, carryIndex);
438  });
439  }
440  void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
441  {
443  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->INCDECSC(toAdd, start, length, carryIndex); });
444  }
445 #if ENABLE_BCD
446  void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
447  {
448  ExecuteAsStateVector([&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->INCBCD(toAdd, start, length); });
449  }
450  void INCDECBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
451  {
453  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->INCDECBCDC(toAdd, start, length, carryIndex); });
454  }
455 #endif
456  void MUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
457  {
459  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->MUL(toMul, inOutStart, carryStart, length); });
460  }
461  void DIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
462  {
464  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->DIV(toDiv, inOutStart, carryStart, length); });
465  }
466  void POWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
467  {
469  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->POWModNOut(base, modN, inStart, outStart, length); });
470  }
471  void CMUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
472  const std::vector<bitLenInt>& controls)
473  {
475  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->CMUL(toMul, inOutStart, carryStart, length, controls); });
476  }
477  void CDIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
478  const std::vector<bitLenInt>& controls)
479  {
481  [&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->CDIV(toDiv, inOutStart, carryStart, length, controls); });
482  }
483  void CPOWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
484  const std::vector<bitLenInt>& controls)
485  {
487  QINTERFACE_TO_QALU(eng)->CPOWModNOut(base, modN, inStart, outStart, length, controls);
488  });
489  }
490  bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
491  const unsigned char* values, bool resetValue = true)
492  {
493  return BitCapIntAsStateVector([&](QInterfacePtr eng) {
494  return QINTERFACE_TO_QALU(eng)->IndexedLDA(
495  indexStart, indexLength, valueStart, valueLength, values, resetValue);
496  });
497  }
498  bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
499  bitLenInt carryIndex, const unsigned char* values)
500  {
501  return BitCapIntAsStateVector([&](QInterfacePtr eng) {
502  return QINTERFACE_TO_QALU(eng)->IndexedADC(
503  indexStart, indexLength, valueStart, valueLength, carryIndex, values);
504  });
505  }
506  bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
507  bitLenInt carryIndex, const unsigned char* values)
508  {
509  return BitCapIntAsStateVector([&](QInterfacePtr eng) {
510  return QINTERFACE_TO_QALU(eng)->IndexedSBC(
511  indexStart, indexLength, valueStart, valueLength, carryIndex, values);
512  });
513  }
514  void Hash(bitLenInt start, bitLenInt length, const unsigned char* values)
515  {
516  ExecuteAsStateVector([&](QInterfacePtr eng) { QINTERFACE_TO_QALU(eng)->Hash(start, length, values); });
517  }
518 #endif
519 };
520 } // namespace Qrack
Definition: qalu.hpp:22
Definition: qbdt.hpp:32
void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: qbdt.hpp:377
QEnginePtr MakeQEngine(bitLenInt qbCount, bitCapInt perm=0U)
Definition: tree.cpp:63
void MCMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: tree.cpp:716
bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, const unsigned char *values)
Add to entangled 8 bit register state with a superposed index-offset-based read from classical memory...
Definition: qbdt.hpp:498
void SetAmplitude(bitCapInt perm, complex amp)
Sets the representational amplitude of a full permutation.
Definition: qbdt.hpp:232
complex GetAmplitude(bitCapInt perm)
Get the representational amplitude of a full permutation.
Definition: tree.cpp:303
void CINC(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: qbdt.hpp:393
void CPOWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled, raise a classical base to a quantum power, modulo N, (out of place)
Definition: qbdt.hpp:483
void PhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length)
This is an expedient for an adaptive Grover's search for a function's global minimum.
Definition: qbdt.hpp:423
void CMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled multiplication modulo N by integer, (out of place)
Definition: qbdt.hpp:413
void SetQuantumState(QInterfacePtr eng)
Definition: qbdt.hpp:222
void NormalizeState(real1_f nrm=REAL1_DEFAULT_ARG, real1_f norm_thresh=REAL1_DEFAULT_ARG, real1_f phaseArg=ZERO_R1_F)
Apply the normalization factor found by UpdateRunningNorm() or on the fly by a single bit gate.
Definition: qbdt.hpp:197
void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qbdt.hpp:385
QBdt(std::vector< QInterfaceEngine > eng, bitLenInt qBitCount, bitCapInt initState=0, qrack_rand_gen_ptr rgp=nullptr, complex phaseFac=CMPLX_DEFAULT_ARG, bool doNorm=false, bool randomGlobalPhase=true, bool useHostMem=false, int64_t deviceId=-1, bool useHardwareRNG=true, bool useSparseStateVec=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > ignored={}, bitLenInt qubitThreshold=0, real1_f separation_thresh=FP_NORM_EPSILON_F)
Definition: tree.cpp:24
void ISqrtSwap(bitLenInt q1, bitLenInt q2)
Inverse square root of Swap gate.
Definition: qbdt.hpp:302
void ISwap(bitLenInt q1, bitLenInt q2)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: qbdt.hpp:281
virtual bitLenInt Allocate(bitLenInt length)
Allocate new "length" count of |0> state qubits at end of qubit index position.
Definition: qinterface.hpp:434
void ApplyControlledSingle(const complex *mtrx, std::vector< bitLenInt > controls, bitLenInt target, bool isAnti)
Definition: tree.cpp:623
void IMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Inverse of multiplication modulo N by integer, (out of place)
Definition: qbdt.hpp:409
bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, const unsigned char *values, bool resetValue=true)
Set 8 bit register bits by a superposed index-offset-based read from classical memory.
Definition: qbdt.hpp:490
void INCDECC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCC and DECC (without sign, with carry)
Definition: qbdt.hpp:401
void CMUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled multiplication by integer.
Definition: qbdt.hpp:471
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:338
bitCapInt bdtMaxQPower
Definition: qbdt.hpp:40
real1_f Prob(bitLenInt qubitIndex)
Direct measure of bit probability to be in |1> state.
Definition: tree.cpp:400
size_t CountBranches()
Definition: tree.cpp:195
void Init()
Definition: tree.cpp:40
int64_t devID
Definition: qbdt.hpp:38
bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: tree.cpp:528
void DecomposeDispose(bitLenInt start, bitLenInt length, QBdtPtr dest)
Definition: tree.cpp:360
void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (with overflow flag)
Definition: qbdt.hpp:434
void INCDECBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (without overflow flag)
Definition: qbdt.hpp:450
void DumpBuffers()
Definition: qbdt.hpp:45
void CUniformParityRZ(const std::vector< bitLenInt > &controls, bitCapInt mask, real1_f angle)
If the controls are set and the target qubit set parity is odd, this applies a phase factor of .
Definition: qbdt.hpp:346
std::vector< MpsShardPtr > shards
Definition: qbdt.hpp:43
void Mtrx(const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation.
Definition: tree.cpp:706
void CISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt q1, bitLenInt q2)
Apply an inverse square root of swap with arbitrary control bits.
Definition: qbdt.hpp:323
void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qbdt.hpp:376
void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qbdt.hpp:251
std::vector< int64_t > deviceIDs
Definition: qbdt.hpp:41
void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qbdt.hpp:249
void CDEC(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Subtract integer (without sign, with controls)
Definition: qbdt.hpp:397
static bitCapInt RemovePower(bitCapInt perm, bitCapInt power)
Definition: qbdt.hpp:159
void FSim(real1_f theta, real1_f phi, bitLenInt qubitIndex1, bitLenInt qubitIndex2)
The 2-qubit "fSim" gate, (useful in the simulation of particles with fermionic statistics)
Definition: tree.cpp:805
real1_f ProbParity(bitCapInt mask)
Overall probability of any odd permutation of the masked set of bits.
Definition: qbdt.hpp:331
void Swap(bitLenInt q1, bitLenInt q2)
Swap values of two bits in register.
Definition: qbdt.hpp:274
void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qbdt.hpp:190
void GetTraversal(Fn getLambda)
Definition: qbdt.hpp:93
void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract classical integer (without sign, with carry)
Definition: qbdt.hpp:381
void MCPhase(const std::vector< bitLenInt > &controls, complex topLeft, complex bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase, with arbitrary control bits.
Definition: tree.cpp:747
void CSwap(const std::vector< bitLenInt > &controls, bitLenInt q1, bitLenInt q2)
Apply a swap with arbitrary control bits.
Definition: qbdt.hpp:309
void POWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Raise a classical base to a quantum power, modulo N, (out of place)
Definition: qbdt.hpp:466
void par_for_qbdt(const bitCapInt &end, bitLenInt maxQubit, BdtFunc fn, bool branch=true)
Definition: tree.cpp:69
void DIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Divide by integer.
Definition: qbdt.hpp:461
void FlushBuffer(bitLenInt t)
Definition: qbdt.hpp:51
real1_f SumSqrDiff(QInterfacePtr toCompare)
Definition: qbdt.hpp:203
void ApplySingle(const complex *mtrx, bitLenInt target)
Definition: tree.cpp:570
void SetTraversal(Fn setLambda)
Definition: qbdt.hpp:111
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Definition: qbdt.hpp:239
void FlushNonPhaseBuffers()
Definition: qbdt.hpp:80
void CIMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Inverse of controlled multiplication modulo N by integer, (out of place)
Definition: qbdt.hpp:418
void CPhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
The 6502 uses its carry flag also as a greater-than/less-than flag, for the CMP operation.
Definition: qbdt.hpp:428
void GetQuantumState(QInterfacePtr eng)
Definition: qbdt.hpp:214
bitCapInt BitCapIntAsStateVector(Fn operation)
Definition: qbdt.hpp:140
bool M(bitLenInt q)
Definition: qbdt.hpp:372
void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qbdt.hpp:375
bool ForceMParity(bitCapInt mask, bool result, bool doForce=true)
Act as if is a measurement of parity of the masked set of qubits was applied, except force the (usual...
Definition: qbdt.hpp:351
void SetQuantumState(const complex *state)
Set an arbitrary pure quantum state representation.
Definition: qbdt.hpp:218
void MULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Multiplication modulo N by integer, (out of place)
Definition: qbdt.hpp:405
void FlushBuffers()
Definition: qbdt.hpp:59
bool ForceM(bitLenInt qubit, bool result, bool doForce=true, bool doApply=true)
Act as if is a measurement was applied, except force the (usually random) result.
Definition: tree.cpp:461
void Hash(bitLenInt start, bitLenInt length, const unsigned char *values)
Transform a length of qubit register via lookup through a hash table.
Definition: qbdt.hpp:514
void GetProbs(real1 *outputProbs)
Get the pure quantum state representation.
Definition: qbdt.hpp:226
void UpdateRunningNorm(real1_f norm_thresh=REAL1_DEFAULT_ARG)
Force a calculation of the norm of the state vector, in order to make it unit length before the next ...
Definition: qbdt.hpp:192
void IISwap(bitLenInt q1, bitLenInt q2)
Inverse ISwap - Swap values of two bits in register, and apply phase factor of -i if bits are differe...
Definition: qbdt.hpp:288
void SqrtSwap(bitLenInt q1, bitLenInt q2)
Square root of Swap gate.
Definition: qbdt.hpp:295
void _par_for(const bitCapInt &end, ParallelFuncBdt fn)
Definition: tree.cpp:144
void FlushIfBlocked(const std::vector< bitLenInt > &controls)
Definition: qbdt.hpp:70
bool isBinaryDecisionTree()
Returns "true" if current state representation is definitely a binary decision tree,...
Definition: qbdt.hpp:188
void CSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt q1, bitLenInt q2)
Apply a square root of swap with arbitrary control bits.
Definition: qbdt.hpp:316
void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (without overflow flag)
Definition: qbdt.hpp:440
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qbdt.hpp:243
std::vector< QInterfaceEngine > engines
Definition: qbdt.hpp:42
QBdt(bitLenInt qBitCount, bitCapInt initState=0U, qrack_rand_gen_ptr rgp=nullptr, complex phaseFac=CMPLX_DEFAULT_ARG, bool doNorm=false, bool randomGlobalPhase=true, bool useHostMem=false, int64_t deviceId=-1, bool useHardwareRNG=true, bool useSparseStateVec=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > devList={}, bitLenInt qubitThreshold=0U, real1_f separation_thresh=FP_NORM_EPSILON_F)
Definition: qbdt.hpp:176
void MCInvert(const std::vector< bitLenInt > &controls, complex topRight, complex bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: tree.cpp:775
void ExecuteAsStateVector(Fn operation)
Definition: qbdt.hpp:132
void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add classical BCD integer (without sign)
Definition: qbdt.hpp:446
void X(bitLenInt q)
Definition: qbdt.hpp:374
void SetPermutation(bitCapInt initState, complex phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: tree.cpp:223
void GetQuantumState(complex *state)
Get the pure quantum state representation.
Definition: qbdt.hpp:210
bitLenInt bdtStride
Definition: qbdt.hpp:37
QInterfacePtr Clone()
Clone this QInterface.
Definition: tree.cpp:250
void CDIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled division by power of integer.
Definition: qbdt.hpp:477
static size_t SelectBit(bitCapInt perm, bitLenInt bit)
Definition: qbdt.hpp:157
QBdtNodeInterfacePtr root
Definition: qbdt.hpp:39
void MUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Multiply by integer.
Definition: qbdt.hpp:456
void DECS(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qbdt.hpp:389
void MACMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
Definition: tree.cpp:731
bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, const unsigned char *values)
Subtract from an entangled 8 bit register state with a superposed index-offset-based read from classi...
Definition: qbdt.hpp:506
void FlushIfBlocked(bitLenInt target, const std::vector< bitLenInt > &controls=std::vector< bitLenInt >())
Definition: qbdt.hpp:65
real1_f ProbAll(bitCapInt fullRegister)
Direct measure of full permutation probability.
Definition: tree.cpp:443
A "Qrack::QInterface" is an abstract interface exposing qubit permutation state vector with methods t...
Definition: qinterface.hpp:146
bitCapInt maxQPower
Definition: qinterface.hpp:154
virtual bitLenInt Allocate(bitLenInt length)
Allocate new "length" count of |0> state qubits at end of qubit index position.
Definition: qinterface.hpp:434
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:338
bitLenInt qubitCount
Definition: qinterface.hpp:151
Definition: qparity.hpp:22
Half-precision floating-point type.
Definition: half.hpp:2222
virtual void CMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled multiplication modulo N by integer, (out of place)
Definition: arithmetic.cpp:259
virtual void CIMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Inverse of controlled multiplication modulo N by integer, (out of place)
Definition: arithmetic.cpp:296
virtual void INCDECC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCC and DECC.
Definition: arithmetic.cpp:63
virtual void IMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Inverse of multiplication modulo N by integer, (out of place)
Definition: arithmetic.cpp:226
virtual void CINC(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: arithmetic.cpp:114
virtual void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: arithmetic.cpp:88
virtual void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract classical integer (without sign, with carry)
Definition: arithmetic.cpp:100
virtual void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: arithmetic.cpp:167
virtual void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
Subtract classical integer (without sign)
Definition: arithmetic.cpp:57
virtual void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: arithmetic.cpp:24
virtual void DECS(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Subtract a classical integer from the register, with sign and without carry.
Definition: arithmetic.cpp:182
virtual void MULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Multiplication modulo N by integer, (out of place)
Definition: arithmetic.cpp:191
virtual void CDEC(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Subtract classical integer (without sign, with controls)
Definition: arithmetic.cpp:160
virtual void CSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a square root of swap with arbitrary control bits.
Definition: gates.cpp:270
virtual bool M(bitLenInt qubitIndex)
Measurement gate.
Definition: qinterface.hpp:976
virtual void CISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply an inverse square root of swap with arbitrary control bits.
Definition: gates.cpp:320
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1054
virtual void U(bitLenInt target, real1_f theta, real1_f phi, real1_f lambda)
General unitary gate.
Definition: rotational.cpp:18
virtual void CSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a swap with arbitrary control bits.
Definition: gates.cpp:234
virtual void ISqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Inverse square root of Swap gate.
Definition: gates.cpp:211
virtual bitCapInt ForceMReg(bitLenInt start, bitLenInt length, bitCapInt result, bool doForce=true, bool doApply=true)
Act as if is a measurement was applied, except force the (usually random) result.
Definition: qinterface.cpp:212
virtual void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register.
Definition: gates.cpp:153
virtual void IISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Inverse ISwap - Swap values of two bits in register, and apply phase factor of -i if bits are differe...
Definition: gates.cpp:176
virtual void ISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: gates.cpp:164
virtual void SqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Square root of Swap gate.
Definition: gates.cpp:188
Definition: complex16x2simd.hpp:25
constexpr uint8_t ONE_BCI
Definition: qrack_types.hpp:90
std::complex< half_float::half > complex
Definition: qrack_types.hpp:62
@ QINTERFACE_OPTIMAL_BASE
Definition: qinterface.hpp:129
std::shared_ptr< QEngine > QEnginePtr
Definition: qrack_types.hpp:141
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:28
constexpr real1_f ZERO_R1_F
Definition: qrack_types.hpp:152
constexpr real1_f FP_NORM_EPSILON_F
Definition: qrack_types.hpp:245
std::shared_ptr< QBdt > QBdtPtr
Definition: qbdt.hpp:28
std::function< bitCapInt(const bitCapInt &)> BdtFunc
Definition: qrack_types.hpp:128
const real1_f _qrack_qbdt_sep_thresh
Definition: qrack_functions.hpp:110
std::function< void(const bitCapInt &, const unsigned &cpu)> ParallelFuncBdt
Definition: qrack_types.hpp:129
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:101
const real1 REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:155
float real1_f
Definition: qrack_types.hpp:64
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:242
std::shared_ptr< MpsShard > MpsShardPtr
Definition: mpsshard.hpp:18
std::shared_ptr< QBdtNodeInterface > QBdtNodeInterfacePtr
Definition: qbdt_node_interface.hpp:33
const real1 REAL1_EPSILON
Definition: qrack_types.hpp:157
bitLenInt log2(bitCapInt n)
Definition: qrack_functions.hpp:26
#define QINTERFACE_TO_QALU(qReg)
Definition: qbdt.hpp:23
#define QINTERFACE_TO_QPARITY(qReg)
Definition: qbdt.hpp:24
#define bitLenInt
Definition: qrack_types.hpp:44
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:146
#define bitCapInt
Definition: qrack_types.hpp:105
#define bitCapIntOcl
Definition: qrack_types.hpp:91