Qrack  9.0
General classical-emulating-quantum development framework
qbdthybrid.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // This is a multithreaded, universal quantum register simulation, allowing
6 // (nonphysical) register cloning and direct measurement of probability and
7 // phase, to leverage what advantages classical emulation of qubits can have.
8 //
9 // Licensed under the GNU Lesser General Public License V3.
10 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
11 // for details.
12 #pragma once
13 
14 #include "qinterface.hpp"
15 
16 namespace Qrack {
17 
18 class QBdtHybrid;
19 typedef std::shared_ptr<QBdtHybrid> QBdtHybridPtr;
20 
25 #if ENABLE_ALU
26 class QBdtHybrid : public QAlu, public QParity, public QInterface {
27 #else
28 class QBdtHybrid : public QParity, public QInterface {
29 #endif
30 protected:
31  bool useRDRAND;
32  bool isSparse;
33  bool useHostRam;
36  int64_t devID;
40  std::vector<int64_t> deviceIDs;
41  std::vector<QInterfaceEngine> engines;
42 
48  void SwitchMode(bool useBdt)
49  {
50  if (!engine == useBdt) {
51  return;
52  }
53 
54  QInterfacePtr nEngine = MakeSimulator(useBdt);
55  std::unique_ptr<complex[]> sv(new complex[(size_t)maxQPower]);
56  if (qbdt) {
57  qbdt->GetQuantumState(sv.get());
58  } else {
59  engine->GetQuantumState(sv.get());
60  }
61  nEngine->SetQuantumState(sv.get());
62  if (useBdt) {
63  qbdt = std::dynamic_pointer_cast<QBdt>(nEngine);
64  engine = NULL;
65  } else {
66  qbdt = NULL;
67  engine = std::dynamic_pointer_cast<QEngine>(nEngine);
68  }
69  }
70 
72  {
73  double threshold = getenv("QRACK_QBDT_HYBRID_THRESHOLD")
74  ? std::log2(qubitCount) * std::stod(getenv("QRACK_QBDT_HYBRID_THRESHOLD"))
75  : (std::log2(qubitCount) / 4);
76  if ((1.0 - threshold) <= FP_NORM_EPSILON) {
77  // This definitely won't switch.
78  return;
79  }
80  const size_t count = qbdt->CountBranches();
81 #if (QBCAPPOW > 6) && BOOST_AVAILABLE
82  if ((threshold * maxQPower.convert_to<double>()) < count) {
83 #else
84  if ((threshold * maxQPower) < count) {
85 #endif
86  SwitchMode(false);
87  }
88  }
89 
90 public:
91  QBdtHybrid(std::vector<QInterfaceEngine> eng, bitLenInt qBitCount, bitCapInt initState = 0U,
92  qrack_rand_gen_ptr rgp = nullptr, complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false,
93  bool randomGlobalPhase = true, bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true,
94  bool useSparseStateVec = false, real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devList = {},
95  bitLenInt qubitThreshold = 0U, real1_f separation_thresh = FP_NORM_EPSILON_F);
96 
97  QBdtHybrid(QBdtPtr q, QEnginePtr e, std::vector<QInterfaceEngine> eng, bitLenInt qBitCount,
98  bitCapInt initState = 0U, qrack_rand_gen_ptr rgp = nullptr, complex phaseFac = CMPLX_DEFAULT_ARG,
99  bool doNorm = false, bool randomGlobalPhase = true, bool useHostMem = false, int64_t deviceId = -1,
100  bool useHardwareRNG = true, bool useSparseStateVec = false, real1_f norm_thresh = REAL1_EPSILON,
101  std::vector<int64_t> devList = {}, bitLenInt qubitThreshold = 0U,
102  real1_f separation_thresh = FP_NORM_EPSILON_F);
103 
104  QBdtHybrid(bitLenInt qBitCount, bitCapInt initState = 0U, qrack_rand_gen_ptr rgp = nullptr,
105  complex phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
106  bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true, bool useSparseStateVec = false,
107  real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devList = {}, bitLenInt qubitThreshold = 0U,
108  real1_f separation_thresh = FP_NORM_EPSILON_F)
109  : QBdtHybrid({ QINTERFACE_OPTIMAL_BASE }, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase,
110  useHostMem, deviceId, useHardwareRNG, useSparseStateVec, norm_thresh, devList, qubitThreshold,
111  separation_thresh)
112  {
113  }
114 
115  QInterfacePtr MakeSimulator(bool isBdt, bitCapInt perm = 0U, complex phaseFac = CMPLX_DEFAULT_ARG);
116 
117  bool isBinaryDecisionTree() { return !engine; }
118 
119  void SetConcurrency(uint32_t threadCount)
120  {
121  QInterface::SetConcurrency(threadCount);
122  if (qbdt) {
123  qbdt->SetConcurrency(GetConcurrencyLevel());
124  } else {
125  engine->SetConcurrency(GetConcurrencyLevel());
126  }
127  }
128 
129  real1_f ProbReg(bitLenInt start, bitLenInt length, bitCapInt permutation)
130  {
131  if (qbdt) {
132  return qbdt->ProbReg(start, length, permutation);
133  }
134  return engine->ProbReg(start, length, permutation);
135  }
136 
137  using QInterface::Compose;
139  {
140  SetQubitCount(qubitCount + toCopy->qubitCount);
141  toCopy->SwitchMode(!engine);
142  if (engine) {
143  return engine->Compose(toCopy->engine);
144  }
145 
146  const bitLenInt toRet = qbdt->Compose(toCopy->qbdt);
147  CheckThreshold();
148 
149  return toRet;
150  }
151  bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QBdtHybrid>(toCopy)); }
153  {
154  SetQubitCount(qubitCount + toCopy->qubitCount);
155  toCopy->SwitchMode(!engine);
156  if (engine) {
157  return engine->Compose(toCopy->engine, start);
158  }
159 
160  const bitLenInt toRet = qbdt->Compose(toCopy->qbdt, start);
161  CheckThreshold();
162 
163  return toRet;
164  }
166  {
167  return Compose(std::dynamic_pointer_cast<QBdtHybrid>(toCopy), start);
168  }
170  {
171  SetQubitCount(qubitCount + toCopy->qubitCount);
172  toCopy->SwitchMode(!engine);
173  if (engine) {
174  return engine->ComposeNoClone(toCopy->engine);
175  }
176 
177  const bitLenInt toRet = qbdt->ComposeNoClone(toCopy->qbdt);
178  CheckThreshold();
179 
180  return toRet;
181  }
183  {
184  return ComposeNoClone(std::dynamic_pointer_cast<QBdtHybrid>(toCopy));
185  }
186  using QInterface::Decompose;
188  {
189  SetQubitCount(qubitCount - length);
190  QBdtPtr q = NULL;
191  QEnginePtr e = NULL;
192  if (qbdt) {
193  q = std::dynamic_pointer_cast<QBdt>(qbdt->Decompose(start, length));
194  CheckThreshold();
195  } else {
196  e = std::dynamic_pointer_cast<QEngine>(engine->Decompose(start, length));
197  }
198 
199  return std::make_shared<QBdtHybrid>(q, e, engines, qubitCount, 0U, rand_generator, phaseFactor, doNormalize,
202  }
204  {
205  Decompose(start, std::dynamic_pointer_cast<QBdtHybrid>(dest));
206  }
208  {
209  return TryDecompose(start, std::dynamic_pointer_cast<QBdtHybrid>(dest), error_tol);
210  }
212  {
213  SwitchMode(false);
214  dest->SwitchMode(false);
215  if (engine->TryDecompose(start, dest->engine, error_tol)) {
216  SetQubitCount(qubitCount - dest->qubitCount);
217  return true;
218  }
219  return false;
220  }
222  {
223  SetQubitCount(qubitCount - dest->qubitCount);
224  dest->SwitchMode(!engine);
225  if (qbdt) {
226  qbdt->Decompose(start, dest->qbdt);
227  CheckThreshold();
228  } else {
229  engine->Decompose(start, dest->engine);
230  }
231  }
232  void Dispose(bitLenInt start, bitLenInt length)
233  {
234  SetQubitCount(qubitCount - length);
235  if (qbdt) {
236  qbdt->Dispose(start, length);
237  CheckThreshold();
238  } else {
239  engine->Dispose(start, length);
240  }
241  }
242  void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm)
243  {
244  SetQubitCount(qubitCount - length);
245  if (qbdt) {
246  qbdt->Dispose(start, length, disposedPerm);
247  CheckThreshold();
248  } else {
249  engine->Dispose(start, length, disposedPerm);
250  }
251  }
252 
253  using QInterface::Allocate;
255  {
256  if (!length) {
257  return start;
258  }
259 
260  if (qbdt) {
261  qbdt->Allocate(start, length);
262  } else {
263  engine->Allocate(start, length);
264  }
265  SetQubitCount(qubitCount + length);
266 
267  return start;
268  }
269 
270  void SetQuantumState(const complex* inputState)
271  {
272  if (qbdt) {
273  qbdt->SetQuantumState(inputState);
274  } else {
275  engine->SetQuantumState(inputState);
276  }
277  }
278  void GetQuantumState(complex* outputState)
279  {
280  if (qbdt) {
281  qbdt->GetQuantumState(outputState);
282  } else {
283  engine->GetQuantumState(outputState);
284  }
285  }
286  void GetProbs(real1* outputProbs)
287  {
288  if (qbdt) {
289  qbdt->GetProbs(outputProbs);
290  } else {
291  engine->GetProbs(outputProbs);
292  }
293  }
295  {
296  if (qbdt) {
297  return qbdt->GetAmplitude(perm);
298  }
299  return engine->GetAmplitude(perm);
300  }
302  {
303  if (qbdt) {
304  qbdt->SetAmplitude(perm, amp);
305  } else {
306  engine->SetAmplitude(perm, amp);
307  }
308  }
310  {
311  if (qbdt) {
312  qbdt->SetPermutation(perm, phaseFac);
313  } else {
314  qbdt = std::dynamic_pointer_cast<QBdt>(MakeSimulator(true, perm, phaseFac));
315  engine = NULL;
316  }
317  }
318 
319  void Mtrx(const complex* mtrx, bitLenInt qubitIndex)
320  {
321  if (qbdt) {
322  qbdt->Mtrx(mtrx, qubitIndex);
323  } else {
324  engine->Mtrx(mtrx, qubitIndex);
325  }
326  }
327  void Phase(complex topLeft, complex bottomRight, bitLenInt qubitIndex)
328  {
329  if (qbdt) {
330  qbdt->Phase(topLeft, bottomRight, qubitIndex);
331  } else {
332  engine->Phase(topLeft, bottomRight, qubitIndex);
333  }
334  }
335  void Invert(complex topRight, complex bottomLeft, bitLenInt qubitIndex)
336  {
337  if (qbdt) {
338  qbdt->Invert(topRight, bottomLeft, qubitIndex);
339  } else {
340  engine->Invert(topRight, bottomLeft, qubitIndex);
341  }
342  }
343  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
344  {
345  if (qbdt) {
346  qbdt->MCMtrx(controls, mtrx, target);
347  CheckThreshold();
348  } else {
349  engine->MCMtrx(controls, mtrx, target);
350  }
351  }
352  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
353  {
354  if (qbdt) {
355  qbdt->MACMtrx(controls, mtrx, target);
356  CheckThreshold();
357  } else {
358  engine->MACMtrx(controls, mtrx, target);
359  }
360  }
361 
363  void UniformlyControlledSingleBit(const std::vector<bitLenInt>& controls, bitLenInt qubitIndex,
364  const complex* mtrxs, const std::vector<bitCapInt> mtrxSkipPowers, bitCapInt mtrxSkipValueMask)
365  {
366  if (qbdt) {
367  qbdt->UniformlyControlledSingleBit(controls, qubitIndex, mtrxs, mtrxSkipPowers, mtrxSkipValueMask);
368  CheckThreshold();
369  } else {
370  engine->UniformlyControlledSingleBit(controls, qubitIndex, mtrxs, mtrxSkipPowers, mtrxSkipValueMask);
371  }
372  }
373 
374  void XMask(bitCapInt mask)
375  {
376  if (qbdt) {
377  qbdt->XMask(mask);
378  } else {
379  engine->XMask(mask);
380  }
381  }
382  void PhaseParity(real1_f radians, bitCapInt mask)
383  {
384  if (qbdt) {
385  qbdt->PhaseParity(radians, mask);
386  } else {
387  engine->PhaseParity(radians, mask);
388  }
389  }
390 
391  real1_f CProb(bitLenInt control, bitLenInt target)
392  {
393  if (qbdt) {
394  return qbdt->CProb(control, target);
395  }
396  return engine->CProb(control, target);
397  }
399  {
400  if (qbdt) {
401  return qbdt->ACProb(control, target);
402  }
403  return engine->ACProb(control, target);
404  }
405 
407  {
408  if (qbdt) {
409  qbdt->UniformParityRZ(mask, angle);
410  CheckThreshold();
411  } else {
412  engine->UniformParityRZ(mask, angle);
413  }
414  }
415  void CUniformParityRZ(const std::vector<bitLenInt>& controls, bitCapInt mask, real1_f angle)
416  {
417  if (qbdt) {
418  qbdt->CUniformParityRZ(controls, mask, angle);
419  CheckThreshold();
420  } else {
421  engine->CUniformParityRZ(controls, mask, angle);
422  }
423  }
424 
425  void CSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
426  {
427  if (qbdt) {
428  qbdt->CSwap(controls, qubit1, qubit2);
429  } else {
430  engine->CSwap(controls, qubit1, qubit2);
431  }
432  }
433  void AntiCSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
434  {
435  if (qbdt) {
436  qbdt->AntiCSwap(controls, qubit1, qubit2);
437  } else {
438  engine->AntiCSwap(controls, qubit1, qubit2);
439  }
440  }
441  void CSqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
442  {
443  if (qbdt) {
444  qbdt->CSqrtSwap(controls, qubit1, qubit2);
445  CheckThreshold();
446  } else {
447  engine->CSqrtSwap(controls, qubit1, qubit2);
448  }
449  }
450  void AntiCSqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
451  {
452  if (qbdt) {
453  qbdt->AntiCSqrtSwap(controls, qubit1, qubit2);
454  CheckThreshold();
455  } else {
456  engine->AntiCSqrtSwap(controls, qubit1, qubit2);
457  }
458  }
459  void CISqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
460  {
461  if (qbdt) {
462  qbdt->CISqrtSwap(controls, qubit1, qubit2);
463  CheckThreshold();
464  } else {
465  engine->CISqrtSwap(controls, qubit1, qubit2);
466  }
467  }
468  void AntiCISqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2)
469  {
470  if (qbdt) {
471  qbdt->AntiCISqrtSwap(controls, qubit1, qubit2);
472  CheckThreshold();
473  } else {
474  engine->AntiCISqrtSwap(controls, qubit1, qubit2);
475  }
476  }
477 
478  bool ForceM(bitLenInt qubit, bool result, bool doForce = true, bool doApply = true)
479  {
480  if (qbdt) {
481  return qbdt->ForceM(qubit, result, doForce, doApply);
482  }
483  return engine->ForceM(qubit, result, doForce, doApply);
484  }
485 
487  {
488  if (qbdt) {
489  return qbdt->MAll();
490  }
491 
492  const bitCapInt toRet = engine->MAll();
493  qbdt = std::dynamic_pointer_cast<QBdt>(MakeSimulator(true, toRet));
494  engine = NULL;
495 
496  return toRet;
497  }
498 
499 #if ENABLE_ALU
500  using QInterface::M;
501  bool M(bitLenInt q)
502  {
503  if (qbdt) {
504  return qbdt->M(q);
505  }
506  return engine->M(q);
507  }
508  using QInterface::X;
509  void X(bitLenInt q)
510  {
511  if (qbdt) {
512  qbdt->X(q);
513  } else {
514  engine->X(q);
515  }
516  }
517  void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
518  {
519  if (qbdt) {
520  qbdt->INC(toAdd, start, length);
521  } else {
522  engine->INC(toAdd, start, length);
523  }
524  }
525  void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
526  {
527  if (qbdt) {
528  qbdt->DEC(toSub, start, length);
529  } else {
530  engine->DEC(toSub, start, length);
531  }
532  }
533  void CDEC(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
534  {
535  if (qbdt) {
536  qbdt->CDEC(toSub, inOutStart, length, controls);
537  } else {
538  engine->CDEC(toSub, inOutStart, length, controls);
539  }
540  }
541  void INCDECC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
542  {
543  if (qbdt) {
544  qbdt->INCDECC(toAdd, start, length, carryIndex);
545  } else {
546  engine->INCDECC(toAdd, start, length, carryIndex);
547  }
548  }
549  void CINC(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
550  {
551  if (qbdt) {
552  qbdt->CINC(toAdd, inOutStart, length, controls);
553  CheckThreshold();
554  } else {
555  engine->CINC(toAdd, inOutStart, length, controls);
556  }
557  }
558  void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
559  {
560  if (qbdt) {
561  qbdt->INCC(toAdd, start, length, carryIndex);
562  CheckThreshold();
563  } else {
564  engine->INCC(toAdd, start, length, carryIndex);
565  }
566  }
567  void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
568  {
569  if (qbdt) {
570  qbdt->INCS(toAdd, start, length, overflowIndex);
571  CheckThreshold();
572  } else {
573  engine->INCS(toAdd, start, length, overflowIndex);
574  }
575  }
576  void DECS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
577  {
578  if (qbdt) {
579  qbdt->DECS(toAdd, start, length, overflowIndex);
580  CheckThreshold();
581  } else {
582  engine->DECS(toAdd, start, length, overflowIndex);
583  }
584  }
585  void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
586  {
587  SwitchMode(false);
588  engine->INCSC(toAdd, start, length, overflowIndex, carryIndex);
589  }
590  void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
591  {
592  SwitchMode(false);
593  engine->INCSC(toAdd, start, length, carryIndex);
594  }
595  void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
596  {
597  if (qbdt) {
598  qbdt->DECC(toSub, start, length, carryIndex);
599  CheckThreshold();
600  } else {
601  engine->DECC(toSub, start, length, carryIndex);
602  }
603  }
604  void DECSC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
605  {
606  SwitchMode(false);
607  engine->DECSC(toSub, start, length, overflowIndex, carryIndex);
608  }
609  void DECSC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
610  {
611  SwitchMode(false);
612  engine->DECSC(toSub, start, length, carryIndex);
613  }
614  void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
615  {
616  SwitchMode(false);
617  engine->INCDECSC(toAdd, start, length, overflowIndex, carryIndex);
618  }
619  void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
620  {
621  SwitchMode(false);
622  engine->INCDECSC(toAdd, start, length, carryIndex);
623  }
624 #if ENABLE_BCD
625  void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
626  {
627  SwitchMode(false);
628  engine->INCBCD(toAdd, start, length);
629  }
630  void INCBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
631  {
632  SwitchMode(false);
633  engine->INCBCDC(toAdd, start, length, carryIndex);
634  }
635  void DECBCDC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
636  {
637  SwitchMode(false);
638  engine->DECBCDC(toSub, start, length, carryIndex);
639  }
640 #endif
641  void MUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
642  {
643  if (qbdt) {
644  qbdt->MUL(toMul, inOutStart, carryStart, length);
645  CheckThreshold();
646  } else {
647  engine->MUL(toMul, inOutStart, carryStart, length);
648  }
649  }
650  void DIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
651  {
652  if (qbdt) {
653  qbdt->DIV(toDiv, inOutStart, carryStart, length);
654  CheckThreshold();
655  } else {
656  engine->DIV(toDiv, inOutStart, carryStart, length);
657  }
658  }
659  void MULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
660  {
661  if (qbdt) {
662  qbdt->MULModNOut(toMul, modN, inStart, outStart, length);
663  CheckThreshold();
664  } else {
665  engine->MULModNOut(toMul, modN, inStart, outStart, length);
666  }
667  }
668  void IMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
669  {
670  if (qbdt) {
671  qbdt->IMULModNOut(toMul, modN, inStart, outStart, length);
672  CheckThreshold();
673  } else {
674  engine->IMULModNOut(toMul, modN, inStart, outStart, length);
675  }
676  }
677  void POWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
678  {
679  SwitchMode(false);
680  engine->POWModNOut(base, modN, inStart, outStart, length);
681  }
682  void CMUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
683  const std::vector<bitLenInt>& controls)
684  {
685  if (qbdt) {
686  qbdt->CMUL(toMul, inOutStart, carryStart, length, controls);
687  CheckThreshold();
688  } else {
689  engine->CMUL(toMul, inOutStart, carryStart, length, controls);
690  }
691  }
692  void CDIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
693  const std::vector<bitLenInt>& controls)
694  {
695  if (qbdt) {
696  qbdt->CDIV(toDiv, inOutStart, carryStart, length, controls);
697  CheckThreshold();
698  } else {
699  engine->CDIV(toDiv, inOutStart, carryStart, length, controls);
700  }
701  }
702  void CMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
703  const std::vector<bitLenInt>& controls)
704  {
705  if (qbdt) {
706  qbdt->CMULModNOut(toMul, modN, inStart, outStart, length, controls);
707  CheckThreshold();
708  } else {
709  engine->CMULModNOut(toMul, modN, inStart, outStart, length, controls);
710  }
711  }
712  void CIMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
713  const std::vector<bitLenInt>& controls)
714  {
715  if (qbdt) {
716  qbdt->CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
717  CheckThreshold();
718  } else {
719  engine->CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
720  }
721  }
722  void CPOWModNOut(bitCapInt base, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length,
723  const std::vector<bitLenInt>& controls)
724  {
725  SwitchMode(false);
726  engine->CPOWModNOut(base, modN, inStart, outStart, length, controls);
727  }
728 
729  bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
730  const unsigned char* values, bool resetValue = true)
731  {
732  SwitchMode(false);
733  return engine->IndexedLDA(indexStart, indexLength, valueStart, valueLength, values, resetValue);
734  }
735  bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
736  bitLenInt carryIndex, const unsigned char* values)
737  {
738  SwitchMode(false);
739  return engine->IndexedADC(indexStart, indexLength, valueStart, valueLength, carryIndex, values);
740  }
741  bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
742  bitLenInt carryIndex, const unsigned char* values)
743  {
744  SwitchMode(false);
745  return engine->IndexedSBC(indexStart, indexLength, valueStart, valueLength, carryIndex, values);
746  }
747  void Hash(bitLenInt start, bitLenInt length, const unsigned char* values)
748  {
749  SwitchMode(false);
750  engine->Hash(start, length, values);
751  }
752 
753  void CPhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
754  {
755  SwitchMode(false);
756  engine->CPhaseFlipIfLess(greaterPerm, start, length, flagIndex);
757  }
758  void PhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length)
759  {
760  SwitchMode(false);
761  engine->PhaseFlipIfLess(greaterPerm, start, length);
762  }
763 #endif
764 
765  void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
766  {
767  if (qbdt) {
768  qbdt->Swap(qubitIndex1, qubitIndex2);
769  } else {
770  engine->Swap(qubitIndex1, qubitIndex2);
771  }
772  }
773  void ISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
774  {
775  if (qbdt) {
776  qbdt->ISwap(qubitIndex1, qubitIndex2);
777  CheckThreshold();
778  } else {
779  engine->ISwap(qubitIndex1, qubitIndex2);
780  }
781  }
782  void IISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
783  {
784  if (qbdt) {
785  qbdt->IISwap(qubitIndex1, qubitIndex2);
786  CheckThreshold();
787  } else {
788  engine->IISwap(qubitIndex1, qubitIndex2);
789  }
790  }
791  void SqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
792  {
793  if (qbdt) {
794  qbdt->SqrtSwap(qubitIndex1, qubitIndex2);
795  CheckThreshold();
796  } else {
797  engine->SqrtSwap(qubitIndex1, qubitIndex2);
798  }
799  }
800  void ISqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
801  {
802  if (qbdt) {
803  qbdt->ISqrtSwap(qubitIndex1, qubitIndex2);
804  CheckThreshold();
805  } else {
806  engine->ISqrtSwap(qubitIndex1, qubitIndex2);
807  }
808  }
809  void FSim(real1_f theta, real1_f phi, bitLenInt qubitIndex1, bitLenInt qubitIndex2)
810  {
811  if (qbdt) {
812  qbdt->FSim(theta, phi, qubitIndex1, qubitIndex2);
813  CheckThreshold();
814  } else {
815  engine->FSim(theta, phi, qubitIndex1, qubitIndex2);
816  }
817  }
818 
819  real1_f Prob(bitLenInt qubitIndex)
820  {
821  if (qbdt) {
822  return qbdt->Prob(qubitIndex);
823  }
824  return engine->Prob(qubitIndex);
825  }
826  real1_f ProbAll(bitCapInt fullRegister)
827  {
828  if (qbdt) {
829  return qbdt->ProbAll(fullRegister);
830  }
831  return engine->ProbAll(fullRegister);
832  }
833  real1_f ProbMask(bitCapInt mask, bitCapInt permutation)
834  {
835  if (qbdt) {
836  return qbdt->ProbMask(mask, permutation);
837  }
838  return engine->ProbMask(mask, permutation);
839  }
841  {
842  if (qbdt) {
843  return qbdt->ProbParity(mask);
844  }
845  return engine->ProbParity(mask);
846  }
847  bool ForceMParity(bitCapInt mask, bool result, bool doForce = true)
848  {
849  if (qbdt) {
850  return qbdt->ForceMParity(mask, result, doForce);
851  }
852  return engine->ForceMParity(mask, result, doForce);
853  }
854 
855  real1_f SumSqrDiff(QInterfacePtr toCompare) { return SumSqrDiff(std::dynamic_pointer_cast<QBdtHybrid>(toCompare)); }
857  {
858  toCompare->SwitchMode(!engine);
859  if (qbdt) {
860  return qbdt->SumSqrDiff(toCompare->qbdt);
861  }
862  return engine->SumSqrDiff(toCompare->engine);
863  }
864 
866  {
867  if (qbdt) {
868  qbdt->UpdateRunningNorm(norm_thresh);
869  } else {
870  engine->UpdateRunningNorm(norm_thresh);
871  }
872  }
874  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
875  {
876  if (qbdt) {
877  qbdt->NormalizeState(nrm, norm_thresh, phaseArg);
878  } else {
879  engine->NormalizeState(nrm, norm_thresh, phaseArg);
880  }
881  }
882 
883  real1_f ExpectationBitsAll(const std::vector<bitLenInt>& bits, bitCapInt offset = 0)
884  {
885  if (qbdt) {
886  return qbdt->ExpectationBitsAll(bits, offset);
887  }
888  return engine->ExpectationBitsAll(bits, offset);
889  }
890 
891  void Finish()
892  {
893  if (qbdt) {
894  qbdt->Finish();
895  } else {
896  engine->Finish();
897  }
898  }
899 
900  bool isFinished()
901  {
902  if (qbdt) {
903  return qbdt->isFinished();
904  }
905  return engine->isFinished();
906  }
907 
908  void Dump()
909  {
910  if (qbdt) {
911  qbdt->Dump();
912  } else {
913  engine->Dump();
914  }
915  }
916 
918  {
919  QBdtHybridPtr c = std::make_shared<QBdtHybrid>(engines, qubitCount, 0U, rand_generator, phaseFactor,
922  c->SetConcurrency(GetConcurrencyLevel());
923  if (qbdt) {
924  c->qbdt = std::dynamic_pointer_cast<QBdt>(qbdt->Clone());
925  } else {
926  c->SwitchMode(false);
927  c->engine->CopyStateVec(engine);
928  }
929 
930  return c;
931  }
932 
933  void SetDevice(int64_t dID)
934  {
935  devID = dID;
936  if (qbdt) {
937  qbdt->SetDevice(dID);
938  } else {
939  engine->SetDevice(dID);
940  }
941  }
942 
943  int64_t GetDevice() { return devID; }
944 
946  {
947  if (qbdt) {
948  return qbdt->GetMaxSize();
949  }
950  return engine->GetMaxSize();
951  };
952 };
953 } // namespace Qrack
unsigned GetConcurrencyLevel()
Definition: parallel_for.hpp:38
Definition: qalu.hpp:22
A "Qrack::QBdtHybrid" internally switched between Qrack::QBdt and Qrack::QHybrid to maximize entangle...
Definition: qbdthybrid.hpp:26
void DIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Divide by integer.
Definition: qbdthybrid.hpp:650
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: qbdthybrid.hpp:735
bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: qbdthybrid.hpp:486
void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register.
Definition: qbdthybrid.hpp:765
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: qbdthybrid.hpp:478
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: qbdthybrid.hpp:352
real1_f ACProb(bitLenInt control, bitLenInt target)
Direct measure of bit probability to be in |1> state, if control bit is |0>.
Definition: qbdthybrid.hpp:398
void Mtrx(const complex *mtrx, bitLenInt qubitIndex)
Apply an arbitrary single bit unitary transformation.
Definition: qbdthybrid.hpp:319
bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qbdthybrid.hpp:151
void UniformlyControlledSingleBit(const std::vector< bitLenInt > &controls, bitLenInt qubitIndex, const complex *mtrxs, const std::vector< bitCapInt > mtrxSkipPowers, bitCapInt mtrxSkipValueMask)
Definition: qbdthybrid.hpp:363
bitLenInt ComposeNoClone(QBdtHybridPtr toCopy)
Definition: qbdthybrid.hpp:169
void Phase(complex topLeft, complex bottomRight, bitLenInt qubitIndex)
Apply a single bit transformation that only effects phase.
Definition: qbdthybrid.hpp:327
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: qbdthybrid.hpp:865
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Definition: qbdthybrid.hpp:165
void MULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Multiplication modulo N by integer, (out of place)
Definition: qbdthybrid.hpp:659
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: qbdthybrid.hpp:712
bool TryDecompose(bitLenInt start, QInterfacePtr dest, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qbdthybrid.hpp:207
real1_f ProbMask(bitCapInt mask, bitCapInt permutation)
Direct measure of masked permutation probability.
Definition: qbdthybrid.hpp:833
void AntiCSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a square root of swap with arbitrary (anti) control bits.
Definition: qbdthybrid.hpp:450
void SqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Square root of Swap gate.
Definition: qbdthybrid.hpp:791
int64_t devID
Definition: qbdthybrid.hpp:36
QBdtHybrid(std::vector< QInterfaceEngine > eng, 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: qbdthybrid.cpp:17
QBdtPtr qbdt
Definition: qbdthybrid.hpp:37
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qbdthybrid.hpp:203
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:338
complex phaseFactor
Definition: qbdthybrid.hpp:39
void UniformParityRZ(bitCapInt mask, real1_f angle)
If the target qubit set parity is odd, this applies a phase factor of .
Definition: qbdthybrid.hpp:406
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: qbdthybrid.hpp:873
bitLenInt thresholdQubits
Definition: qbdthybrid.hpp:34
bitLenInt ComposeNoClone(QInterfacePtr toCopy)
Definition: qbdthybrid.hpp:182
void XMask(bitCapInt mask)
Masked X gate.
Definition: qbdthybrid.hpp:374
void CINC(bitCapInt toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: qbdthybrid.hpp:549
void ISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: qbdthybrid.hpp:773
void Invert(complex topRight, complex bottomLeft, bitLenInt qubitIndex)
Apply a single bit transformation that reverses bit probability and might effect phase.
Definition: qbdthybrid.hpp:335
void DECSC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract a classical integer from the register, with sign and with carry.
Definition: qbdthybrid.hpp:609
void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qbdthybrid.hpp:517
QInterfacePtr Decompose(bitLenInt start, bitLenInt length)
Schmidt decompose a length of qubits.
Definition: qbdthybrid.hpp:187
bitCapIntOcl GetMaxSize()
Definition: qbdthybrid.hpp:945
std::vector< int64_t > deviceIDs
Definition: qbdthybrid.hpp:40
void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract classical integer (without sign, with carry)
Definition: qbdthybrid.hpp:595
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: qbdthybrid.hpp:722
void GetProbs(real1 *outputProbs)
Get the pure quantum state representation.
Definition: qbdthybrid.hpp:286
virtual void Decompose(bitLenInt start, QInterfacePtr dest)=0
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
real1_f ProbAll(bitCapInt fullRegister)
Direct measure of full permutation probability.
Definition: qbdthybrid.hpp:826
void DECSC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Subtract a classical integer from the register, with sign and with carry.
Definition: qbdthybrid.hpp:604
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: qbdthybrid.hpp:758
void SetConcurrency(uint32_t threadCount)
Set the number of threads in parallel for loops, per component QEngine.
Definition: qbdthybrid.hpp:119
void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qbdthybrid.hpp:242
QBdtHybrid(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: qbdthybrid.hpp:104
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: qbdthybrid.hpp:753
real1_f separabilityThreshold
Definition: qbdthybrid.hpp:35
void IMULModNOut(bitCapInt toMul, bitCapInt modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Inverse of multiplication modulo N by integer, (out of place)
Definition: qbdthybrid.hpp:668
real1_f ProbReg(bitLenInt start, bitLenInt length, bitCapInt permutation)
Direct measure of register permutation probability.
Definition: qbdthybrid.hpp:129
void INCDECC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCC and DECC (without sign, with carry)
Definition: qbdthybrid.hpp:541
real1_f SumSqrDiff(QInterfacePtr toCompare)
Definition: qbdthybrid.hpp:855
void X(bitLenInt q)
Definition: qbdthybrid.hpp:509
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: qbdthybrid.hpp:741
QInterfacePtr Clone()
Clone this QInterface.
Definition: qbdthybrid.hpp:917
void MUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Multiply by integer.
Definition: qbdthybrid.hpp:641
void AntiCSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a swap with arbitrary (anti) control bits.
Definition: qbdthybrid.hpp:433
real1_f Prob(bitLenInt qubitIndex)
Direct measure of bit probability to be in |1> state.
Definition: qbdthybrid.hpp:819
void SetPermutation(bitCapInt perm, complex phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qbdthybrid.hpp:309
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: qbdthybrid.hpp:847
void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: qbdthybrid.hpp:558
void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (with overflow flag)
Definition: qbdthybrid.hpp:614
real1_f ExpectationBitsAll(const std::vector< bitLenInt > &bits, bitCapInt offset=0)
Get permutation expectation value of bits.
Definition: qbdthybrid.hpp:883
void MCMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: qbdthybrid.hpp:343
QInterfacePtr MakeSimulator(bool isBdt, bitCapInt perm=0U, complex phaseFac=CMPLX_DEFAULT_ARG)
Definition: qbdthybrid.cpp:59
void ISqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Inverse square root of Swap gate.
Definition: qbdthybrid.hpp:800
bool M(bitLenInt q)
Definition: qbdthybrid.hpp:501
complex GetAmplitude(bitCapInt perm)
Get the representational amplitude of a full permutation.
Definition: qbdthybrid.hpp:294
void Finish()
If asynchronous work is still running, block until it finishes.
Definition: qbdthybrid.hpp:891
void DECS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qbdthybrid.hpp:576
bool useHostRam
Definition: qbdthybrid.hpp:33
bool isBinaryDecisionTree()
Returns "true" if current state representation is definitely a binary decision tree,...
Definition: qbdthybrid.hpp:117
real1_f SumSqrDiff(QBdtHybridPtr toCompare)
Definition: qbdthybrid.hpp:856
void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add classical BCD integer (without sign)
Definition: qbdthybrid.hpp:625
void PhaseParity(real1_f radians, bitCapInt mask)
Parity phase gate.
Definition: qbdthybrid.hpp:382
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: qbdthybrid.hpp:809
void SetAmplitude(bitCapInt perm, complex amp)
Sets the representational amplitude of a full permutation.
Definition: qbdthybrid.hpp:301
bitLenInt Compose(QBdtHybridPtr toCopy)
Definition: qbdthybrid.hpp:138
void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qbdthybrid.hpp:908
std::vector< QInterfaceEngine > engines
Definition: qbdthybrid.hpp:41
int64_t GetDevice()
Get the device index.
Definition: qbdthybrid.hpp:943
void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qbdthybrid.hpp:232
void CISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply an inverse square root of swap with arbitrary control bits.
Definition: qbdthybrid.hpp:459
void SwitchMode(bool useBdt)
Switches between QBdt and QEngine modes.
Definition: qbdthybrid.hpp:48
bool useRDRAND
Definition: qbdthybrid.hpp:31
real1_f CProb(bitLenInt control, bitLenInt target)
Direct measure of bit probability to be in |1> state, if control bit is |1>.
Definition: qbdthybrid.hpp:391
void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qbdthybrid.hpp:567
void CSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a square root of swap with arbitrary control bits.
Definition: qbdthybrid.hpp:441
void CheckThreshold()
Definition: qbdthybrid.hpp:71
void SetQuantumState(const complex *inputState)
Set an arbitrary pure quantum state representation.
Definition: qbdthybrid.hpp:270
void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qbdthybrid.hpp:933
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: qbdthybrid.hpp:702
void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add a classical integer to the register, with sign and with (phase-based) carry.
Definition: qbdthybrid.hpp:590
void CDEC(bitCapInt toSub, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Subtract integer (without sign, with controls)
Definition: qbdthybrid.hpp:533
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: qbdthybrid.hpp:415
bool TryDecompose(bitLenInt start, QBdtHybridPtr dest, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qbdthybrid.hpp:211
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: qbdthybrid.hpp:729
void Decompose(bitLenInt start, QBdtHybridPtr dest)
Definition: qbdthybrid.hpp:221
void INCDECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (without overflow flag)
Definition: qbdthybrid.hpp:619
QEnginePtr engine
Definition: qbdthybrid.hpp:38
bool isSparse
Definition: qbdthybrid.hpp:32
void INCBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add classical BCD integer (without sign, with carry)
Definition: qbdthybrid.hpp:630
void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Add a classical integer to the register, with sign and with carry.
Definition: qbdthybrid.hpp:585
bitLenInt Compose(QBdtHybridPtr toCopy, bitLenInt start)
Definition: qbdthybrid.hpp:152
void AntiCISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply an inverse square root of swap with arbitrary (anti) control bits.
Definition: qbdthybrid.hpp:468
bool isFinished()
Returns "false" if asynchronous work is still running, and "true" if all previously dispatched asynch...
Definition: qbdthybrid.hpp:900
real1_f ProbParity(bitCapInt mask)
Overall probability of any odd permutation of the masked set of bits.
Definition: qbdthybrid.hpp:840
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: qbdthybrid.hpp:782
void DECBCDC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract BCD integer (without sign, with carry)
Definition: qbdthybrid.hpp:635
void Hash(bitLenInt start, bitLenInt length, const unsigned char *values)
Transform a length of qubit register via lookup through a hash table.
Definition: qbdthybrid.hpp:747
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: qbdthybrid.hpp:677
bitLenInt Allocate(bitLenInt start, bitLenInt length)
Allocate new "length" count of |0> state qubits at specified qubit index start position.
Definition: qbdthybrid.hpp:254
void CMUL(bitCapInt toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled multiplication by integer.
Definition: qbdthybrid.hpp:682
void GetQuantumState(complex *outputState)
Get the pure quantum state representation.
Definition: qbdthybrid.hpp:278
void CDIV(bitCapInt toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled division by power of integer.
Definition: qbdthybrid.hpp:692
void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qbdthybrid.hpp:525
void CSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a swap with arbitrary control bits.
Definition: qbdthybrid.hpp:425
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 void SetConcurrency(uint32_t threadsPerEngine)
Set the number of threads in parallel for loops, per component QEngine.
Definition: qinterface.hpp:249
real1 amplitudeFloor
Definition: qinterface.hpp:153
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
qrack_rand_gen_ptr rand_generator
Definition: qinterface.hpp:155
bool randGlobalPhase
Definition: qinterface.hpp:149
virtual void Decompose(bitLenInt start, QInterfacePtr dest)=0
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
virtual void SetQubitCount(bitLenInt qb)
Definition: qinterface.hpp:159
bitLenInt qubitCount
Definition: qinterface.hpp:151
bool doNormalize
Definition: qinterface.hpp:148
Definition: qparity.hpp:22
Half-precision floating-point type.
Definition: half.hpp:2222
virtual bool M(bitLenInt qubitIndex)
Measurement gate.
Definition: qinterface.hpp:976
virtual void UniformlyControlledSingleBit(const std::vector< bitLenInt > &controls, bitLenInt qubitIndex, const complex *mtrxs)
Apply a "uniformly controlled" arbitrary single bit unitary transformation.
Definition: qinterface.hpp:590
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
Definition: complex16x2simd.hpp:25
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
QRACK_CONST real1_f TRYDECOMPOSE_EPSILON
Definition: qrack_types.hpp:244
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::shared_ptr< QBdtHybrid > QBdtHybridPtr
Definition: qbdthybrid.hpp:18
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:243
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
const real1 REAL1_EPSILON
Definition: qrack_types.hpp:157
uint32 log2(uint32 m, unsigned int n=32)
Fixed point binary logarithm.
Definition: half.hpp:1700
#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