Qrack  10.0
General classical-emulating-quantum development framework
qunit.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // QUnit maintains explicit separability of qubits as an optimization on a QEngine.
6 // See https://arxiv.org/abs/1710.05867
7 // (The makers of Qrack have no affiliation with the authors of that paper.)
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 
13 #pragma once
14 
15 #include "qengineshard.hpp"
16 #include "qparity.hpp"
17 
18 #if ENABLE_ALU
19 #include "qalu.hpp"
20 #endif
21 
22 namespace Qrack {
23 
24 class QUnit;
25 typedef std::shared_ptr<QUnit> QUnitPtr;
26 
27 #if ENABLE_ALU
28 class QUnit : public QAlu, public QParity, public QInterface {
29 #else
30 class QUnit : public QParity, public QInterface {
31 #endif
32 protected:
34  bool useHostRam;
36  bool useTGadget;
37  bool useExactNC;
38  bool isBdt;
39  bool isCpu;
41  bool isSparse;
42  bool isAce;
43  size_t aceMb;
49  double logFidelity;
50  int64_t devID;
53  std::vector<int64_t> deviceIDs;
54  std::vector<QInterfaceEngine> engines;
55 
56  QInterfacePtr MakeEngine(bitLenInt length, const bitCapInt& perm);
57 
58  virtual void Copy(QInterfacePtr orig) { Copy(std::dynamic_pointer_cast<QUnit>(orig)); }
59  virtual void Copy(QUnitPtr orig)
60  {
61  QInterface::Copy(orig);
62  freezeBasis2Qb = orig->freezeBasis2Qb;
63  useHostRam = orig->useHostRam;
64  isReactiveSeparate = orig->isReactiveSeparate;
65  useTGadget = orig->useTGadget;
66  useExactNC = orig->useExactNC;
67  thresholdQubits = orig->thresholdQubits;
68  separabilityThreshold = orig->separabilityThreshold;
69  roundingThreshold = orig->roundingThreshold;
70  sparse_thresh = orig->sparse_thresh;
71  logFidelity = orig->logFidelity;
72  devID = orig->devID;
73  phaseFactor = orig->phaseFactor;
74  shards = orig->shards;
75  deviceIDs = orig->deviceIDs;
76  engines = orig->engines;
77  }
78 
79  double PhaseInfidelity(const complex& p) { return (double)clampProb(abs(arg(p)) / PI_R1); }
80 
81  // Drafted by Ellie (the OpenAI custom GPT instance), refined by Dan
82  // Returns payload factor in [0,3] = negator + phase0 + phase1
83  // clamped to range [0,2] as lower bound for general worst-case input
84  // m: row-major [u00, u01, u10, u11]
85  double PayloadInfidelityFactor3(const complex m[4U])
86  {
87  const complex& u00 = m[0];
88  const complex& u01 = m[1];
89  const complex& u10 = m[2];
90  const complex& u11 = m[3];
91 
92  // Negator strength: average off-diagonal power
93  const real1_f n01 = norm(u01);
94  const real1_f n10 = norm(u10);
95  const real1_f N = clampProb((n01 + n10) / 2);
96 
97  // Phase contributions per "input basis branch", weighted by where amplitude goes
98  const real1_f n00 = norm(u00);
99  const real1_f n11 = norm(u11);
100  const real1_f P0 = clampProb(n00 * PhaseInfidelity(u00) + n10 * PhaseInfidelity(u10));
101  const real1_f P1 = clampProb(n11 * PhaseInfidelity(u11) + n01 * PhaseInfidelity(u01));
102 
103  return (double)clampProb((N + P0 + P1) / 2) * 2;
104  }
105 
107  {
108 #if ENABLE_ENV_VARS
109  if ((!(bool)getenv("QRACK_DISABLE_QUNIT_FIDELITY_GUARD")) && (logFidelity <= FIDELITY_MIN)) {
110 #else
111  if (logFidelity <= FIDELITY_MIN) {
112 #endif
113  throw std::runtime_error("QUnit fidelity estimate is effectively 0! (This DOES NOT mean your fidelity is "
114  "necessarily close to 0! Please read the Qrack README, and then, afterward, "
115  "consider setting environment variable QRACK_DISABLE_QUNIT_FIDELITY_GUARD=1.)");
116  }
117  }
118 
119  void ElideCz(
120  const bool& isAnti, const bitLenInt& control, const bitLenInt& target, const real1_f& pth, const real1_f& pc)
121  {
122  // Act CNOT shadow.
123  const bool ptHi = pth > pc;
124  const real1_f pHi = ptHi ? pth : pc;
125  const real1_f pLo = ptHi ? pc : pth;
126  const bool pState = abs(pHi - HALF_R1) >= abs(pLo - HALF_R1);
127 
128  logFidelity += (double)log(pState ? pHi : (ONE_R1_F - pLo));
129  CheckFidelity();
130 
131  if (pState) {
132  if (!ptHi) {
133  Phase(ONE_CMPLX, -ONE_CMPLX, target);
134  } else if (isAnti) {
135  // This makes absolutely no detectable difference,
136  // according to canonical quantum mechanics.
137  // Trump is Hitler, by the way, and Dan needs
138  // to make that explicitly obvious as part of
139  // the statement of free speech that is Qrack.
140  // (I'm saying, you should've already known.)
141  Phase(-ONE_CMPLX, ONE_CMPLX, control);
142  } else {
143  Phase(ONE_CMPLX, -ONE_CMPLX, control);
144  }
145  }
146  }
147 
148 public:
149  QUnit(std::vector<QInterfaceEngine> eng, bitLenInt qBitCount, const bitCapInt& initState = ZERO_BCI,
150  qrack_rand_gen_ptr rgp = nullptr, const complex& phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false,
151  bool randomGlobalPhase = true, bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true,
152  bool ignored = false, real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devIDs = {},
153  bitLenInt qubitThreshold = 0U, real1_f separation_thresh = _qrack_qunit_sep_thresh);
154 
155  QUnit(bitLenInt qBitCount, const bitCapInt& initState = ZERO_BCI, qrack_rand_gen_ptr rgp = nullptr,
156  const complex& phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
157  bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true, bool ignored = false,
158  real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devIDs = {}, bitLenInt qubitThreshold = 0U,
159  real1_f separation_thresh = _qrack_qunit_sep_thresh)
160  : QUnit({ QINTERFACE_STABILIZER_HYBRID }, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase,
161  useHostMem, deviceId, useHardwareRNG, ignored, norm_thresh, devIDs, qubitThreshold, separation_thresh)
162  {
163  }
164 
165  virtual ~QUnit() { Dump(); }
166 
167  virtual void SetConcurrency(uint32_t threadsPerEngine)
168  {
169  QInterface::SetConcurrency(threadsPerEngine);
171  [](QInterfacePtr unit, real1_f unused1, real1_f unused2, real1_f unused3, int64_t threadsPerEngine,
172  std::vector<int64_t> unused4) {
173  unit->SetConcurrency((uint32_t)threadsPerEngine);
174  return true;
175  },
176  ZERO_R1_F, ZERO_R1_F, ZERO_R1_F, threadsPerEngine);
177  }
178 
179  virtual void SetTInjection(bool useGadget)
180  {
181  useTGadget = useGadget;
183  [](QInterfacePtr unit, real1_f unused1, real1_f unused2, real1_f unused3, int64_t useGadget,
184  std::vector<int64_t> unused4) {
185  unit->SetTInjection((bool)useGadget);
186  return true;
187  },
188  ZERO_R1_F, ZERO_R1_F, ZERO_R1_F, useGadget ? 1U : 0U);
189  }
190 
191  virtual void SetUseExactNearClifford(bool useExact)
192  {
193  useExactNC = useExact;
195  [](QInterfacePtr unit, real1_f unused1, real1_f unused2, real1_f unused3, int64_t useExact,
196  std::vector<int64_t> unused4) {
197  unit->SetUseExactNearClifford((bool)useExact);
198  return true;
199  },
200  ZERO_R1_F, ZERO_R1_F, ZERO_R1_F, useExact ? 1U : 0U);
201  }
202 
204  {
205  sparse_thresh = p;
207  [](QInterfacePtr unit, real1_f p, real1_f unused1, real1_f unused2, int64_t unused3,
208  std::vector<int64_t> unused4) {
209  unit->SetSparseProbabilityFloor(p);
210  return true;
211  },
212  p, ZERO_R1_F, ZERO_R1_F, 0U);
213  }
214 
215  virtual void SetReactiveSeparate(bool isAggSep) { isReactiveSeparate = isAggSep; }
216  virtual bool GetReactiveSeparate() { return isReactiveSeparate; }
217 
218  virtual void SetDevice(int64_t dID);
219  virtual void SetDeviceList(std::vector<int64_t> dIDs);
220  virtual int64_t GetDevice() { return devID; }
221  virtual std::vector<int64_t> GetDeviceList() { return deviceIDs; }
222 
223  virtual real1_f ProbRdm(bitLenInt qubit)
224  {
225  if (qubit >= qubitCount) {
226  throw std::invalid_argument("Qubit index " + std::to_string(qubit) + " out of range in QUnit::ProbRdm!");
227  }
228 
229  const QEngineShard& shard = shards[qubit];
230  if (!shard.unit) {
231  return Prob(qubit);
232  }
233 
234  return shard.unit->ProbRdm(qubit);
235  }
236  virtual real1_f CProbRdm(bitLenInt control, bitLenInt target)
237  {
238  AntiCNOT(control, target);
239  const real1_f prob = ProbRdm(target);
240  AntiCNOT(control, target);
241 
242  return prob;
243  }
244  virtual real1_f ACProbRdm(bitLenInt control, bitLenInt target)
245  {
246  CNOT(control, target);
247  const real1_f prob = ProbRdm(target);
248  CNOT(control, target);
249 
250  return prob;
251  }
252 
253  virtual bool AreFactorized(std::vector<bitLenInt> a, std::vector<bitLenInt> b, bool flushCache = false)
254  {
255  std::set<QInterfacePtr> aUnits;
256  for (auto i : a) {
257  if (flushCache) {
258  ToPermBasis(i);
259  }
260  QInterfacePtr u = shards[i].unit;
261  if (!u) {
262  continue;
263  }
264  aUnits.insert(u);
265  }
266  std::set<QInterfacePtr> bUnits;
267  for (auto i : b) {
268  if (flushCache) {
269  ToPermBasis(i);
270  }
271  QInterfacePtr u = shards[i].unit;
272  if (!u) {
273  continue;
274  }
275  bUnits.insert(u);
276  }
277 
278  // Comparison written with assistance from Google search LLM
279  auto it1 = aUnits.begin();
280  auto it2 = bUnits.begin();
281 
282  while (it1 != aUnits.end() && it2 != bUnits.end()) {
283  if (*it1 < *it2) {
284  ++it1;
285  } else if (*it2 < *it1) {
286  ++it2;
287  } else {
288  // Match found, sets have a common element!
289  return false;
290  }
291  }
292 
293  // Match not found, sets have no common element!
294  return true;
295  }
296 
297  virtual void LossySaveStateVector(std::string f, int p = 6, int b = 4);
298  virtual void LossyLoadStateVector(std::string f);
299  virtual void SetQuantumState(const complex* inputState);
300  virtual void GetQuantumState(complex* outputState) { GetQuantumStateOrProbs(outputState, nullptr); }
301  virtual void GetProbs(real1* outputProbs) { GetQuantumStateOrProbs(nullptr, outputProbs); }
302  virtual void GetQuantumStateOrProbs(complex* outputState, real1* outputProbs);
303  virtual complex GetAmplitude(const bitCapInt& perm);
304  virtual void SetAmplitude(const bitCapInt& perm, const complex& amp)
305  {
306  if (!qubitCount) {
307  throw std::domain_error("QUnit::SetAmplitude called for 0 qubits!");
308  }
309 
310  if (bi_compare(perm, maxQPower) >= 0) {
311  throw std::invalid_argument("QUnit::SetAmplitude argument out-of-bounds!");
312  }
313 
314  EntangleAll();
315  shards[0U].unit->SetAmplitude(perm, amp);
316  }
317  virtual void SetPermutation(const bitCapInt& perm, const complex& phaseFac = CMPLX_DEFAULT_ARG);
318  using QInterface::Compose;
319  virtual bitLenInt Compose(QUnitPtr toCopy) { return Compose(toCopy, qubitCount); }
320  virtual bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QUnit>(toCopy)); }
321  virtual bitLenInt Compose(QUnitPtr toCopy, bitLenInt start)
322  {
323  if (start > qubitCount) {
324  throw std::invalid_argument("QUnit::Compose start index is out-of-bounds!");
325  }
326 
327  ToPermBasisAll();
328 
329  /* Create a clone of the quantum state in toCopy. */
330  QUnitPtr clone = std::dynamic_pointer_cast<QUnit>(toCopy->Clone());
331 
332  clone->ToPermBasisAll();
333 
334  /* Insert the new shards in the middle */
335  shards.insert(start, clone->shards);
336 
337  SetQubitCount(qubitCount + toCopy->GetQubitCount());
338 
339  return start;
340  }
341  virtual bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
342  {
343  return Compose(std::dynamic_pointer_cast<QUnit>(toCopy), start);
344  }
345  virtual void Decompose(bitLenInt start, QInterfacePtr dest)
346  {
347  Decompose(start, std::dynamic_pointer_cast<QUnit>(dest));
348  }
349  virtual void Decompose(bitLenInt start, QUnitPtr dest) { Detach(start, dest->GetQubitCount(), dest); }
351  {
352  QUnitPtr dest = std::make_shared<QUnit>(engines, length, ZERO_BCI, rand_generator, phaseFactor, doNormalize,
355 
356  Decompose(start, dest);
357 
358  return dest;
359  }
360  virtual void Dispose(bitLenInt start, bitLenInt length) { Detach(start, length, nullptr); }
361  virtual void Dispose(bitLenInt start, bitLenInt length, const bitCapInt& disposedPerm)
362  {
363  Detach(start, length, nullptr);
364  }
365  virtual bool TryDecompose(bitLenInt start, QInterfacePtr dest, real1_f error_tol = TRYDECOMPOSE_EPSILON)
366  {
367  return TryDecompose(start, std::dynamic_pointer_cast<QUnit>(dest), error_tol);
368  }
369  virtual bool TryDecompose(bitLenInt start, QUnitPtr dest, real1_f error_tol = TRYDECOMPOSE_EPSILON)
370  {
371  return Detach(start, dest->GetQubitCount(), dest, true, error_tol);
372  }
373  using QInterface::Allocate;
374  virtual bitLenInt Allocate(bitLenInt start, bitLenInt length);
375 
381  using QInterface::H;
382  virtual void H(bitLenInt target);
383  using QInterface::S;
384  virtual void S(bitLenInt target);
385  using QInterface::IS;
386  virtual void IS(bitLenInt target);
387 
388  virtual void ZMask(const bitCapInt& mask) { PhaseParity(PI_R1, mask); }
389  virtual void PhaseParity(real1_f radians, const bitCapInt& mask);
390 
391  virtual void Phase(const complex& topLeft, const complex& bottomRight, bitLenInt qubitIndex);
392  virtual void Invert(const complex& topRight, const complex& bottomLeft, bitLenInt qubitIndex);
393  virtual void MCPhase(
394  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target)
395  {
396  bitCapInt m = pow2(controls.size());
397  bi_decrement(&m, 1U);
398  UCPhase(controls, topLeft, bottomRight, target, m);
399  }
400  virtual void MCInvert(
401  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target)
402  {
403  bitCapInt m = pow2(controls.size());
404  bi_decrement(&m, 1U);
405  UCInvert(controls, topRight, bottomLeft, target, m);
406  }
407  virtual void MACPhase(
408  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target)
409  {
410  UCPhase(controls, topLeft, bottomRight, target, ZERO_BCI);
411  }
412  virtual void MACInvert(
413  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target)
414  {
415  UCInvert(controls, topRight, bottomLeft, target, ZERO_BCI);
416  }
417  virtual void UCPhase(const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight,
418  bitLenInt target, const bitCapInt& controlPerm);
419  virtual void UCInvert(const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft,
420  bitLenInt target, const bitCapInt& controlPerm);
421  virtual void Mtrx(const complex mtrx[4U], bitLenInt qubit);
422  virtual void MCMtrx(const std::vector<bitLenInt>& controls, const complex mtrx[4U], bitLenInt target)
423  {
424  bitCapInt m = pow2(controls.size());
425  bi_decrement(&m, 1U);
426  UCMtrx(controls, mtrx, target, m);
427  }
428  virtual void MACMtrx(const std::vector<bitLenInt>& controls, const complex mtrx[4U], bitLenInt target)
429  {
430  UCMtrx(controls, mtrx, target, ZERO_BCI);
431  }
432  virtual void UCMtrx(
433  const std::vector<bitLenInt>& controls, const complex mtrx[4U], bitLenInt target, const bitCapInt& controlPerm);
435  virtual void UniformlyControlledSingleBit(const std::vector<bitLenInt>& controls, bitLenInt qubitIndex,
436  const complex* mtrxs, const std::vector<bitCapInt>& mtrxSkipPowers, const bitCapInt& mtrxSkipValueMask);
437  virtual void CUniformParityRZ(const std::vector<bitLenInt>& controls, const bitCapInt& mask, real1_f angle);
438  virtual void CSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
439  virtual void AntiCSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
440  virtual void CSqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
441  virtual void AntiCSqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
442  virtual void CISqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
443  virtual void AntiCISqrtSwap(const std::vector<bitLenInt>& controls, bitLenInt qubit1, bitLenInt qubit2);
444  using QInterface::ForceM;
445  virtual bool ForceM(bitLenInt qubitIndex, bool result, bool doForce = true, bool doApply = true);
446  using QInterface::ForceMReg;
447  virtual bitCapInt ForceMReg(
448  bitLenInt start, bitLenInt length, const bitCapInt& result, bool doForce = true, bool doApply = true);
449  virtual bitCapInt HighestProbAll();
450  virtual bitCapInt MAll();
451  virtual std::map<bitCapInt, int> MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots);
452  virtual void MultiShotMeasureMask(
453  const std::vector<bitCapInt>& qPowers, unsigned shots, unsigned long long* shotsArray);
454 
457 #if ENABLE_ALU
458  using QInterface::M;
459  virtual bool M(bitLenInt q) { return QInterface::M(q); }
460  using QInterface::X;
461  virtual void X(bitLenInt q) { QInterface::X(q); }
462 
469  virtual void DEC(const bitCapInt& toSub, bitLenInt start, bitLenInt length)
470  {
471  QInterface::DEC(toSub, start, length);
472  }
473  virtual void DECS(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
474  {
475  QInterface::DECS(toSub, start, length, overflowIndex);
476  }
477  virtual void CINC(
478  const bitCapInt& toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
479  {
480  QInterface::CINC(toAdd, inOutStart, length, controls);
481  }
482  virtual void CDEC(
483  const bitCapInt& toSub, bitLenInt inOutStart, bitLenInt length, const std::vector<bitLenInt>& controls)
484  {
485  QInterface::CDEC(toSub, inOutStart, length, controls);
486  }
487  virtual void INCDECC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
488  {
489  QInterface::INCDECC(toAdd, start, length, carryIndex);
490  }
491  virtual void MULModNOut(
492  const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
493  {
494  QInterface::MULModNOut(toMul, modN, inStart, outStart, length);
495  }
496  virtual void IMULModNOut(
497  const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
498  {
499  QInterface::IMULModNOut(toMul, modN, inStart, outStart, length);
500  }
501  virtual void CMULModNOut(const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
502  bitLenInt length, const std::vector<bitLenInt>& controls)
503  {
504  QInterface::CMULModNOut(toMul, modN, inStart, outStart, length, controls);
505  }
506  virtual void CIMULModNOut(const bitCapInt& toMul, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
507  bitLenInt length, const std::vector<bitLenInt>& controls)
508  {
509  QInterface::CIMULModNOut(toMul, modN, inStart, outStart, length, controls);
510  }
511 
512  virtual void INC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length);
513  virtual void INCC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
514  virtual void INCS(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex);
515  virtual void INCDECSC(
516  const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex);
517  virtual void INCDECSC(const bitCapInt& toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
518  virtual void DECC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
519 #if ENABLE_BCD
520  virtual void INCBCD(const bitCapInt& toAdd, bitLenInt start, bitLenInt length);
521  virtual void DECBCD(const bitCapInt& toAdd, bitLenInt start, bitLenInt length);
522  virtual void INCDECBCDC(const bitCapInt& toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
523 #endif
524  virtual void MUL(const bitCapInt& toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length);
525  virtual void DIV(const bitCapInt& toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length);
526  virtual void POWModNOut(
527  const bitCapInt& base, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length);
528  virtual void CMUL(const bitCapInt& toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
529  const std::vector<bitLenInt>& controls);
530  virtual void CDIV(const bitCapInt& toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length,
531  const std::vector<bitLenInt>& controls);
532  virtual void CPOWModNOut(const bitCapInt& base, const bitCapInt& modN, bitLenInt inStart, bitLenInt outStart,
533  bitLenInt length, const std::vector<bitLenInt>& controls);
534  virtual bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
535  bitLenInt valueLength, const unsigned char* values, bool resetValue = true);
536  virtual bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
537  bitLenInt valueLength, bitLenInt carryIndex, const unsigned char* values);
538  virtual bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
539  bitLenInt valueLength, bitLenInt carryIndex, const unsigned char* values);
540  virtual void Hash(bitLenInt start, bitLenInt length, const unsigned char* values);
541  virtual void CPhaseFlipIfLess(const bitCapInt& greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex);
542  virtual void PhaseFlipIfLess(const bitCapInt& greaterPerm, bitLenInt start, bitLenInt length);
543 
545 #endif
546 
553  virtual void SetReg(bitLenInt start, bitLenInt length, const bitCapInt& value);
554  virtual void Swap(bitLenInt qubit1, bitLenInt qubit2)
555  {
556  if (qubit1 >= qubitCount) {
557  throw std::invalid_argument("QUnit::Swap qubit index parameter must be within allocated qubit bounds!");
558  }
559 
560  if (qubit2 >= qubitCount) {
561  throw std::invalid_argument("QUnit::Swap qubit index parameter must be within allocated qubit bounds!");
562  }
563 
564  if (qubit1 == qubit2) {
565  return;
566  }
567 
568  // Simply swap the bit mapping.
569  shards.swap(qubit1, qubit2);
570  }
571  virtual void ISwap(bitLenInt qubit1, bitLenInt qubit2) { EitherISwap(qubit1, qubit2, false); }
572  virtual void IISwap(bitLenInt qubit1, bitLenInt qubit2) { EitherISwap(qubit1, qubit2, true); }
573  virtual void SqrtSwap(bitLenInt qubit1, bitLenInt qubit2);
574  virtual void ISqrtSwap(bitLenInt qubit1, bitLenInt qubit2);
575 
584  virtual real1_f Prob(bitLenInt qubit)
585  {
586  if (qubit >= qubitCount) {
587  throw std::invalid_argument("QUnit::Prob target parameter must be within allocated qubit bounds!");
588  }
589 
590  ToPermBasisProb(qubit);
591  return ProbBase(qubit);
592  }
593  virtual real1_f ProbAll(const bitCapInt& perm) { return clampProb((real1_f)norm(GetAmplitudeOrProb(perm, true))); }
594  virtual real1_f ProbAllRdm(bool roundRz, const bitCapInt& perm)
595  {
596  if (!qubitCount) {
597  throw std::domain_error("QUnit::ProbAllRdm called for 0 qubits!");
598  }
599 
600  if (shards[0U].unit && (shards[0U].unit->GetQubitCount() == qubitCount)) {
601  OrderContiguous(shards[0U].unit);
602  return shards[0U].unit->ProbAllRdm(roundRz, perm);
603  }
604 
605  QUnitPtr clone = std::dynamic_pointer_cast<QUnit>(Clone());
606  QInterfacePtr unit = clone->EntangleAll(true);
607  clone->OrderContiguous(unit);
608 
609  return unit->ProbAllRdm(roundRz, perm);
610  }
611  virtual real1_f ProbParity(const bitCapInt& mask);
612  virtual bool ForceMParity(const bitCapInt& mask, bool result, bool doForce = true);
613  virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
614  {
615  return SumSqrDiff(std::dynamic_pointer_cast<QUnit>(toCompare));
616  }
617  virtual real1_f SumSqrDiff(QUnitPtr toCompare);
619  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
620  {
621  return ExpVarFactorized(true, false, false, bits, perms, std::vector<real1_f>(), offset, false);
622  }
623  virtual real1_f ExpectationBitsFactorizedRdm(bool roundRz, const std::vector<bitLenInt>& bits,
624  const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
625  {
626  return ExpVarFactorized(true, true, false, bits, perms, std::vector<real1_f>(), offset, roundRz);
627  }
629  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
630  {
631  return ExpVarFactorized(false, false, false, bits, perms, std::vector<real1_f>(), offset, false);
632  }
633  virtual real1_f VarianceBitsFactorizedRdm(bool roundRz, const std::vector<bitLenInt>& bits,
634  const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
635  {
636  return ExpVarFactorized(false, true, false, bits, perms, std::vector<real1_f>(), offset, roundRz);
637  }
638  virtual void UpdateRunningNorm(real1_f norm_thresh = REAL1_DEFAULT_ARG);
639  virtual void NormalizeState(
640  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F);
641  virtual void Finish();
642  virtual bool isFinished();
643  virtual void Dump()
644  {
645  for (QEngineShard& shard : shards) {
646  // Setting shard to NULL seems theoretically memory-safe, as previously used here,
647  // but it's safer (in the intent of dumping remaining QInterface work)
648  // to set shard.unit to nullptr.
649  shard.unit = nullptr;
650  }
651  }
653  virtual bool isClifford(bitLenInt qubit)
654  {
655  if (qubit >= qubitCount) {
656  throw std::invalid_argument("Qubit index " + std::to_string(qubit) + " out of range in QUnit::isClifford!");
657  }
658 
659  return shards[qubit].isClifford();
660  };
661 
663  virtual bool TrySeparate(bitLenInt qubit);
664  virtual bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2);
665  virtual bool TrySeparate(const std::vector<bitLenInt>& qubits, real1_f error_tol)
666  {
667  for (size_t i = 0U; i < qubits.size(); ++i) {
668  Swap(qubitCount - (i + 1U), qubits[i]);
669  }
670 
671  QUnitPtr dest = std::make_shared<QUnit>(engines, qubits.size(), ZERO_BCI, rand_generator, phaseFactor,
674 
675  const bool result = TryDecompose(qubitCount - qubits.size(), dest);
676  if (result) {
677  Compose(dest);
678  }
679 
680  for (bitLenInt i = qubits.size(); i > 0U; --i) {
681  Swap(qubitCount - i, qubits[i - 1U]);
682  }
683 
684  return result;
685  }
686  virtual double GetUnitaryFidelity();
687  virtual void ResetUnitaryFidelity() { logFidelity = 0.0; }
688  virtual void SetSdrp(real1_f sdrp)
689  {
690  separabilityThreshold = sdrp;
692  };
693  virtual void SetNcrp(real1_f ncrp)
694  {
695  roundingThreshold = ncrp;
697  [](QInterfacePtr unit, real1_f rp, real1_f unused, real1_f unused2, int64_t unused3,
698  std::vector<int64_t> unused4) {
699  unit->SetNcrp(rp);
700  return true;
701  },
702  ncrp, ZERO_R1_F, ZERO_R1_F, 0);
703  }
704  virtual void SetAceMaxQubits(bitLenInt qb) { aceQubits = qb; }
705  virtual void SetSparseAceMaxMb(size_t mb) { aceMb = mb; }
706 
707  virtual QInterfacePtr Clone();
708  virtual QInterfacePtr Copy();
709 
712 protected:
713  virtual complex GetAmplitudeOrProb(const bitCapInt& perm, bool isProb);
714 
715  virtual void XBase(bitLenInt target)
716  {
717  if (target >= qubitCount) {
718  throw std::invalid_argument("QUnit::XBase qubit index parameter must be within allocated qubit bounds!");
719  }
720 
721  QEngineShard& shard = shards[target];
722 
723  if (shard.unit) {
724  shard.unit->X(shard.mapped);
725  }
726 
727  std::swap(shard.amp0, shard.amp1);
728  }
729 
730  virtual void YBase(bitLenInt target)
731  {
732  if (target >= qubitCount) {
733  throw std::invalid_argument("QUnit::YBase qubit index parameter must be within allocated qubit bounds!");
734  }
735 
736  QEngineShard& shard = shards[target];
737 
738  if (shard.unit) {
739  shard.unit->Y(shard.mapped);
740  }
741 
742  const complex Y0 = shard.amp0;
743  shard.amp0 = -I_CMPLX * shard.amp1;
744  shard.amp1 = I_CMPLX * Y0;
745  }
746 
747  virtual void ZBase(bitLenInt target)
748  {
749  if (target >= qubitCount) {
750  throw std::invalid_argument("QUnit::ZBase qubit index parameter must be within allocated qubit bounds!");
751  }
752 
753  QEngineShard& shard = shards[target];
754 
755  if (shard.unit) {
756  shard.unit->Z(shard.mapped);
757  }
758 
759  shard.amp1 = -shard.amp1;
760  }
761  virtual real1_f ProbBase(bitLenInt qubit);
762 
763  virtual bool TrySeparateClifford(bitLenInt qubit);
764 
765  virtual void EitherISwap(bitLenInt qubit1, bitLenInt qubit2, bool isInverse);
766 
767 #if ENABLE_ALU
768  typedef void (QAlu::*INCxFn)(const bitCapInt&, bitLenInt, bitLenInt, bitLenInt);
770  typedef void (QAlu::*CMULFn)(const bitCapInt&, bitLenInt, bitLenInt, bitLenInt, const std::vector<bitLenInt>&);
771  typedef void (QAlu::*CMULModFn)(
772  const bitCapInt&, const bitCapInt&, bitLenInt, bitLenInt, bitLenInt, const std::vector<bitLenInt>&);
773  void INT(const bitCapInt& toMod, bitLenInt start, bitLenInt length, bitLenInt carryIndex, bool hasCarry,
774  std::vector<bitLenInt> controlVec = std::vector<bitLenInt>());
775  void INTS(const bitCapInt& toMod, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex,
776  bool hasCarry);
777  void INCx(INCxFn fn, const bitCapInt& toMod, bitLenInt start, bitLenInt length, bitLenInt flagIndex);
778  void INCxx(INCxxFn fn, const bitCapInt& toMod, bitLenInt start, bitLenInt length, bitLenInt flag1Index,
779  bitLenInt flag2Index);
780  QInterfacePtr CMULEntangle(std::vector<bitLenInt> controlVec, bitLenInt start, bitLenInt carryStart,
781  bitLenInt length, std::vector<bitLenInt>* controlsMapped);
782  std::vector<bitLenInt> CMULEntangle(
783  std::vector<bitLenInt> controlVec, bitLenInt start, const bitCapInt& carryStart, bitLenInt length);
784  void CMULx(CMULFn fn, const bitCapInt& toMod, bitLenInt start, bitLenInt carryStart, bitLenInt length,
785  std::vector<bitLenInt> controlVec);
786  void CMULModx(CMULModFn fn, const bitCapInt& toMod, const bitCapInt& modN, bitLenInt start, bitLenInt carryStart,
787  bitLenInt length, std::vector<bitLenInt> controlVec);
788  bool INTCOptimize(const bitCapInt& toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt carryIndex);
789  bool INTSOptimize(const bitCapInt& toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt overflowIndex);
790  bool INTSCOptimize(const bitCapInt& toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt carryIndex,
791  bitLenInt overflowIndex);
792  bitCapInt GetIndexedEigenstate(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
793  bitLenInt valueLength, const unsigned char* values);
794  bitCapInt GetIndexedEigenstate(bitLenInt start, bitLenInt length, const unsigned char* values);
795 #endif
796 
797  real1_f ExpVarFactorized(bool isExp, bool isRdm, bool isFloat, const std::vector<bitLenInt>& bits,
798  const std::vector<bitCapInt>& perms, const std::vector<real1_f>& weights, const bitCapInt& offset, bool roundRz)
799  {
800  if (!qubitCount) {
801  throw std::domain_error("QUnit::ProbAllRdm called for 0 qubits!");
802  }
803 
804  if ((isFloat && (weights.size() < bits.size())) || (!isFloat && (perms.size() < bits.size()))) {
805  throw std::invalid_argument("QUnit::ExpectationFactorized() must supply at least as many weights as bits!");
806  }
807 
809  "QUnit::ExpectationFactorized parameter qubits vector values must be within allocated qubit bounds!");
810 
811  if (shards[0U].unit && (shards[0U].unit->GetQubitCount() == qubitCount)) {
812  OrderContiguous(shards[0U].unit);
813  return isExp ? isFloat
814  ? (isRdm ? shards[0U].unit->ExpectationFloatsFactorizedRdm(roundRz, bits, weights)
815  : shards[0U].unit->ExpectationFloatsFactorized(bits, weights))
816  : (isRdm ? shards[0U].unit->ExpectationBitsFactorizedRdm(roundRz, bits, perms, offset)
817  : shards[0U].unit->ExpectationBitsFactorized(bits, perms, offset))
818  : isFloat ? (isRdm ? shards[0U].unit->VarianceFloatsFactorizedRdm(roundRz, bits, weights)
819  : shards[0U].unit->VarianceFloatsFactorized(bits, weights))
820  : (isRdm ? shards[0U].unit->VarianceBitsFactorizedRdm(roundRz, bits, perms, offset)
821  : shards[0U].unit->VarianceBitsFactorized(bits, perms, offset));
822  }
823 
824  QUnitPtr clone = std::dynamic_pointer_cast<QUnit>(Clone());
825  QInterfacePtr unit = clone->EntangleAll(true);
826  clone->OrderContiguous(unit);
827 
828  return isExp ? isFloat ? (isRdm ? unit->ExpectationFloatsFactorizedRdm(roundRz, bits, weights)
829  : unit->ExpectationFloatsFactorized(bits, weights))
830  : (isRdm ? unit->ExpectationBitsFactorizedRdm(roundRz, bits, perms, offset)
831  : unit->ExpectationBitsFactorized(bits, perms, offset))
832  : isFloat ? (isRdm ? unit->VarianceFloatsFactorizedRdm(roundRz, bits, weights)
833  : unit->VarianceFloatsFactorized(bits, weights))
834  : (isRdm ? unit->VarianceBitsFactorizedRdm(roundRz, bits, perms, offset)
835  : unit->VarianceBitsFactorized(bits, perms, offset));
836  }
837 
838  virtual QInterfacePtr Entangle(std::vector<bitLenInt> bits);
839  virtual QInterfacePtr Entangle(std::vector<bitLenInt*> bits);
840  virtual QInterfacePtr EntangleRange(bitLenInt start, bitLenInt length, bool isForProb = false);
841  virtual QInterfacePtr EntangleRange(bitLenInt start, bitLenInt length, bitLenInt start2, bitLenInt length2);
843  bitLenInt start, bitLenInt length, bitLenInt start2, bitLenInt length2, bitLenInt start3, bitLenInt length3);
844  virtual QInterfacePtr EntangleAll(bool isForProb = false)
845  {
846  QInterfacePtr toRet = EntangleRange(0, qubitCount, isForProb);
847  OrderContiguous(toRet);
848  return toRet;
849  }
850 
851  virtual QInterfacePtr CloneBody(QUnitPtr copyPtr, bool isCopy);
852 
853  virtual bool CheckBitsPermutation(bitLenInt start, bitLenInt length = 1);
854  virtual bitCapInt GetCachedPermutation(bitLenInt start, bitLenInt length);
855  virtual bitCapInt GetCachedPermutation(const std::vector<bitLenInt>& bitArray);
856  virtual bool CheckBitsPlus(bitLenInt qubitIndex, bitLenInt length);
857 
859  std::vector<bitLenInt*>::iterator first, std::vector<bitLenInt*>::iterator last);
860 
861  typedef bool (*ParallelUnitFn)(QInterfacePtr unit, real1_f param1, real1_f param2, real1_f param3, int64_t param4,
862  std::vector<int64_t> param5);
864  real1_f param3 = ZERO_R1_F, int64_t param4 = 0, std::vector<int64_t> param5 = {});
865 
866  virtual bool SeparateBit(bool value, bitLenInt qubit);
867 
868  void OrderContiguous(QInterfacePtr unit);
869 
870  virtual bool Detach(
871  bitLenInt start, bitLenInt length, QUnitPtr dest, bool isTry = false, real1_f tol = TRYDECOMPOSE_EPSILON);
872 
873  struct QSortEntry {
876  bool operator<(const QSortEntry& rhs) { return mapped < rhs.mapped; }
877  bool operator>(const QSortEntry& rhs) { return mapped > rhs.mapped; }
878  };
879  void SortUnit(QInterfacePtr unit, std::vector<QSortEntry>& bits, bitLenInt low, bitLenInt high);
880 
881  bool TrimControls(const std::vector<bitLenInt>& controls, std::vector<bitLenInt>& controlVec, bitCapInt* perm);
882 
883  template <typename CF>
884  void ApplyEitherControlled(std::vector<bitLenInt> controlVec, const std::vector<bitLenInt> targets, CF cfn,
885  bool isPhase, const bitCapInt& controlPerm, const double payloadInfidelity);
886 
887  void ClampShard(bitLenInt qubit)
888  {
889  if (qubit >= qubitCount) {
890  throw std::invalid_argument("Qubit index " + std::to_string(qubit) + " out of range in QUnit::ClampShard!");
891  }
892 
893  QEngineShard& shard = shards[qubit];
894  if (!shard.ClampAmps() || !shard.unit) {
895  return;
896  }
897 
898  if (IS_NORM_0(shard.amp1)) {
899  logFidelity += (double)log(clampProb(ONE_R1_F - norm(shard.amp1)));
900  SeparateBit(false, qubit);
901  } else if (IS_NORM_0(shard.amp0)) {
902  logFidelity += (double)log(clampProb(ONE_R1_F - norm(shard.amp0)));
903  SeparateBit(true, qubit);
904  }
905 
906  CheckFidelity();
907  }
908 
909  void TransformX2x2(const complex mtrxIn[4U], complex mtrxOut[4U])
910  {
911  mtrxOut[0U] = HALF_R1 * (mtrxIn[0U] + mtrxIn[1U] + mtrxIn[2U] + mtrxIn[3U]);
912  mtrxOut[1U] = HALF_R1 * (mtrxIn[0U] - mtrxIn[1U] + mtrxIn[2U] - mtrxIn[3U]);
913  mtrxOut[2U] = HALF_R1 * (mtrxIn[0U] + mtrxIn[1U] - mtrxIn[2U] - mtrxIn[3U]);
914  mtrxOut[3U] = HALF_R1 * (mtrxIn[0U] - mtrxIn[1U] - mtrxIn[2U] + mtrxIn[3U]);
915  }
916 
917  void TransformXInvert(const complex& topRight, const complex& bottomLeft, complex mtrxOut[4U])
918  {
919  mtrxOut[0U] = HALF_R1 * (topRight + bottomLeft);
920  mtrxOut[1U] = HALF_R1 * (-topRight + bottomLeft);
921  mtrxOut[2U] = -mtrxOut[1U];
922  mtrxOut[3U] = -mtrxOut[0U];
923  }
924 
925  void TransformY2x2(const complex mtrxIn[4U], complex mtrxOut[4U])
926  {
927  mtrxOut[0U] = HALF_R1 * (mtrxIn[0U] + I_CMPLX * (mtrxIn[1U] - mtrxIn[2U]) + mtrxIn[3U]);
928  mtrxOut[1U] = HALF_R1 * (mtrxIn[0U] - I_CMPLX * (mtrxIn[1U] + mtrxIn[2U]) - mtrxIn[3U]);
929  mtrxOut[2U] = HALF_R1 * (mtrxIn[0U] + I_CMPLX * (mtrxIn[1U] + mtrxIn[2U]) - mtrxIn[3U]);
930  mtrxOut[3U] = HALF_R1 * (mtrxIn[0U] - I_CMPLX * (mtrxIn[1U] - mtrxIn[2U]) + mtrxIn[3U]);
931  }
932 
933  void TransformYInvert(const complex& topRight, const complex& bottomLeft, complex mtrxOut[4U])
934  {
935  mtrxOut[0U] = I_CMPLX * HALF_R1 * (topRight - bottomLeft);
936  mtrxOut[1U] = I_CMPLX * HALF_R1 * (-topRight - bottomLeft);
937  mtrxOut[2U] = -mtrxOut[1U];
938  mtrxOut[3U] = -mtrxOut[0U];
939  }
940 
941  void TransformPhase(const complex& topLeft, const complex& bottomRight, complex* mtrxOut)
942  {
943  mtrxOut[0U] = HALF_R1 * (topLeft + bottomRight);
944  mtrxOut[1U] = HALF_R1 * (topLeft - bottomRight);
945  mtrxOut[2U] = mtrxOut[1U];
946  mtrxOut[3U] = mtrxOut[0U];
947  }
948 
950  {
951  if (i >= qubitCount) {
952  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::RevertBasisX!");
953  }
954 
955  QEngineShard& shard = shards[i];
956  if (shard.pauliBasis != PauliX) {
957  // Recursive call that should be blocked,
958  // or already in target basis.
959  return;
960  }
961 
962  ConvertZToX(i);
963  }
964 
966  {
967  if (i >= qubitCount) {
968  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::RevertBasisY!");
969  }
970 
971  QEngineShard& shard = shards[i];
972 
973  if (shard.pauliBasis != PauliY) {
974  // Recursive call that should be blocked,
975  // or already in target basis.
976  return;
977  }
978 
979  shard.pauliBasis = PauliX;
980 
981  if (shard.unit) {
982  shard.unit->SqrtX(shard.mapped);
983  }
984 
985  if (shard.isPhaseDirty || shard.isProbDirty) {
986  shard.isProbDirty = true;
987  return;
988  }
989 
992  QRACK_CONST complex mtrx[4U]{ diag, cross, cross, diag };
993 
994  const complex Y0 = shard.amp0;
995  const complex& Y1 = shard.amp1;
996  shard.amp0 = (mtrx[0U] * Y0) + (mtrx[1U] * Y1);
997  shard.amp1 = (mtrx[2U] * Y0) + (mtrx[3U] * Y1);
998  ClampShard(i);
999  }
1000 
1002  {
1003  if (i >= qubitCount) {
1004  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::RevertBasis1Qb!");
1005  }
1006 
1007  QEngineShard& shard = shards[i];
1008 
1009  if (shard.pauliBasis == PauliY) {
1010  ConvertYToZ(i);
1011  } else {
1012  RevertBasisX(i);
1013  }
1014  }
1015 
1017  {
1018  if (i >= qubitCount) {
1019  throw std::invalid_argument(
1020  "Qubit index " + std::to_string(i) + " out of range in QUnit::RevertBasisToX1Qb!");
1021  }
1022 
1023  QEngineShard& shard = shards[i];
1024  if (shard.pauliBasis == PauliZ) {
1025  ConvertZToX(i);
1026  } else if (shard.pauliBasis == PauliY) {
1027  RevertBasisY(i);
1028  }
1029  }
1030 
1032  {
1033  if (i >= qubitCount) {
1034  throw std::invalid_argument(
1035  "Qubit index " + std::to_string(i) + " out of range in QUnit::RevertBasisToY1Qb!");
1036  }
1037 
1038  QEngineShard& shard = shards[i];
1039  if (shard.pauliBasis == PauliZ) {
1040  ConvertZToY(i);
1041  } else if (shard.pauliBasis == PauliX) {
1042  ConvertXToY(i);
1043  }
1044  }
1045 
1047  {
1048  if (i >= qubitCount) {
1049  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::ConvertZToX!");
1050  }
1051 
1052  QEngineShard& shard = shards[i];
1053 
1054  // WARNING: Might be called when shard is in either Z or X basis
1055  shard.pauliBasis = (shard.pauliBasis == PauliX) ? PauliZ : PauliX;
1056 
1057  if (shard.unit) {
1058  shard.unit->H(shard.mapped);
1059  }
1060 
1061  if (shard.isPhaseDirty || shard.isProbDirty) {
1062  shard.isProbDirty = true;
1063  return;
1064  }
1065 
1066  const complex tempAmp1 = SQRT1_2_R1 * (shard.amp0 - shard.amp1);
1067  shard.amp0 = SQRT1_2_R1 * (shard.amp0 + shard.amp1);
1068  shard.amp1 = tempAmp1;
1069  ClampShard(i);
1070  }
1072  {
1073  if (i >= qubitCount) {
1074  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::ConvertXToY!");
1075  }
1076 
1077  QEngineShard& shard = shards[i];
1078 
1079  shard.pauliBasis = PauliY;
1080 
1081  if (shard.unit) {
1082  shard.unit->ISqrtX(shard.mapped);
1083  }
1084 
1085  if (shard.isPhaseDirty || shard.isProbDirty) {
1086  shard.isProbDirty = true;
1087  return;
1088  }
1089 
1090  QRACK_CONST complex diag = complex(ONE_R1 / (real1)2, -ONE_R1 / (real1)2);
1091  QRACK_CONST complex cross = complex(ONE_R1 / (real1)2, ONE_R1 / (real1)2);
1092  QRACK_CONST complex mtrx[4U]{ diag, cross, cross, diag };
1093 
1094  const complex Y0 = shard.amp0;
1095  const complex& Y1 = shard.amp1;
1096  shard.amp0 = (mtrx[0U] * Y0) + (mtrx[1U] * Y1);
1097  shard.amp1 = (mtrx[2U] * Y0) + (mtrx[3U] * Y1);
1098  ClampShard(i);
1099  }
1101  {
1102  if (i >= qubitCount) {
1103  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::ConvertYToZ!");
1104  }
1105 
1106  QEngineShard& shard = shards[i];
1107 
1108  shard.pauliBasis = PauliZ;
1109 
1110  if (shard.unit) {
1111  shard.unit->SH(shard.mapped);
1112  }
1113 
1114  if (shard.isPhaseDirty || shard.isProbDirty) {
1115  shard.isProbDirty = true;
1116  return;
1117  }
1118 
1120  QRACK_CONST complex mtrx[4U]{ row1, row1, complex(ZERO_R1, SQRT1_2_R1), complex(ZERO_R1, -SQRT1_2_R1) };
1121 
1122  const complex Y0 = shard.amp0;
1123  const complex& Y1 = shard.amp1;
1124  shard.amp0 = (mtrx[0U] * Y0) + (mtrx[1U] * Y1);
1125  shard.amp1 = (mtrx[2U] * Y0) + (mtrx[3U] * Y1);
1126  ClampShard(i);
1127  }
1129  {
1130  if (i >= qubitCount) {
1131  throw std::invalid_argument("Qubit index " + std::to_string(i) + " out of range in QUnit::ConvertZToY!");
1132  }
1133 
1134  QEngineShard& shard = shards[i];
1135 
1136  shard.pauliBasis = PauliY;
1137 
1138  if (shard.unit) {
1139  shard.unit->HIS(shard.mapped);
1140  }
1141 
1142  if (shard.isPhaseDirty || shard.isProbDirty) {
1143  shard.isProbDirty = true;
1144  return;
1145  }
1146 
1148  QRACK_CONST complex mtrx[4U]{ col1, complex(ZERO_R1, -SQRT1_2_R1), col1, complex(ZERO_R1, SQRT1_2_R1) };
1149 
1150  const complex Y0 = shard.amp0;
1151  const complex& Y1 = shard.amp1;
1152  shard.amp0 = (mtrx[0U] * Y0) + (mtrx[1U] * Y1);
1153  shard.amp1 = (mtrx[2U] * Y0) + (mtrx[3U] * Y1);
1154  ClampShard(i);
1155  }
1156  void ShardAI(bitLenInt qubit, real1_f azimuth, real1_f inclination)
1157  {
1158  if (qubit >= qubitCount) {
1159  throw std::invalid_argument("Qubit index " + std::to_string(qubit) + " out of range in QUnit::ShardAI!");
1160  }
1161 
1162  real1 cosineA = (real1)cos(azimuth);
1163  real1 sineA = (real1)sin(azimuth);
1164  real1 cosineI = (real1)cos(inclination / 2);
1165  real1 sineI = (real1)sin(inclination / 2);
1166  complex expA = complex(cosineA, sineA);
1167  complex expNegA = complex(cosineA, -sineA);
1168  complex mtrx[4U]{ cosineI, -expNegA * sineI, expA * sineI, cosineI };
1169 
1170  QEngineShard& shard = shards[qubit];
1171 
1172  const complex Y0 = shard.amp0;
1173  const complex& Y1 = shard.amp1;
1174  shard.amp0 = (mtrx[0U] * Y0) + (mtrx[1U] * Y1);
1175  shard.amp1 = (mtrx[2U] * Y0) + (mtrx[3U] * Y1);
1176  ClampShard(qubit);
1177  }
1178 
1182 
1183  void ApplyBuffer(PhaseShardPtr phaseShard, bitLenInt control, bitLenInt target, bool isAnti);
1184  void ApplyBufferMap(bitLenInt bitIndex, ShardToPhaseMap bufferMap, RevertExclusivity exclusivity, bool isControl,
1185  bool isAnti, const std::set<bitLenInt>& exceptPartners, bool dumpSkipped);
1187  RevertControl controlExclusivity = CONTROLS_AND_TARGETS, RevertAnti antiExclusivity = CTRL_AND_ANTI,
1188  const std::set<bitLenInt>& exceptControlling = {}, const std::set<bitLenInt>& exceptTargetedBy = {},
1189  bool dumpSkipped = false, bool skipOptimized = false);
1190 
1192  {
1193  if (i >= qubitCount) {
1194  throw std::invalid_argument(
1195  "Qubit index " + std::to_string(i) + " out of range in QUnit::Flush0Eigenstate!");
1196  }
1197 
1198  QEngineShard& shard = shards[i];
1199  shard.DumpControlOf();
1200  if (randGlobalPhase) {
1202  }
1204  }
1206  {
1207  if (i >= qubitCount) {
1208  throw std::invalid_argument(
1209  "Qubit index " + std::to_string(i) + " out of range in QUnit::Flush1Eigenstate!");
1210  }
1211 
1212  QEngineShard& shard = shards[i];
1213  shard.DumpAntiControlOf();
1214  if (randGlobalPhase) {
1215  shard.DumpSamePhaseControlOf();
1216  }
1218  }
1220  {
1221  RevertBasis1Qb(i);
1222  RevertBasis2Qb(i);
1223  }
1224  void ToPermBasis(bitLenInt start, bitLenInt length)
1225  {
1226  for (bitLenInt i = 0U; i < length; ++i) {
1227  RevertBasis1Qb(start + i);
1228  }
1229  for (bitLenInt i = 0U; i < length; ++i) {
1230  RevertBasis2Qb(start + i);
1231  }
1232  }
1234  {
1235  RevertBasis1Qb(qubit);
1237  }
1239  {
1240  for (bitLenInt i = 0U; i < length; ++i) {
1241  RevertBasis1Qb(start + i);
1242  }
1243  for (bitLenInt i = 0U; i < length; ++i) {
1245  }
1246  }
1250  {
1251  RevertBasis1Qb(qubit);
1252  RevertBasis2Qb(qubit, ONLY_INVERT);
1254 
1255  shards[qubit].DumpMultiBit();
1256  }
1257  void ToPermBasisMeasure(bitLenInt start, bitLenInt length);
1258  void ToPermBasisAllMeasure();
1259 
1261  {
1262  if ((start + length) > qubitCount) {
1263  throw std::invalid_argument(
1264  "Qubit index " + std::to_string(start + length) + " out of range in QUnit::DirtyShardRange!");
1265  }
1266 
1267  for (bitLenInt i = 0U; i < length; ++i) {
1268  shards[start + i].MakeDirty();
1269  }
1270  }
1271 
1273  {
1274  if ((start + length) > qubitCount) {
1275  throw std::invalid_argument(
1276  "Qubit index " + std::to_string(start + length) + " out of range in QUnit::DirtyShardRangePhase!");
1277  }
1278 
1279  for (bitLenInt i = 0U; i < length; ++i) {
1280  shards[start + i].isPhaseDirty = true;
1281  }
1282  }
1283 
1284  void DirtyShardIndexVector(std::vector<bitLenInt> bitIndices)
1285  {
1286  for (const bitLenInt& bitIndex : bitIndices) {
1287  if (bitIndex >= qubitCount) {
1288  throw std::invalid_argument(
1289  "Qubit index " + std::to_string(bitIndex) + " out of range in QUnit::DirtyShardRangePhase!");
1290  }
1291 
1292  shards[bitIndex].MakeDirty();
1293  }
1294  }
1295 
1297  {
1298  if (target >= qubitCount) {
1299  throw std::invalid_argument(
1300  "Qubit index " + std::to_string(target) + " out of range in QUnit::EndEmulation!");
1301  }
1302 
1303  QEngineShard& shard = shards[target];
1304  if (shard.unit) {
1305  return;
1306  }
1307 
1308  if (norm(shard.amp1) <= FP_NORM_EPSILON) {
1309  shard.unit = MakeEngine(1U, ZERO_BCI);
1310  } else if (norm(shard.amp0) <= FP_NORM_EPSILON) {
1311  shard.unit = MakeEngine(1U, ONE_BCI);
1312  } else {
1313  const complex bitState[2U]{ shard.amp0, shard.amp1 };
1314  shard.unit = MakeEngine(1U, ZERO_BCI);
1315  shard.unit->SetQuantumState(bitState);
1316  }
1317  }
1318 
1320  {
1321  shard->found = true;
1322  for (bitLenInt i = 0U; i < shards.size(); ++i) {
1323  if (shards[i].found) {
1324  shard->found = false;
1325  return i;
1326  }
1327  }
1328  shard->found = false;
1329  return shards.size();
1330  }
1331 
1332  void CommuteH(bitLenInt bitIndex);
1333 
1334  void OptimizePairBuffers(bitLenInt control, bitLenInt target, bool anti);
1335 };
1336 
1337 } // namespace Qrack
void bi_decrement(BigInteger *pBigInt, const BIG_INTEGER_WORD &value)
Definition: big_integer.hpp:238
int bi_compare(const BigInteger &left, const BigInteger &right)
Definition: big_integer.hpp:126
Definition: qalu.hpp:22
Definition: qengineshard.hpp:316
std::vector< QEngineShard > shards
Definition: qengineshard.hpp:318
bitLenInt size()
Definition: qengineshard.hpp:352
void swap(bitLenInt qubit1, bitLenInt qubit2)
Definition: qengineshard.hpp:388
void insert(bitLenInt start, QEngineShardMap &toInsert)
Definition: qengineshard.hpp:360
Associates a QInterface object with a set of bits.
Definition: qengineshard.hpp:50
void DumpControlOf()
Definition: qengineshard.hpp:163
complex amp0
Definition: qengineshard.hpp:63
bool ClampAmps()
Definition: qengineshard.cpp:26
bitLenInt mapped
Definition: qengineshard.hpp:60
bool isProbDirty
Definition: qengineshard.hpp:61
void DumpAntiControlOf()
Definition: qengineshard.hpp:164
QInterfacePtr unit
Definition: qengineshard.hpp:59
Pauli pauliBasis
Definition: qengineshard.hpp:65
complex amp1
Definition: qengineshard.hpp:64
void DumpSamePhaseAntiControlOf()
Definition: qengineshard.hpp:172
bool found
Definition: qengineshard.hpp:75
void DumpSamePhaseControlOf()
Definition: qengineshard.hpp:168
bool isPhaseDirty
Definition: qengineshard.hpp:62
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
bool useRDRAND
Definition: qinterface.hpp:145
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 SetQubitCount(bitLenInt qb)
Definition: qinterface.hpp:268
static real1_f clampProb(real1_f toClamp)
Definition: qinterface.hpp:158
bitLenInt qubitCount
Definition: qinterface.hpp:146
bool doNormalize
Definition: qinterface.hpp:143
Definition: qparity.hpp:22
Definition: qunit.hpp:28
void ConvertYToZ(bitLenInt i)
Definition: qunit.hpp:1100
void ToPermBasisAll()
Definition: qunit.hpp:1247
bool useExactNC
Definition: qunit.hpp:37
virtual void SetReactiveSeparate(bool isAggSep)
Set reactive separation option (on by default if available)
Definition: qunit.hpp:215
std::vector< int64_t > deviceIDs
Definition: qunit.hpp:53
void CMULx(CMULFn fn, const bitCapInt &toMod, bitLenInt start, bitLenInt carryStart, bitLenInt length, std::vector< bitLenInt > controlVec)
Definition: qunit.cpp:3385
void OptimizePairBuffers(bitLenInt control, bitLenInt target, bool anti)
Definition: qunit.cpp:4288
virtual void YBase(bitLenInt target)
Definition: qunit.hpp:730
void ApplyEitherControlled(std::vector< bitLenInt > controlVec, const std::vector< bitLenInt > targets, CF cfn, bool isPhase, const bitCapInt &controlPerm, const double payloadInfidelity)
Definition: qunit.cpp:2666
void OrderContiguous(QInterfacePtr unit)
Definition: qunit.cpp:857
virtual complex GetAmplitudeOrProb(const bitCapInt &perm, bool isProb)
Definition: qunit.cpp:257
double PhaseInfidelity(const complex &p)
Definition: qunit.hpp:79
real1_f ExpVarFactorized(bool isExp, bool isRdm, bool isFloat, const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const std::vector< real1_f > &weights, const bitCapInt &offset, bool roundRz)
Definition: qunit.hpp:797
void INTS(const bitCapInt &toMod, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex, bool hasCarry)
Definition: qunit.cpp:3148
bool ParallelUnitApply(ParallelUnitFn fn, real1_f param1=ZERO_R1_F, real1_f param2=ZERO_R1_F, real1_f param3=ZERO_R1_F, int64_t param4=0, std::vector< int64_t > param5={})
Definition: qunit.cpp:3739
void(QAlu::* INCxFn)(const bitCapInt &, bitLenInt, bitLenInt, bitLenInt)
Definition: qunit.hpp:768
void Flush1Eigenstate(bitLenInt i)
Definition: qunit.hpp:1205
QInterfacePtr MakeEngine(bitLenInt length, const bitCapInt &perm)
Definition: qunit.cpp:140
void SortUnit(QInterfacePtr unit, std::vector< QSortEntry > &bits, bitLenInt low, bitLenInt high)
Sort a container of bits, calling Swap() on each.
Definition: qunit.cpp:883
void ToPermBasisProb(bitLenInt qubit)
Definition: qunit.hpp:1233
virtual QInterfacePtr EntangleInCurrentBasis(std::vector< bitLenInt * >::iterator first, std::vector< bitLenInt * >::iterator last)
Definition: qunit.cpp:431
double PayloadInfidelityFactor3(const complex m[4U])
Definition: qunit.hpp:85
virtual bool CheckBitsPermutation(bitLenInt start, bitLenInt length=1)
Check if all qubits in the range have cached probabilities indicating that they are in permutation ba...
Definition: qunit.cpp:924
bool useTGadget
Definition: qunit.hpp:36
virtual void X(bitLenInt q)
Definition: qunit.hpp:461
virtual QInterfacePtr Entangle(std::vector< bitLenInt > bits)
Definition: qunit.cpp:545
virtual bitLenInt Allocate(bitLenInt length)
Allocate new "length" count of |0> state qubits at end of qubit index position.
Definition: qinterface.hpp:488
virtual void EitherISwap(bitLenInt qubit1, bitLenInt qubit2, bool isInverse)
Definition: qunit.cpp:1793
void RevertBasis1Qb(bitLenInt i)
Definition: qunit.hpp:1001
virtual QInterfacePtr Decompose(bitLenInt start, bitLenInt length)
Schmidt decompose a length of qubits.
Definition: qunit.hpp:350
virtual void IS(bitLenInt qubit)
Inverse S gate.
Definition: qinterface.hpp:1052
virtual void S(bitLenInt qubit)
S gate.
Definition: qinterface.hpp:1045
virtual real1_f CProbRdm(bitLenInt control, bitLenInt target)
Definition: qunit.hpp:236
real1_f separabilityThreshold
Definition: qunit.hpp:46
void ToPermBasisProb()
Definition: qunit.hpp:1248
virtual real1_f ProbBase(bitLenInt qubit)
Definition: qunit.cpp:976
virtual void GetQuantumState(complex *outputState)
Get the pure quantum state representation.
Definition: qunit.hpp:300
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 bitCapInt ForceMReg(bitLenInt start, bitLenInt length, const bitCapInt &result, bool doForce=true, bool doApply=true)
Act as if is a measurement was applied, except force the (usually random) result.
Definition: qinterface.cpp:215
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:382
virtual bool ForceM(bitLenInt qubit, bool result, bool doForce=true, bool doApply=true)=0
Act as if is a measurement was applied, except force the (usually random) result.
real1_f roundingThreshold
Definition: qunit.hpp:47
virtual bool CheckBitsPlus(bitLenInt qubitIndex, bitLenInt length)
Definition: qunit.cpp:963
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qunit.hpp:320
void ToPermBasisAllMeasure()
Definition: qunit.cpp:2820
complex phaseFactor
Definition: qunit.hpp:51
void CheckFidelity()
Definition: qunit.hpp:106
void INT(const bitCapInt &toMod, bitLenInt start, bitLenInt length, bitLenInt carryIndex, bool hasCarry, std::vector< bitLenInt > controlVec=std::vector< bitLenInt >())
Definition: qunit.cpp:2939
virtual void H(bitLenInt qubit)
Hadamard gate.
Definition: qinterface.hpp:931
virtual bool SeparateBit(bool value, bitLenInt qubit)
Definition: qunit.cpp:1350
bool isReactiveSeparate
Definition: qunit.hpp:35
real1_f sparse_thresh
Definition: qunit.hpp:48
void(QAlu::* CMULModFn)(const bitCapInt &, const bitCapInt &, bitLenInt, bitLenInt, bitLenInt, const std::vector< bitLenInt > &)
Definition: qunit.hpp:771
virtual void SetTInjection(bool useGadget)
Set the option to use T-injection gadgets (off by default)
Definition: qunit.hpp:179
virtual QInterfacePtr EntangleRange(bitLenInt start, bitLenInt length, bool isForProb=false)
Definition: qunit.cpp:565
virtual bool TryDecompose(bitLenInt start, QInterfacePtr dest, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Attempt to Decompose() a bit range.
Definition: qunit.hpp:365
virtual void LossySaveStateVector(std::string f, int p=6, int b=4)
Write the quantum state to disk with lossy compression.
Definition: qunit_turboquant.cpp:105
virtual bool Detach(bitLenInt start, bitLenInt length, QUnitPtr dest, bool isTry=false, real1_f tol=TRYDECOMPOSE_EPSILON)
Definition: qunit.cpp:300
void ShardAI(bitLenInt qubit, real1_f azimuth, real1_f inclination)
Definition: qunit.hpp:1156
virtual void GetProbs(real1 *outputProbs)
Get the pure quantum state representation.
Definition: qunit.hpp:301
void ClampShard(bitLenInt qubit)
Definition: qunit.hpp:887
virtual void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qunit.hpp:345
bool isAce
Definition: qunit.hpp:42
virtual bool M(bitLenInt q)
Definition: qunit.hpp:459
void TransformPhase(const complex &topLeft, const complex &bottomRight, complex *mtrxOut)
Definition: qunit.hpp:941
virtual void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qunit.cpp:3793
bitLenInt thresholdQubits
Definition: qunit.hpp:45
void DirtyShardIndexVector(std::vector< bitLenInt > bitIndices)
Definition: qunit.hpp:1284
bool INTSOptimize(const bitCapInt &toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt overflowIndex)
Check if overflow arithmetic can be optimized.
Definition: qunit.cpp:2881
void ConvertZToY(bitLenInt i)
Definition: qunit.hpp:1128
std::vector< QInterfaceEngine > engines
Definition: qunit.hpp:54
void RevertBasisY(bitLenInt i)
Definition: qunit.hpp:965
virtual bool GetReactiveSeparate()
Get reactive separation option.
Definition: qunit.hpp:216
bool TrimControls(const std::vector< bitLenInt > &controls, std::vector< bitLenInt > &controlVec, bitCapInt *perm)
Definition: qunit.cpp:2549
virtual void SetDeviceList(std::vector< int64_t > dIDs)
Set the device index list, if more than one device is available.
Definition: qunit.cpp:3805
virtual ~QUnit()
Definition: qunit.hpp:165
double logFidelity
Definition: qunit.hpp:49
QUnit(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 ignored=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > devIDs={}, bitLenInt qubitThreshold=0U, real1_f separation_thresh=_qrack_qunit_sep_thresh)
Definition: qunit.hpp:155
void ToPermBasis(bitLenInt start, bitLenInt length)
Definition: qunit.hpp:1224
RevertAnti
Definition: qunit.hpp:1181
@ ONLY_ANTI
Definition: qunit.hpp:1181
@ CTRL_AND_ANTI
Definition: qunit.hpp:1181
@ ONLY_CTRL
Definition: qunit.hpp:1181
void RevertBasisToX1Qb(bitLenInt i)
Definition: qunit.hpp:1016
void CMULModx(CMULModFn fn, const bitCapInt &toMod, const bitCapInt &modN, bitLenInt start, bitLenInt carryStart, bitLenInt length, std::vector< bitLenInt > controlVec)
Definition: qunit.cpp:3398
virtual void SetAmplitude(const bitCapInt &perm, const complex &amp)
Sets the representational amplitude of a full permutation.
Definition: qunit.hpp:304
void ApplyBuffer(PhaseShardPtr phaseShard, bitLenInt control, bitLenInt target, bool isAnti)
Definition: qunit.cpp:3940
virtual void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qunit.hpp:360
int64_t devID
Definition: qunit.hpp:50
void RevertBasis2Qb(bitLenInt i, RevertExclusivity exclusivity=INVERT_AND_PHASE, RevertControl controlExclusivity=CONTROLS_AND_TARGETS, RevertAnti antiExclusivity=CTRL_AND_ANTI, const std::set< bitLenInt > &exceptControlling={}, const std::set< bitLenInt > &exceptTargetedBy={}, bool dumpSkipped=false, bool skipOptimized=false)
Definition: qunit.cpp:4129
virtual void SetUseExactNearClifford(bool useExact)
Set the option to use exact-method near-Clifford simulation (on by default)
Definition: qunit.hpp:191
virtual bool TrySeparateClifford(bitLenInt qubit)
Definition: qunit.cpp:663
bool isCpu
Definition: qunit.hpp:39
bool freezeBasis2Qb
Definition: qunit.hpp:33
bool isSinglePage
Definition: qunit.hpp:40
virtual bitCapInt GetCachedPermutation(bitLenInt start, bitLenInt length)
Assuming all bits in the range are in cached |0>/|1> eigenstates, read the unsigned integer value of ...
Definition: qunit.cpp:941
bool(* ParallelUnitFn)(QInterfacePtr unit, real1_f param1, real1_f param2, real1_f param3, int64_t param4, std::vector< int64_t > param5)
Definition: qunit.hpp:861
virtual QInterfacePtr CloneBody(QUnitPtr copyPtr, bool isCopy)
Definition: qunit.cpp:3907
virtual int64_t GetDevice()
Get the device index.
Definition: qunit.hpp:220
void RevertBasisToY1Qb(bitLenInt i)
Definition: qunit.hpp:1031
void DirtyShardRange(bitLenInt start, bitLenInt length)
Definition: qunit.hpp:1260
QInterfacePtr CMULEntangle(std::vector< bitLenInt > controlVec, bitLenInt start, bitLenInt carryStart, bitLenInt length, std::vector< bitLenInt > *controlsMapped)
Definition: qunit.cpp:3349
virtual void XBase(bitLenInt target)
Definition: qunit.hpp:715
bitLenInt aceQubits
Definition: qunit.hpp:44
void ElideCz(const bool &isAnti, const bitLenInt &control, const bitLenInt &target, const real1_f &pth, const real1_f &pc)
Definition: qunit.hpp:119
void ToPermBasisProb(bitLenInt start, bitLenInt length)
Definition: qunit.hpp:1238
void TransformX2x2(const complex mtrxIn[4U], complex mtrxOut[4U])
Definition: qunit.hpp:909
virtual bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Compose() a QInterface peer, inserting its qubit into index order at start index.
Definition: qunit.hpp:341
void ToPermBasis(bitLenInt i)
Definition: qunit.hpp:1219
virtual bool TryDecompose(bitLenInt start, QUnitPtr dest, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qunit.hpp:369
virtual complex GetAmplitude(const bitCapInt &perm)
Get the representational amplitude of a full permutation.
Definition: qunit.cpp:255
virtual void SetSparseProbabilityFloor(real1_f p)
Set the sparse-simulation amplitude probability floor, before truncation.
Definition: qunit.hpp:203
virtual real1_f ACProbRdm(bitLenInt control, bitLenInt target)
Definition: qunit.hpp:244
virtual void SetPermutation(const bitCapInt &perm, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qunit.cpp:153
virtual bool AreFactorized(std::vector< bitLenInt > a, std::vector< bitLenInt > b, bool flushCache=false)
Check if two vectors of qubit indices are factorized, in internal representation.
Definition: qunit.hpp:253
bitLenInt FindShardIndex(QEngineShardPtr shard)
Definition: qunit.hpp:1319
RevertControl
Definition: qunit.hpp:1180
@ ONLY_TARGETS
Definition: qunit.hpp:1180
@ CONTROLS_AND_TARGETS
Definition: qunit.hpp:1180
@ ONLY_CONTROLS
Definition: qunit.hpp:1180
virtual QInterfacePtr EntangleAll(bool isForProb=false)
Definition: qunit.hpp:844
void ToPermBasisMeasure(bitLenInt qubit)
Definition: qunit.hpp:1249
bitCapInt GetIndexedEigenstate(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, const unsigned char *values)
Definition: qunit.cpp:3495
virtual void Copy(QInterfacePtr orig)
Definition: qunit.hpp:58
bool INTCOptimize(const bitCapInt &toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt carryIndex)
Check if carry arithmetic can be optimized.
Definition: qunit.cpp:2887
std::vector< bitLenInt > CMULEntangle(std::vector< bitLenInt > controlVec, bitLenInt start, const bitCapInt &carryStart, bitLenInt length)
virtual void GetQuantumStateOrProbs(complex *outputState, real1 *outputProbs)
Definition: qunit.cpp:215
virtual bitLenInt Compose(QUnitPtr toCopy)
Definition: qunit.hpp:319
virtual std::vector< int64_t > GetDeviceList()
Get the device index.
Definition: qunit.hpp:221
virtual void Decompose(bitLenInt start, QUnitPtr dest)
Definition: qunit.hpp:349
void TransformXInvert(const complex &topRight, const complex &bottomLeft, complex mtrxOut[4U])
Definition: qunit.hpp:917
void INCxx(INCxxFn fn, const bitCapInt &toMod, bitLenInt start, bitLenInt length, bitLenInt flag1Index, bitLenInt flag2Index)
Definition: qunit.cpp:2852
void INCx(INCxFn fn, const bitCapInt &toMod, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
Definition: qunit.cpp:2833
QUnit(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 ignored=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > devIDs={}, bitLenInt qubitThreshold=0U, real1_f separation_thresh=_qrack_qunit_sep_thresh)
Definition: qunit.cpp:73
virtual void Copy(QUnitPtr orig)
Definition: qunit.hpp:59
virtual void SetConcurrency(uint32_t threadsPerEngine)
Set the number of threads in parallel for loops, per component QEngine.
Definition: qunit.hpp:167
void ConvertZToX(bitLenInt i)
Definition: qunit.hpp:1046
bool isSparse
Definition: qunit.hpp:41
void CommuteH(bitLenInt bitIndex)
Definition: qunit.cpp:4185
virtual bool TrySeparate(const std::vector< bitLenInt > &qubits, real1_f error_tol)
Qrack::QUnit types maintain explicit separation of representations of qubits, which reduces memory us...
Definition: qinterface.hpp:2925
void ApplyBufferMap(bitLenInt bitIndex, ShardToPhaseMap bufferMap, RevertExclusivity exclusivity, bool isControl, bool isAnti, const std::set< bitLenInt > &exceptPartners, bool dumpSkipped)
Definition: qunit.cpp:4062
void(QAlu::* INCxxFn)(const bitCapInt &, bitLenInt, bitLenInt, bitLenInt, bitLenInt)
Definition: qunit.hpp:769
virtual void Dispose(bitLenInt start, bitLenInt length, const bitCapInt &disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qunit.hpp:361
void ConvertXToY(bitLenInt i)
Definition: qunit.hpp:1071
RevertExclusivity
Definition: qunit.hpp:1179
@ ONLY_INVERT
Definition: qunit.hpp:1179
@ ONLY_PHASE
Definition: qunit.hpp:1179
@ INVERT_AND_PHASE
Definition: qunit.hpp:1179
virtual bitLenInt Compose(QUnitPtr toCopy, bitLenInt start)
Definition: qunit.hpp:321
virtual real1_f ProbRdm(bitLenInt qubit)
Direct measure of bit probability to be in |1> state, treating all ancillary qubits as post-selected ...
Definition: qunit.hpp:223
void DirtyShardRangePhase(bitLenInt start, bitLenInt length)
Definition: qunit.hpp:1272
void Flush0Eigenstate(bitLenInt i)
Definition: qunit.hpp:1191
bool isBdt
Definition: qunit.hpp:38
virtual void LossyLoadStateVector(std::string f)
Read the quantum state from disk with lossy compression.
Definition: qunit_turboquant.cpp:227
QEngineShardMap shards
Definition: qunit.hpp:52
size_t aceMb
Definition: qunit.hpp:43
bool INTSCOptimize(const bitCapInt &toMod, bitLenInt start, bitLenInt length, bool isAdd, bitLenInt carryIndex, bitLenInt overflowIndex)
Check if arithmetic with both carry and overflow can be optimized.
Definition: qunit.cpp:2893
void TransformY2x2(const complex mtrxIn[4U], complex mtrxOut[4U])
Definition: qunit.hpp:925
bool useHostRam
Definition: qunit.hpp:34
void EndEmulation(bitLenInt target)
Definition: qunit.hpp:1296
void(QAlu::* CMULFn)(const bitCapInt &, bitLenInt, bitLenInt, bitLenInt, const std::vector< bitLenInt > &)
Definition: qunit.hpp:770
virtual void SetQuantumState(const complex *inputState)
Set an arbitrary pure quantum state representation.
Definition: qunit.cpp:166
void TransformYInvert(const complex &topRight, const complex &bottomLeft, complex mtrxOut[4U])
Definition: qunit.hpp:933
void RevertBasisX(bitLenInt i)
Definition: qunit.hpp:949
virtual void ZBase(bitLenInt target)
Definition: qunit.hpp:747
Half-precision floating-point type.
Definition: half.hpp:2206
virtual void MULModNOut(const bitCapInt &toMul, const bitCapInt &modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Multiplication modulo N by integer, (out of place)
Definition: arithmetic.cpp:127
virtual 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: qunit.cpp:3520
virtual 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: qunit.cpp:3318
virtual void CMUL(const bitCapInt &toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled multiplication by integer.
Definition: qunit.cpp:3410
virtual void DECS(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Subtract a classical integer from the register, with sign and without carry.
Definition: qinterface.hpp:2225
virtual void DECS(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qunit.hpp:473
virtual 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: qunit.cpp:3556
virtual void INCDECBCDC(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (without overflow flag)
Definition: qunit.cpp:3241
virtual void INCDECC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCC and DECC.
Definition: arithmetic.cpp:53
virtual 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: qunit.hpp:501
virtual 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: qunit.cpp:3698
virtual void CINC(const bitCapInt &toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: arithmetic.cpp:79
virtual void INCBCD(const bitCapInt &toAdd, bitLenInt start, bitLenInt length)
Add classical BCD integer (without sign)
Definition: qunit.cpp:3219
virtual void Hash(bitLenInt start, bitLenInt length, const unsigned char *values)
Transform a length of qubit register via lookup through a hash table.
Definition: qunit.cpp:3658
virtual void INC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qunit.cpp:3119
virtual void DEC(const bitCapInt &toSub, bitLenInt start, bitLenInt length)
Subtract classical integer (without sign)
Definition: qinterface.hpp:2166
virtual void CDIV(const bitCapInt &toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Controlled division by power of integer.
Definition: qunit.cpp:3439
virtual void INCC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: qunit.cpp:3125
virtual void DECBCD(const bitCapInt &toAdd, bitLenInt start, bitLenInt length)
Subtract classical BCD integer (without sign)
Definition: qunit.cpp:3230
virtual void MULModNOut(const bitCapInt &toMul, const bitCapInt &modN, bitLenInt inStart, bitLenInt outStart, bitLenInt length)
Multiplication modulo N by integer, (out of place)
Definition: qunit.hpp:491
virtual void DECC(const bitCapInt &toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract integer (without sign, with carry)
Definition: qunit.cpp:3136
virtual 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: qunit.cpp:3468
virtual void DEC(const bitCapInt &toSub, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: qunit.hpp:469
virtual void CINC(const bitCapInt &toAdd, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Add integer (without sign, with controls)
Definition: qunit.hpp:477
virtual 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: qunit.cpp:3607
virtual void INCS(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add a classical integer to the register, with sign and without carry.
Definition: qunit.cpp:3202
virtual 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: arithmetic.cpp:165
virtual void MUL(const bitCapInt &toMul, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Multiply by integer.
Definition: qunit.cpp:3248
virtual void CDEC(const bitCapInt &toSub, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Subtract classical integer (without sign, with controls)
Definition: qinterface.hpp:2206
virtual 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: qunit.hpp:506
virtual 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: qunit.cpp:3678
virtual 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: arithmetic.cpp:201
virtual 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: arithmetic.cpp:240
virtual 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: qunit.hpp:496
virtual void INCDECC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Common driver method behind INCC and DECC (without sign, with carry)
Definition: qunit.hpp:487
virtual void INCDECSC(const bitCapInt &toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Common driver method behind INCSC and DECSC (with overflow flag)
Definition: qunit.cpp:3207
virtual void DIV(const bitCapInt &toDiv, bitLenInt inOutStart, bitLenInt carryStart, bitLenInt length)
Divide by integer.
Definition: qunit.cpp:3282
virtual void CDEC(const bitCapInt &toSub, bitLenInt inOutStart, bitLenInt length, const std::vector< bitLenInt > &controls)
Subtract integer (without sign, with controls)
Definition: qunit.hpp:482
virtual void MCMtrx(const std::vector< bitLenInt > &controls, const complex mtrx[4U], bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: qunit.hpp:422
virtual void CSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a swap with arbitrary control bits.
Definition: qunit.cpp:2519
virtual void MACPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase, with arbitrary (anti-)control bits.
Definition: qunit.hpp:407
virtual void CNOT(bitLenInt control, bitLenInt target)
Controlled NOT gate.
Definition: qinterface.hpp:727
virtual void IS(bitLenInt qubit)
Inverse S gate.
Definition: qinterface.hpp:1052
virtual void MACInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunit.hpp:412
virtual void S(bitLenInt qubit)
S gate.
Definition: qinterface.hpp:1045
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 bool ForceM(bitLenInt qubit, bool result, bool doForce=true, bool doApply=true)=0
Act as if is a measurement was applied, except force the (usually random) result.
virtual void UCMtrx(const std::vector< bitLenInt > &controls, const complex mtrx[4U], bitLenInt target, const bitCapInt &controlPerm)
Definition: qunit.cpp:2488
virtual void H(bitLenInt qubit)
Hadamard gate.
Definition: qinterface.hpp:931
virtual void MCPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase, with arbitrary control bits.
Definition: qunit.hpp:393
virtual bitCapInt HighestProbAll()
Get highest probability permutation.
Definition: qunit.cpp:1501
virtual void MACMtrx(const std::vector< bitLenInt > &controls, const complex mtrx[4U], bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
Definition: qunit.hpp:428
virtual void AntiCSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a square root of swap with arbitrary (anti) control bits.
Definition: qunit.cpp:2534
virtual void Mtrx(const complex mtrx[4U], bitLenInt qubit)
Apply an arbitrary single bit unitary transformation.
Definition: qunit.cpp:2433
virtual void CSqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a square root of swap with arbitrary control bits.
Definition: qunit.cpp:2529
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1116
virtual void ZMask(const bitCapInt &mask)
Masked Z gate.
Definition: qunit.hpp:388
virtual void AntiCNOT(bitLenInt control, bitLenInt target)
Anti controlled NOT gate.
Definition: qinterface.hpp:738
virtual void AntiCSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply a swap with arbitrary (anti) control bits.
Definition: qunit.cpp:2524
virtual void AntiCISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply an inverse square root of swap with arbitrary (anti) control bits.
Definition: qunit.cpp:2544
virtual void UCInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt target, const bitCapInt &controlPerm)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunit.cpp:2371
virtual 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: qunit.cpp:1242
virtual void PhaseParity(real1_f radians, const bitCapInt &mask)
Parity phase gate.
Definition: qunit.cpp:1043
virtual void U(bitLenInt target, real1_f theta, real1_f phi, real1_f lambda)
General unitary gate.
Definition: rotational.cpp:18
virtual void MCInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunit.hpp:400
virtual void Phase(const complex &topLeft, const complex &bottomRight, bitLenInt qubitIndex)
Apply a single bit transformation that only effects phase.
Definition: qunit.cpp:2191
virtual void Invert(const complex &topRight, const complex &bottomLeft, bitLenInt qubitIndex)
Apply a single bit transformation that reverses bit probability and might effect phase.
Definition: qunit.cpp:2251
virtual bool M(bitLenInt qubit)
Measurement gate.
Definition: qinterface.hpp:1031
virtual std::map< bitCapInt, int > MultiShotMeasureMask(const std::vector< bitCapInt > &qPowers, unsigned shots)
Statistical measure of masked permutation probability.
Definition: qunit.cpp:1583
virtual bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: qunit.cpp:1534
virtual void UCPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt target, const bitCapInt &controlPerm)
Apply a single bit transformation that only effects phase, with arbitrary control bits,...
Definition: qunit.cpp:2303
virtual void CISqrtSwap(const std::vector< bitLenInt > &controls, bitLenInt qubit1, bitLenInt qubit2)
Apply an inverse square root of swap with arbitrary control bits.
Definition: qunit.cpp:2539
virtual void SetReg(bitLenInt start, bitLenInt length, const bitCapInt &value)
Set register bits to given permutation.
Definition: qunit.cpp:1784
virtual bitCapInt ForceMReg(bitLenInt start, bitLenInt length, const bitCapInt &result, bool doForce=true, bool doApply=true)
Act as if is a measurement was applied, except force the (usually random) result.
Definition: qinterface.cpp:215
virtual void Swap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register.
Definition: qunit.hpp:554
virtual void SqrtSwap(bitLenInt qubit1, bitLenInt qubit2)
Square root of Swap gate.
Definition: qunit.cpp:1863
virtual void IISwap(bitLenInt qubit1, bitLenInt qubit2)
Inverse ISwap - Swap values of two bits in register, and apply phase factor of -i if bits are differe...
Definition: qunit.hpp:572
virtual void ISqrtSwap(bitLenInt qubit1, bitLenInt qubit2)
Inverse square root of Swap gate.
Definition: qunit.cpp:1897
virtual void ISwap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: qunit.hpp:571
virtual void SetNcrp(real1_f ncrp)
Set the "Near-clifford rounding parameter" value, (between 0 and 1)
Definition: qunit.hpp:693
virtual real1_f VarianceBitsFactorized(const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get expectation value of bits, given an array of qubit weights.
Definition: qunit.hpp:628
virtual real1_f ExpectationBitsFactorizedRdm(bool roundRz, const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get (reduced density matrix) expectation value of bits, given an array of qubit weights.
Definition: qunit.hpp:623
virtual bool TrySeparate(const std::vector< bitLenInt > &qubits, real1_f error_tol)
Qrack::QUnit types maintain explicit separation of representations of qubits, which reduces memory us...
Definition: qunit.hpp:665
virtual bool isClifford()
Returns "true" if current state is identifiably within the Clifford set, or "false" if it is not or c...
Definition: qinterface.hpp:2899
virtual 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: qunit.cpp:3756
virtual real1_f ProbParity(const bitCapInt &mask)
Overall probability of any odd permutation of the masked set of bits.
Definition: qunit.cpp:1119
virtual QInterfacePtr Copy()
Copy this QInterface.
Definition: qunit.cpp:3898
virtual QInterfacePtr Copy()
Copy this QInterface.
Definition: qinterface.hpp:3058
virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
Calculates (1 - <\psi_e|\psi_c>) between states |\psi_c> and |\psi_e>.
Definition: qunit.hpp:613
virtual bool isFinished()
Returns "false" if asynchronous work is still running, and "true" if all previously dispatched asynch...
Definition: qunit.cpp:3787
virtual void SetSparseAceMaxMb(size_t mb)
Set the (sparse-simulation) "automatic circuit elision" (ACE) maximum memory megabytes.
Definition: qunit.hpp:705
virtual real1_f ExpectationBitsFactorized(const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get expectation value of bits, given an array of qubit weights.
Definition: qunit.hpp:618
virtual bool isClifford(bitLenInt qubit)
Returns "true" if current qubit state is identifiably within the Clifford set, or "false" if it is no...
Definition: qunit.hpp:653
virtual QInterfacePtr Clone()
Clone this QInterface.
Definition: qunit.cpp:3890
virtual real1_f ProbAllRdm(bool roundRz, const bitCapInt &perm)
Direct measure of full permutation probability, treating all ancillary qubits as post-selected T gate...
Definition: qunit.hpp:594
virtual 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: qunit.cpp:3767
virtual real1_f VarianceBitsFactorizedRdm(bool roundRz, const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get (reduced density matrix) expectation value of bits, given an array of qubit weights.
Definition: qunit.hpp:633
virtual double GetUnitaryFidelity()
When "Schmidt-decomposition rounding parameter" ("SDRP") is being used, starting from initial 1....
Definition: qunit.cpp:3724
virtual void SetSdrp(real1_f sdrp)
Set the "Schmidt decomposition rounding parameter" value, (between 0 and 1)
Definition: qunit.hpp:688
virtual real1_f ProbAll(const bitCapInt &perm)
Direct measure of full permutation probability.
Definition: qunit.hpp:593
virtual real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qunit.hpp:584
virtual void ResetUnitaryFidelity()
Reset the internal fidelity calculation tracker to 1.0.
Definition: qunit.hpp:687
virtual void SetAceMaxQubits(bitLenInt qb)
Set the "automatic circuit elision" (ACE) maximum entangled subsystem qubit count.
Definition: qunit.hpp:704
virtual void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qunit.hpp:643
virtual bool TrySeparate(const std::vector< bitLenInt > &qubits, real1_f error_tol)
Qrack::QUnit types maintain explicit separation of representations of qubits, which reduces memory us...
Definition: qinterface.hpp:2925
virtual void Finish()
If asynchronous work is still running, block until it finishes.
Definition: qunit.cpp:3778
virtual 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: qunit.cpp:1177
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
void ThrowIfQbIdArrayIsBad(const std::vector< bitLenInt > &controls, const bitLenInt &qubitCount, std::string message)
Definition: qrack_functions.hpp:198
QRACK_CONST real1_f FP_NORM_EPSILON_F
Definition: qrack_types.hpp:264
QRACK_CONST real1 SQRT1_2_R1
Definition: qrack_types.hpp:182
@ QINTERFACE_STABILIZER_HYBRID
Create a QStabilizerHybrid, switching between a QStabilizer and a QHybrid as efficient.
Definition: qinterface.hpp:77
std::shared_ptr< QUnit > QUnitPtr
Definition: qunit.hpp:24
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
QRACK_CONST real1 HALF_R1
Definition: qrack_types.hpp:187
std::shared_ptr< PhaseShard > PhaseShardPtr
Definition: qengineshard.hpp:46
half_float::half real1
Definition: qrack_types.hpp:106
std::complex< real1 > complex
Definition: qrack_types.hpp:140
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:263
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:156
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:122
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:203
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:257
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:188
QRACK_CONST real1 ZERO_R1
Definition: qrack_types.hpp:186
float real1_f
Definition: qrack_types.hpp:107
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:262
QRACK_CONST complex I_CMPLX
Definition: qrack_types.hpp:259
std::map< QEngineShardPtr, PhaseShardPtr > ShardToPhaseMap
Definition: qengineshard.hpp:47
@ PauliX
Pauli X operator. Corresponds to Q# constant "PauliX.".
Definition: pauli.hpp:23
@ PauliY
Pauli Y operator. Corresponds to Q# constant "PauliY.".
Definition: pauli.hpp:25
@ PauliZ
Pauli Z operator. Corresponds to Q# constant "PauliZ.".
Definition: pauli.hpp:27
const double FIDELITY_MIN
Definition: qrack_types.hpp:266
QRACK_CONST real1 PI_R1
Definition: qrack_types.hpp:180
const bitCapInt ONE_BCI
Definition: qrack_types.hpp:141
const bitCapInt ZERO_BCI
Definition: qrack_types.hpp:142
HALF_CONSTEXPR half abs(half arg)
Absolute value.
Definition: half.hpp:2958
half sin(half arg)
Sine function.
Definition: half.hpp:3868
half log(half arg)
Natural logarithm.
Definition: half.hpp:3301
half cos(half arg)
Cosine function.
Definition: half.hpp:3905
#define REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:179
#define QRACK_CONST
Definition: qrack_types.hpp:176
#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 ONE_R1_F
Definition: qrack_types.hpp:165
#define IS_NORM_0(c)
Definition: qrack_types.hpp:28
Definition: qunit.hpp:873
bool operator<(const QSortEntry &rhs)
Definition: qunit.hpp:876
bitLenInt mapped
Definition: qunit.hpp:875
bool operator>(const QSortEntry &rhs)
Definition: qunit.hpp:877
bitLenInt bit
Definition: qunit.hpp:874