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