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  void CINC(const bitCapInt& toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
573  {
574  if (qbdt) {
575  qbdt->CINC(toAdd, inOutStart, length, controls);
576  CheckThreshold();
577  } else {
578  engine->CINC(toAdd, inOutStart, length, controls);
579  }
580  }
581  void INCC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
582  {
583  if (qbdt) {
584  qbdt->INCC(toAdd, start, length, carryIndex);
585  CheckThreshold();
586  } else {
587  engine->INCC(toAdd, start, length, carryIndex);
588  }
589  }
590  void INCS(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
591  {
592  if (qbdt) {
593  qbdt->INCS(toAdd, start, length, overflowIndex);
594  CheckThreshold();
595  } else {
596  engine->INCS(toAdd, start, length, overflowIndex);
597  }
598  }
599  void DECS(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
600  {
601  if (qbdt) {
602  qbdt->DECS(toAdd, start, length, overflowIndex);
603  CheckThreshold();
604  } else {
605  engine->DECS(toAdd, start, length, overflowIndex);
606  }
607  }
608  void INCSC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
609  {
610  SwitchMode(false);
611  engine->INCSC(toAdd, start, length, overflowIndex, carryIndex);
612  }
613  void INCSC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
614  {
615  SwitchMode(false);
616  engine->INCSC(toAdd, start, length, carryIndex);
617  }
618  void DECC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
619  {
620  if (qbdt) {
621  qbdt->DECC(toSub, start, length, carryIndex);
622  CheckThreshold();
623  } else {
624  engine->DECC(toSub, start, length, carryIndex);
625  }
626  }
627  void DECSC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
628  {
629  SwitchMode(false);
630  engine->DECSC(toSub, start, length, overflowIndex, carryIndex);
631  }
632  void DECSC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
633  {
634  SwitchMode(false);
635  engine->DECSC(toSub, start, length, carryIndex);
636  }
637  void INCDECSC(
638  const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
639  {
640  SwitchMode(false);
641  engine->INCDECSC(toAdd, start, length, overflowIndex, carryIndex);
642  }
643  void INCDECSC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
644  {
645  SwitchMode(false);
646  engine->INCDECSC(toAdd, start, length, carryIndex);
647  }
648 #if ENABLE_BCD
649  void INCBCD(const bitCapInt& toAdd, bitLenInt start, bitLenInt length)
650  {
651  SwitchMode(false);
652  engine->INCBCD(toAdd, start, length);
653  }
654  void INCBCDC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
655  {
656  SwitchMode(false);
657  engine->INCBCDC(toAdd, start, length, carryIndex);
658  }
659  void DECBCDC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
660  {
661  SwitchMode(false);
662  engine->DECBCDC(toSub, start, length, carryIndex);
663  }
664 #endif
665  void MUL(const bitCapInt& toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
666  {
667  if (qbdt) {
668  qbdt->MUL(toMul, inOutStart, carryStart, length);
669  } else {
670  engine->MUL(toMul, inOutStart, carryStart, length);
671  }
672  }
673  void DIV(const bitCapInt& toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
674  {
675  if (qbdt) {
676  qbdt->DIV(toDiv, inOutStart, carryStart, length);
677  } else {
678  engine->DIV(toDiv, inOutStart, carryStart, length);
679  }
680  }
682  const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
683  {
684  if (qbdt) {
685  qbdt->MULModNOut(toMul, modN, inStart, outStart, length);
686  } else {
687  engine->MULModNOut(toMul, modN, inStart, outStart, length);
688  }
689  }
691  const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
692  {
693  if (qbdt) {
694  qbdt->IMULModNOut(toMul, modN, inStart, outStart, length);
695  } else {
696  engine->IMULModNOut(toMul, modN, inStart, outStart, length);
697  }
698  }
700  const bitCapInt& base, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
701  {
702  SwitchMode(false);
703  engine->POWModNOut(base, modN, inStart, outStart, length);
704  }
705  void CMUL(const bitCapInt& toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
706  const std::vector<bitLenInt>& controls)
707  {
708  if (qbdt) {
709  qbdt->CMUL(toMul, inOutStart, carryStart, length, controls);
710  CheckThreshold();
711  } else {
712  engine->CMUL(toMul, inOutStart, carryStart, length, controls);
713  }
714  }
715  void CDIV(const bitCapInt& toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
716  const std::vector<bitLenInt>& controls)
717  {
718  if (qbdt) {
719  qbdt->CDIV(toDiv, inOutStart, carryStart, length, controls);
720  CheckThreshold();
721  } else {
722  engine->CDIV(toDiv, inOutStart, carryStart, length, controls);
723  }
724  }
725  void CMULModNOut(const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
726  bitLenInt length, const std::vector<bitLenInt>& controls)
727  {
728  if (qbdt) {
729  qbdt->CMULModNOut(toMul, modN, inStart, outStart, length, controls);
730  CheckThreshold();
731  } else {
732  engine->CMULModNOut(toMul, modN, inStart, outStart, length, controls);
733  }
734  }
735  void CIMULModNOut(const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
736  bitLenInt length, const std::vector<bitLenInt>& controls)
737  {
738  if (qbdt) {
739  qbdt->CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
740  CheckThreshold();
741  } else {
742  engine->CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
743  }
744  }
745  void CPOWModNOut(const bitCapInt& base, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
746  bitLenInt length, const std::vector<bitLenInt>& controls)
747  {
748  SwitchMode(false);
749  engine->CPOWModNOut(base, modN, inStart, outStart, length, controls);
750  }
751 
752  bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
753  const unsigned char* values, bool resetValue = true)
754  {
755  SwitchMode(false);
756  return engine->IndexedLDA(indexStart, indexLength, valueStart, valueLength, values, resetValue);
757  }
758  bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
759  bitLenInt carryIndex, const unsigned char* values)
760  {
761  SwitchMode(false);
762  return engine->IndexedADC(indexStart, indexLength, valueStart, valueLength, carryIndex, values);
763  }
764  bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength,
765  bitLenInt carryIndex, const unsigned char* values)
766  {
767  SwitchMode(false);
768  return engine->IndexedSBC(indexStart, indexLength, valueStart, valueLength, carryIndex, values);
769  }
770  void Hash(bitLenInt start, bitLenInt length, const unsigned char* values)
771  {
772  SwitchMode(false);
773  engine->Hash(start, length, values);
774  }
775 
776  void CPhaseFlipIfLess(const bitCapInt& greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
777  {
778  SwitchMode(false);
779  engine->CPhaseFlipIfLess(greaterPerm, start, length, flagIndex);
780  }
781  void PhaseFlipIfLess(const bitCapInt& greaterPerm, bitLenInt start, bitLenInt length)
782  {
783  SwitchMode(false);
784  engine->PhaseFlipIfLess(greaterPerm, start, length);
785  }
786 #endif
787 
788  void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
789  {
790  if (qbdt) {
791  qbdt->Swap(qubitIndex1, qubitIndex2);
792  } else {
793  engine->Swap(qubitIndex1, qubitIndex2);
794  }
795  }
796  void ISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
797  {
798  if (qbdt) {
799  qbdt->ISwap(qubitIndex1, qubitIndex2);
800  CheckThreshold();
801  } else {
802  engine->ISwap(qubitIndex1, qubitIndex2);
803  }
804  }
805  void IISwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
806  {
807  if (qbdt) {
808  qbdt->IISwap(qubitIndex1, qubitIndex2);
809  CheckThreshold();
810  } else {
811  engine->IISwap(qubitIndex1, qubitIndex2);
812  }
813  }
814  void SqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
815  {
816  if (qbdt) {
817  qbdt->SqrtSwap(qubitIndex1, qubitIndex2);
818  CheckThreshold();
819  } else {
820  engine->SqrtSwap(qubitIndex1, qubitIndex2);
821  }
822  }
823  void ISqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
824  {
825  if (qbdt) {
826  qbdt->ISqrtSwap(qubitIndex1, qubitIndex2);
827  CheckThreshold();
828  } else {
829  engine->ISqrtSwap(qubitIndex1, qubitIndex2);
830  }
831  }
832  void FSim(real1_f theta, real1_f phi, bitLenInt qubitIndex1, bitLenInt qubitIndex2)
833  {
834  if (qbdt) {
835  qbdt->FSim(theta, phi, qubitIndex1, qubitIndex2);
836  CheckThreshold();
837  } else {
838  engine->FSim(theta, phi, qubitIndex1, qubitIndex2);
839  }
840  }
841 
842  real1_f Prob(bitLenInt qubitIndex)
843  {
844  if (qbdt) {
845  return qbdt->Prob(qubitIndex);
846  }
847 
848  return engine->Prob(qubitIndex);
849  }
850  real1_f ProbAll(const bitCapInt& fullRegister)
851  {
852  const real1_f toRet = qbdt ? qbdt->ProbAll(fullRegister) : engine->ProbAll(fullRegister);
853  if (toRet >= (ONE_R1_F - FP_NORM_EPSILON)) {
854  SetPermutation(fullRegister);
855  }
856  return toRet;
857  }
858  real1_f ProbMask(const bitCapInt& mask, const bitCapInt& permutation)
859  {
860  if (qbdt) {
861  return qbdt->ProbMask(mask, permutation);
862  }
863 
864  return engine->ProbMask(mask, permutation);
865  }
867  {
868  if (qbdt) {
869  return qbdt->ProbParity(mask);
870  }
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 
880  return engine->ForceMParity(mask, result, doForce);
881  }
882 
883  real1_f SumSqrDiff(QInterfacePtr toCompare) { return SumSqrDiff(std::dynamic_pointer_cast<QBdtHybrid>(toCompare)); }
885  {
886  toCompare->SwitchMode(!engine);
887  if (qbdt) {
888  return qbdt->SumSqrDiff(toCompare->qbdt);
889  }
890 
891  return engine->SumSqrDiff(toCompare->engine);
892  }
893 
895  {
896  if (qbdt) {
897  qbdt->UpdateRunningNorm(norm_thresh);
898  } else {
899  engine->UpdateRunningNorm(norm_thresh);
900  }
901  }
903  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
904  {
905  if (qbdt) {
906  qbdt->NormalizeState(nrm, norm_thresh, phaseArg);
907  } else {
908  engine->NormalizeState(nrm, norm_thresh, phaseArg);
909  }
910  }
911 
912  real1_f ExpectationBitsAll(const std::vector<bitLenInt>& bits, const bitCapInt& offset = ZERO_BCI)
913  {
914  if (qbdt) {
915  return qbdt->ExpectationBitsAll(bits, offset);
916  }
917 
918  return engine->ExpectationBitsAll(bits, offset);
919  }
920  real1_f VarianceBitsAll(const std::vector<bitLenInt>& bits, const bitCapInt& offset = ZERO_BCI)
921  {
922  if (qbdt) {
923  return qbdt->VarianceBitsAll(bits, offset);
924  }
925 
926  return engine->VarianceBitsAll(bits, offset);
927  }
928 
929  void Finish()
930  {
931  if (qbdt) {
932  qbdt->Finish();
933  } else {
934  engine->Finish();
935  }
936  }
937 
938  bool isFinished()
939  {
940  if (qbdt) {
941  return qbdt->isFinished();
942  }
943 
944  return engine->isFinished();
945  }
946 
947  void Dump()
948  {
949  if (qbdt) {
950  qbdt->Dump();
951  } else {
952  engine->Dump();
953  }
954  }
955 
957  {
958  QBdtHybridPtr c = std::make_shared<QBdtHybrid>(engines, qubitCount, ZERO_BCI, rand_generator, phaseFactor,
961  c->SetConcurrency(GetConcurrencyLevel());
962  if (qbdt) {
963  c->qbdt = std::dynamic_pointer_cast<QBdt>(qbdt->Clone());
964  } else {
965  c->SwitchMode(false);
966  c->engine->CopyStateVec(engine);
967  }
968 
969  return c;
970  }
971 
972  void SetDevice(int64_t dID)
973  {
974  devID = dID;
975  if (qbdt) {
976  qbdt->SetDevice(dID);
977  } else {
978  engine->SetDevice(dID);
979  }
980  }
981 
982  void SetDeviceList(std::vector<int64_t> dIDs)
983  {
984  deviceIDs = dIDs;
985  if (qbdt) {
986  qbdt->SetDeviceList(dIDs);
987  } else {
988  engine->SetDeviceList(dIDs);
989  }
990  }
991 
992  int64_t GetDevice() { return devID; }
993  std::vector<int64_t> GetDeviceList() { return deviceIDs; }
994 
996  {
997  if (qbdt) {
998  return qbdt->GetMaxSize();
999  }
1000 
1001  return engine->GetMaxSize();
1002  };
1003 };
1004 } // namespace Qrack
double bi_to_double(const BigInteger &in)
Definition: big_integer.hpp:483
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:758
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:982
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:874
void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register.
Definition: qbdthybrid.hpp:788
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)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
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:613
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:690
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)
Apply an arbitrary single bit unitary transformation.
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:920
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:894
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:665
void INCDECSC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (without overflow flag)
Definition: qbdthybrid.hpp:643
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:912
real1_f ProbParity(const bitCapInt &mask)
Overall probability of any odd permutation of the masked set of bits.
Definition: qbdthybrid.hpp:866
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:627
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:632
void SqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Square root of Swap gate.
Definition: qbdthybrid.hpp:814
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:371
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:608
complex phaseFactor
Definition: qbdthybrid.hpp:39
void XMask(const bitCapInt &mask)
Masked X gate.
Definition: qbdthybrid.hpp:390
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:902
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:796
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:995
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:745
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:590
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:673
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:993
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:883
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:764
QInterfacePtr Clone()
Clone this QInterface.
Definition: qbdthybrid.hpp:956
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:842
void INCC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: qbdthybrid.hpp:581
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:781
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:359
real1_f ProbMask(const bitCapInt &mask, const bitCapInt &permutation)
Direct measure of masked permutation probability.
Definition: qbdthybrid.hpp:858
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:681
void ISqrtSwap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Inverse square root of Swap gate.
Definition: qbdthybrid.hpp:823
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:705
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:699
void Finish()
If asynchronous work is still running, block until it finishes.
Definition: qbdthybrid.hpp:929
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:637
real1_f SumSqrDiff(QBdtHybridPtr toCompare)
Definition: qbdthybrid.hpp:884
void INCBCD(const bitCapInt &toAdd, bitLenInt start, bitLenInt length)
Add classical BCD integer (without sign)
Definition: qbdthybrid.hpp:649
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:735
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:832
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:947
std::vector< QInterfaceEngine > engines
Definition: qbdthybrid.hpp:41
int64_t GetDevice()
Get the device index.
Definition: qbdthybrid.hpp:992
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:725
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:972
void DECBCDC(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract BCD integer (without sign, with carry)
Definition: qbdthybrid.hpp:659
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:752
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:938
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:715
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:599
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:805
void CINC(const bitCapInt &toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: qbdthybrid.hpp:572
void INCBCDC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add classical BCD integer (without sign, with carry)
Definition: qbdthybrid.hpp:654
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:770
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:776
void DECC(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract classical integer (without sign, with carry)
Definition: qbdthybrid.hpp:618
real1_f ProbAll(const bitCapInt &fullRegister)
Direct measure of full permutation probability.
Definition: qbdthybrid.hpp:850
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:477
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:371
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:634
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1091
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:1020
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:159
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:29
const real1_f _qrack_qunit_sep_thresh
Definition: qrack_functions.hpp:249
QRACK_CONST real1_f TRYDECOMPOSE_EPSILON
Definition: qrack_types.hpp:270
bitLenInt log2Ocl(bitCapIntOcl n)
Definition: qrack_functions.hpp:95
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:136
const bitLenInt PSTRIDEPOW_DEFAULT
Definition: qrack_functions.hpp:255
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:268
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:208
float real1_f
Definition: qrack_types.hpp:103
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:267
const bitCapInt ZERO_BCI
Definition: qrack_types.hpp:138
bitCapIntOcl pow2Ocl(const bitLenInt &p)
Definition: qrack_functions.hpp:144
uint32 log2(uint32 m, unsigned int n=32)
Fixed point binary logarithm.
Definition: half.hpp:1700
#define REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:185
#define bitLenInt
Definition: qrack_types.hpp:42
#define ZERO_R1_F
Definition: qrack_types.hpp:168
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:164
#define bitCapInt
Definition: qrack_types.hpp:66
#define bitCapIntOcl
Definition: qrack_types.hpp:54
#define ONE_R1_F
Definition: qrack_types.hpp:171