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