Qrack  9.13
General classical-emulating-quantum development framework
qunitclifford.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // QUnitClifford maintains explicit separability of qubits as an optimization on a
6 // QStabilizer. 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 "qstabilizer.hpp"
16 #include "qunitstatevector.hpp"
17 
18 namespace Qrack {
19 
20 class QUnitClifford;
21 typedef std::shared_ptr<QUnitClifford> QUnitCliffordPtr;
22 
23 struct CliffordShard {
26 
28  : mapped(m)
29  , unit(u)
30  {
31  // Intentionally left blank
32  }
33 
35  : mapped(o.mapped)
36  , unit(o.unit)
37  {
38  // Intentionally left blank
39  }
40 };
41 
42 class QUnitClifford : public QInterface {
43 protected:
45  std::vector<CliffordShard> shards;
46 
47  using QInterface::Copy;
48  void Copy(QInterfacePtr orig) { Copy(std::dynamic_pointer_cast<QUnitClifford>(orig)); }
50  {
51  QInterface::Copy(std::dynamic_pointer_cast<QInterface>(orig));
52  phaseOffset = orig->phaseOffset;
53  shards = orig->shards;
54  }
55 
57  {
58  if (randGlobalPhase) {
59  return;
60  }
61 
62  phaseOffset *= unit->GetPhaseOffset();
63  unit->ResetPhaseOffset();
64  }
65 
66  struct QSortEntry {
69  bool operator<(const QSortEntry& rhs) { return mapped < rhs.mapped; }
70  bool operator>(const QSortEntry& rhs) { return mapped > rhs.mapped; }
71  };
72  void SortUnit(QStabilizerPtr unit, std::vector<QSortEntry>& bits, bitLenInt low, bitLenInt high);
73 
74  void Detach(bitLenInt start, bitLenInt length, QUnitCliffordPtr dest);
75 
77  std::vector<bitLenInt*>::iterator first, std::vector<bitLenInt*>::iterator last);
78 
80  {
81  if (!qubitCount) {
82  return MakeStabilizer(0U);
83  }
84  std::vector<bitLenInt> bits(qubitCount);
85  std::vector<bitLenInt*> ebits(qubitCount);
86  for (bitLenInt i = 0U; i < qubitCount; ++i) {
87  bits[i] = i;
88  ebits[i] = &bits[i];
89  }
90 
91  QStabilizerPtr toRet = EntangleInCurrentBasis(ebits.begin(), ebits.end());
92  OrderContiguous(toRet);
93 
94  return toRet;
95  }
96 
98 
99  typedef std::function<void(QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx)>
101  typedef std::function<void(QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx)> GateFn;
102  typedef std::function<void(QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t)> SwapGateFn;
103  void CGate(bitLenInt control, bitLenInt target, const complex* mtrx, CGateFn cfn, GateFn fn, bool isAnti)
104  {
105  ThrowIfQubitInvalid(target, "QUnitClifford::CGate");
106  const real1_f p = Prob(control);
107  if (p < (ONE_R1_F / 4)) {
108  if (isAnti) {
109  fn(shards[target].unit, target, mtrx);
110  }
111  return;
112  } else if (p > (3 * ONE_R1_F / 4)) {
113  if (!isAnti) {
114  fn(shards[target].unit, target, mtrx);
115  }
116  return;
117  }
118 
119  std::vector<bitLenInt> bits{ control, target };
120  std::vector<bitLenInt*> ebits{ &bits[0U], &bits[1U] };
121  QStabilizerPtr unit = EntangleInCurrentBasis(ebits.begin(), ebits.end());
122  cfn(unit, bits[0U], bits[1U], mtrx);
123  CombinePhaseOffsets(unit);
124  TrySeparate(control);
125  TrySeparate(target);
126  }
127  void SwapGate(bitLenInt control, bitLenInt target, SwapGateFn ufn, const complex& phaseFac)
128  {
129  const real1_f pc = Prob(control);
130  const real1_f pt = Prob(target);
131  if (((pc < (ONE_R1_F / 4)) && (pt > (3 * ONE_R1_F / 4))) ||
132  ((pt < (ONE_R1_F / 4)) && (pc > (3 * ONE_R1_F / 4)))) {
133  Swap(control, target);
134  Phase(phaseFac, phaseFac, target);
135  return;
136  }
137  std::vector<bitLenInt> bits{ control, target };
138  std::vector<bitLenInt*> ebits{ &bits[0U], &bits[1U] };
139  QStabilizerPtr unit = EntangleInCurrentBasis(ebits.begin(), ebits.end());
140  ufn(unit, bits[0U], bits[1U]);
141  CombinePhaseOffsets(unit);
142  TrySeparate(control);
143  TrySeparate(target);
144  }
145 
147 
148  bool SeparateBit(bool value, bitLenInt qubit);
149 
150  void ThrowIfQubitInvalid(bitLenInt t, std::string methodName)
151  {
152  if (t >= qubitCount) {
153  throw std::invalid_argument(
154  methodName + std::string(" target qubit index parameter must be within allocated qubit bounds!"));
155  }
156  }
157 
158  bitLenInt ThrowIfQubitSetInvalid(const std::vector<bitLenInt>& controls, bitLenInt t, std::string methodName)
159  {
160  if (t >= qubitCount) {
161  throw std::invalid_argument(
162  methodName + std::string(" target qubit index parameter must be within allocated qubit bounds!"));
163  }
164  if (controls.size() > 1U) {
165  throw std::invalid_argument(methodName + std::string(" can only have one control qubit!"));
166  }
167  const bitLenInt c = controls[0U];
168  if (c >= qubitCount) {
169  throw std::invalid_argument(
170  methodName + std::string(" control qubit index parameter must be within allocated qubit bounds!"));
171  }
172 
173  return controls[0U];
174  }
175 
176  real1_f ExpVarBitsFactorized(bool isExp, const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms,
177  const bitCapInt& offset = ZERO_BCI);
178 
179  real1_f ExpVarFloatsFactorized(bool isExp, const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights);
180 
181 public:
182  QUnitClifford(bitLenInt n, const bitCapInt& perm = ZERO_BCI, qrack_rand_gen_ptr rgp = nullptr,
183  const complex& phasFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
184  bool ignored2 = false, int64_t ignored3 = -1, bool useHardwareRNG = true, bool ignored4 = false,
185  real1_f ignored5 = REAL1_EPSILON, std::vector<int64_t> ignored6 = {}, bitLenInt ignored7 = 0U,
186  real1_f ignored8 = _qrack_qunit_sep_thresh);
187 
189 
191  {
192  QUnitCliffordPtr copyPtr = std::make_shared<QUnitClifford>(
194 
195  return CloneBody(copyPtr);
196  }
198  {
199  return std::make_shared<QUnitClifford>(
201  }
202 
203  bool isClifford() { return true; };
204  bool isClifford(bitLenInt qubit) { return true; };
205 
207 
209 
210  void SetDevice(int64_t dID) {}
211 
212  void SetRandGlobalPhase(bool isRand)
213  {
214  for (bitLenInt i = 0U; i < qubitCount; ++i) {
215  shards[i].unit->SetRandGlobalPhase(isRand);
216  }
217  }
218 
221 
223  {
224  std::map<QStabilizerPtr, QStabilizerPtr> engines;
225  bitCapInt permCount = ONE_BCI;
226  for (bitLenInt i = 0U; i < qubitCount; ++i) {
227  QStabilizerPtr unit = shards[i].unit;
228  if (engines.find(unit) == engines.end()) {
229  const bitCapInt pg = pow2(unit->gaussian());
230  // This would be "*", but Schmidt decomposition makes it "+".
231  permCount = permCount + pg;
232  }
233  }
234 
235  return permCount;
236  }
237 
238  void Clear()
239  {
240  shards = std::vector<CliffordShard>();
242  qubitCount = 0U;
243  maxQPower = ONE_BCI;
244  }
245 
247  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
248  {
249  return ExpVarBitsFactorized(true, bits, perms, offset);
250  }
251 
252  real1_f ExpectationFloatsFactorized(const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights)
253  {
254  return ExpVarFloatsFactorized(true, bits, weights);
255  }
256 
258  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI)
259  {
260  return ExpVarBitsFactorized(false, bits, perms, offset);
261  }
262 
263  real1_f VarianceFloatsFactorized(const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights)
264  {
265  return ExpVarFloatsFactorized(false, bits, weights);
266  }
267 
268  real1_f ProbPermRdm(const bitCapInt& perm, bitLenInt ancillaeStart);
269 
270  real1_f ProbMask(const bitCapInt& mask, const bitCapInt& permutation);
271 
272  void SetPermutation(const bitCapInt& perm, const complex& phaseFac = CMPLX_DEFAULT_ARG);
273 
275  bitLenInt length = 1U, const bitCapInt& perm = ZERO_BCI, const complex& phaseFac = CMPLX_DEFAULT_ARG)
276  {
277  QStabilizerPtr toRet = std::make_shared<QStabilizer>(
278  length, perm, rand_generator, phaseFac, false, randGlobalPhase, false, -1, useRDRAND);
279 
280  return toRet;
281  }
282 
283  void SetQuantumState(const complex* inputState);
284  void SetAmplitude(const bitCapInt& perm, const complex& amp)
285  {
286  throw std::domain_error("QUnitClifford::SetAmplitude() not implemented!");
287  }
288 
291  {
292  H(t);
293  if (IsSeparableZ(t)) {
294  CZ(c, t);
295  H(t);
296  return;
297  }
298  H(t);
299  CGate(
300  c, t, NULL,
301  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
302  unit->CNOT(c, t);
303  },
304  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->X(t); }, false);
305  }
307  void CY(bitLenInt c, bitLenInt t)
308  {
309  CGate(
310  c, t, NULL,
311  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) { unit->CY(c, t); },
312  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->Y(t); }, false);
313  }
315  void CZ(bitLenInt c, bitLenInt t)
316  {
317  const real1_f p = Prob(t);
318  if (p > (3 * ONE_R1_F / 4)) {
319  Z(c);
320  return;
321  }
322  CGate(
323  c, t, NULL,
324  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) { unit->CZ(c, t); },
325  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->Z(t); }, false);
326  }
329  {
330  H(t);
331  if (IsSeparableZ(t)) {
332  AntiCZ(c, t);
333  H(t);
334  return;
335  }
336  H(t);
337  CGate(
338  c, t, NULL,
339  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
340  unit->AntiCNOT(c, t);
341  },
342  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->X(t); }, true);
343  }
346  {
347  CGate(
348  c, t, NULL,
349  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
350  unit->AntiCY(c, t);
351  },
352  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->Y(t); }, true);
353  }
356  {
357  const real1_f p = Prob(t);
358  if (p > (3 * ONE_R1_F / 4)) {
359  Phase(-ONE_CMPLX, ONE_CMPLX, c);
360  return;
361  }
362  CGate(
363  c, t, NULL,
364  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
365  unit->AntiCZ(c, t);
366  },
367  [](QStabilizerPtr unit, const bitLenInt& t, const complex* unused) { unit->Z(t); }, true);
368  }
370  using QInterface::H;
371  void H(bitLenInt t)
372  {
373  ThrowIfQubitInvalid(t, std::string("QUnitClifford::H"));
374  CliffordShard& shard = shards[t];
375  shard.unit->H(shard.mapped);
376  }
378  void S(bitLenInt t)
379  {
380  ThrowIfQubitInvalid(t, std::string("QUnitClifford::S"));
381  CliffordShard& shard = shards[t];
382  shard.unit->S(shard.mapped);
383  CombinePhaseOffsets(shard.unit);
384  }
386  void IS(bitLenInt t)
387  {
388  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IS"));
389  CliffordShard& shard = shards[t];
390  shard.unit->IS(shard.mapped);
391  CombinePhaseOffsets(shard.unit);
392  }
394  void Z(bitLenInt t)
395  {
396  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Z"));
397  CliffordShard& shard = shards[t];
398  shard.unit->Z(shard.mapped);
399  CombinePhaseOffsets(shard.unit);
400  }
402  using QInterface::X;
403  void X(bitLenInt t)
404  {
405  ThrowIfQubitInvalid(t, std::string("QUnitClifford::X"));
406  CliffordShard& shard = shards[t];
407  shard.unit->X(shard.mapped);
408  }
410  void Y(bitLenInt t)
411  {
412  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Y"));
413  CliffordShard& shard = shards[t];
414  shard.unit->Y(shard.mapped);
415  CombinePhaseOffsets(shard.unit);
416  }
417  // Swap two bits
418  void Swap(bitLenInt qubit1, bitLenInt qubit2)
419  {
420  ThrowIfQubitInvalid(qubit1, std::string("QUnitClifford::Swap"));
421  ThrowIfQubitInvalid(qubit2, std::string("QUnitClifford::Swap"));
422 
423  if (qubit1 == qubit2) {
424  return;
425  }
426 
427  // Simply swap the bit mapping.
428  std::swap(shards[qubit1], shards[qubit2]);
429  }
430  // Swap two bits and apply a phase factor of i if they are different
432  {
433  SwapGate(
434  c, t, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t) { unit->ISwap(c, t); }, I_CMPLX);
435  }
436  // Swap two bits and apply a phase factor of -i if they are different
438  {
439  SwapGate(
440  c, t, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t) { unit->IISwap(c, t); }, -I_CMPLX);
441  }
442 
444  bool ForceM(bitLenInt t, bool result, bool doForce = true, bool doApply = true);
445 
448  {
449  bitCapInt toRet = QInterface::MAll();
450  SetPermutation(toRet);
451  return toRet;
452  }
453 
454  std::map<bitCapInt, int> MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots);
455 
456  void MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots, unsigned long long* shotsArray);
457 
459  void GetQuantumState(complex* stateVec);
460 
462  void GetQuantumState(QInterfacePtr eng);
463 
465  std::map<bitCapInt, complex> GetQuantumState();
466 
469 
471  void GetProbs(real1* outputProbs);
472 
474  complex GetAmplitude(const bitCapInt& perm);
475 
477  std::vector<complex> GetAmplitudes(std::vector<bitCapInt> perms);
478 
482  bool IsSeparableZ(const bitLenInt& t)
483  {
484  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableZ"));
485  CliffordShard& shard = shards[t];
486  return shard.unit->IsSeparableZ(shard.mapped);
487  }
488 
492  bool IsSeparableX(const bitLenInt& t)
493  {
494  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableX"));
495  CliffordShard& shard = shards[t];
496  return shard.unit->IsSeparableX(shard.mapped);
497  }
501  bool IsSeparableY(const bitLenInt& t)
502  {
503  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableY"));
504  CliffordShard& shard = shards[t];
505  return shard.unit->IsSeparableY(shard.mapped);
506  }
514  uint8_t IsSeparable(const bitLenInt& t)
515  {
516  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparable"));
517  CliffordShard& shard = shards[t];
518  return shard.unit->IsSeparable(shard.mapped);
519  }
520 
521  bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
522  {
523  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->CanDecomposeDispose(start, length);
524  }
525 
526  using QInterface::Compose;
527  bitLenInt Compose(QUnitCliffordPtr toCopy) { return Compose(toCopy, qubitCount); }
528  bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy)); }
530  {
531  if (start > qubitCount) {
532  throw std::invalid_argument("QUnit::Compose start index is out-of-bounds!");
533  }
534 
535  /* Create a clone of the quantum state in toCopy. */
536  QUnitCliffordPtr clone = std::dynamic_pointer_cast<QUnitClifford>(toCopy->Clone());
537 
538  /* Insert the new shards in the middle */
539  shards.insert(shards.begin() + start, clone->shards.begin(), clone->shards.end());
540 
541  SetQubitCount(qubitCount + toCopy->GetQubitCount());
542 
543  return start;
544  }
546  {
547  return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy), start);
548  }
550  {
551  Decompose(start, std::dynamic_pointer_cast<QUnitClifford>(dest));
552  }
553  void Decompose(bitLenInt start, QUnitCliffordPtr dest) { Detach(start, dest->GetQubitCount(), dest); }
555  {
556  QUnitCliffordPtr dest = std::make_shared<QUnitClifford>(
558 
559  Decompose(start, dest);
560 
561  return dest;
562  }
563  void Dispose(bitLenInt start, bitLenInt length) { Detach(start, length, nullptr); }
564  void Dispose(bitLenInt start, bitLenInt length, const bitCapInt& disposedPerm) { Detach(start, length, nullptr); }
565  using QInterface::Allocate;
567  {
568  if (!length) {
569  return start;
570  }
571 
572  if (start > qubitCount) {
573  throw std::out_of_range("QUnitClifford::Allocate() cannot start past end of register!");
574  }
575 
576  if (!qubitCount) {
577  SetQubitCount(length);
579  return 0U;
580  }
581 
582  QUnitCliffordPtr nQubits = std::make_shared<QUnitClifford>(length, ZERO_BCI, rand_generator, CMPLX_DEFAULT_ARG,
583  false, randGlobalPhase, false, -1, hardware_rand_generator != NULL);
584  return Compose(nQubits, start);
585  }
586 
588  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
589  {
590  if (!randGlobalPhase) {
591  phaseOffset *= std::polar(ONE_R1, (real1)phaseArg);
592  }
593  }
595  {
596  // Intentionally left blank
597  }
598 
599  virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
600  {
601  return SumSqrDiff(std::dynamic_pointer_cast<QUnitClifford>(toCompare));
602  }
603  virtual real1_f SumSqrDiff(QUnitCliffordPtr toCompare);
605  {
606  return ApproxCompare(std::dynamic_pointer_cast<QUnitClifford>(toCompare), error_tol);
607  }
609  {
610  if (!toCompare) {
611  return false;
612  }
613 
614  if (this == toCompare.get()) {
615  return true;
616  }
617 
618  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->ApproxCompare(
619  std::dynamic_pointer_cast<QUnitClifford>(toCompare->Clone())->EntangleAll(), error_tol);
620  }
621 
623  {
624  ThrowIfQubitInvalid(qubit, std::string("QUnitClifford::Prob"));
625  CliffordShard& shard = shards[qubit];
626  return shard.unit->Prob(shard.mapped);
627  }
628 
629  void Mtrx(const complex* mtrx, bitLenInt t)
630  {
631  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Mtrx"));
632  CliffordShard& shard = shards[t];
633  shard.unit->Mtrx(mtrx, shard.mapped);
634  CombinePhaseOffsets(shard.unit);
635  }
636  void Phase(const complex& topLeft, const complex& bottomRight, bitLenInt t)
637  {
638  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Phase"));
639  CliffordShard& shard = shards[t];
640  shard.unit->Phase(topLeft, bottomRight, shard.mapped);
641  CombinePhaseOffsets(shard.unit);
642  }
643  void Invert(const complex& topRight, const complex& bottomLeft, bitLenInt t)
644  {
645  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Invert"));
646  CliffordShard& shard = shards[t];
647  shard.unit->Invert(topRight, bottomLeft, shard.mapped);
648  CombinePhaseOffsets(shard.unit);
649  }
650  void MCPhase(
651  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt t)
652  {
653  if (controls.empty()) {
654  Phase(topLeft, bottomRight, t);
655  return;
656  }
657 
658  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCPhase"));
659 
660  if (IS_SAME(topLeft, ONE_CMPLX) && IS_SAME(bottomRight, -ONE_CMPLX)) {
661  CZ(c, t);
662  return;
663  }
664 
665  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
666  CGate(
667  c, t, mtrx,
668  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
669  unit->MCPhase({ c }, mtrx[0U], mtrx[3U], t);
670  },
671  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Phase(mtrx[0U], mtrx[3U], t); },
672  false);
673  }
674  void MACPhase(
675  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt t)
676  {
677  if (controls.empty()) {
678  Phase(topLeft, bottomRight, t);
679  return;
680  }
681 
682  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACPhase"));
683 
684  if (IS_SAME(topLeft, ONE_CMPLX) && IS_SAME(bottomRight, -ONE_CMPLX)) {
685  AntiCZ(c, t);
686  return;
687  }
688 
689  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
690  CGate(
691  c, t, mtrx,
692  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
693  unit->MACPhase({ c }, mtrx[0U], mtrx[3U], t);
694  },
695  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Phase(mtrx[0U], mtrx[3U], t); },
696  true);
697  }
698  void MCInvert(
699  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt t)
700  {
701  if (controls.empty()) {
702  Invert(topRight, bottomLeft, t);
703  return;
704  }
705 
706  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCInvert"));
707 
708  if (IS_SAME(topRight, ONE_CMPLX) && IS_SAME(bottomLeft, ONE_CMPLX)) {
709  CNOT(c, t);
710  return;
711  }
712 
713  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
714  CGate(
715  c, t, mtrx,
716  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
717  unit->MCInvert({ c }, mtrx[1U], mtrx[2U], t);
718  },
719  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Invert(mtrx[1U], mtrx[2U], t); },
720  false);
721  }
722  void MACInvert(
723  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt t)
724  {
725  if (controls.empty()) {
726  Invert(topRight, bottomLeft, t);
727  return;
728  }
729 
730  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACInvert"));
731 
732  if (IS_SAME(topRight, ONE_CMPLX) && IS_SAME(bottomLeft, ONE_CMPLX)) {
733  AntiCNOT(c, t);
734  return;
735  }
736 
737  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
738  CGate(
739  c, t, mtrx,
740  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
741  unit->MACInvert({ c }, mtrx[1U], mtrx[2U], t);
742  },
743  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Invert(mtrx[1U], mtrx[2U], t); },
744  true);
745  }
746  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt t)
747  {
748  if ((norm(mtrx[1U]) <= FP_NORM_EPSILON) && (norm(mtrx[2U]) <= FP_NORM_EPSILON)) {
749  MCPhase(controls, mtrx[0U], mtrx[3U], t);
750  return;
751  }
752  if ((norm(mtrx[0U]) <= FP_NORM_EPSILON) && (norm(mtrx[3U]) <= FP_NORM_EPSILON)) {
753  MCInvert(controls, mtrx[1U], mtrx[2U], t);
754  return;
755  }
756 
757  if (controls.empty()) {
758  Mtrx(mtrx, t);
759  return;
760  }
761 
762  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCMtrx"));
763 
764  CGate(
765  c, t, mtrx,
766  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
767  unit->MCMtrx({ c }, mtrx, t);
768  },
769  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Mtrx(mtrx, t); }, false);
770  }
771  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt t)
772  {
773  if ((norm(mtrx[1U]) <= FP_NORM_EPSILON) && (norm(mtrx[2U]) <= FP_NORM_EPSILON)) {
774  MACPhase(controls, mtrx[0U], mtrx[3U], t);
775  return;
776  }
777  if ((norm(mtrx[0U]) <= FP_NORM_EPSILON) && (norm(mtrx[3U]) <= FP_NORM_EPSILON)) {
778  MACInvert(controls, mtrx[1U], mtrx[2U], t);
779  return;
780  }
781 
782  if (controls.empty()) {
783  Mtrx(mtrx, t);
784  return;
785  }
786 
787  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACMtrx"));
788 
789  CGate(
790  c, t, mtrx,
791  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
792  unit->MACMtrx({ c }, mtrx, t);
793  },
794  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Mtrx(mtrx, t); }, true);
795  }
796  void FSim(real1_f theta, real1_f phi, bitLenInt c, bitLenInt t)
797  {
798  ThrowIfQubitInvalid(c, std::string("QUnitClifford::FSim"));
799  ThrowIfQubitInvalid(t, std::string("QUnitClifford::FSim"));
800 
801  std::vector<bitLenInt> bits{ c, t };
802  std::vector<bitLenInt*> ebits{ &bits[0U], &bits[1U] };
803  QStabilizerPtr unit = EntangleInCurrentBasis(ebits.begin(), ebits.end());
804  unit->FSim(theta, phi, c, t);
805  CombinePhaseOffsets(unit);
806  TrySeparate(c);
807  TrySeparate(t);
808  }
809 
810  bool TrySeparate(const std::vector<bitLenInt>& qubits, real1_f ignored)
811  {
812  for (size_t i = 0U; i < qubits.size(); ++i) {
813  if (!TrySeparate(qubits[i])) {
814  return false;
815  }
816  }
817 
818  return true;
819  }
820  bool TrySeparate(bitLenInt qubit);
821  bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
822  {
823  if (qubit1 == qubit2) {
824  return TrySeparate(qubit1);
825  }
826 
827  const bool q1 = TrySeparate(qubit1);
828  const bool q2 = TrySeparate(qubit2);
829 
830  return q1 && q2;
831  }
832 
833  friend std::ostream& operator<<(std::ostream& os, const QUnitCliffordPtr s);
834  friend std::istream& operator>>(std::istream& is, const QUnitCliffordPtr s);
835 };
836 } // namespace Qrack
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
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:470
std::shared_ptr< RdRandom > hardware_rand_generator
Definition: qinterface.hpp:152
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:364
qrack_rand_gen_ptr rand_generator
Definition: qinterface.hpp:150
bool randGlobalPhase
Definition: qinterface.hpp:144
virtual void SetQubitCount(bitLenInt qb)
Definition: qinterface.hpp:268
bitLenInt qubitCount
Definition: qinterface.hpp:146
bool doNormalize
Definition: qinterface.hpp:143
Definition: qunitclifford.hpp:42
void Mtrx(const complex *mtrx, bitLenInt t)
Apply an arbitrary single bit unitary transformation.
Definition: qunitclifford.hpp:629
void Phase(const complex &topLeft, const complex &bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase.
Definition: qunitclifford.hpp:636
bitCapInt GetMaxQPower()
Get the maximum number of basis states, namely for qubits.
Definition: qunitclifford.hpp:208
real1_f ProbPermRdm(const bitCapInt &perm, bitLenInt ancillaeStart)
Definition: qunitclifford.cpp:115
void MACInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunitclifford.hpp:722
void AntiCNOT(bitLenInt c, bitLenInt t)
Apply an (anti-)CNOT gate with control and target.
Definition: qunitclifford.hpp:328
void MACMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt t)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
Definition: qunitclifford.hpp:771
void SetRandGlobalPhase(bool isRand)
Definition: qunitclifford.hpp:212
bool IsSeparableZ(const bitLenInt &t)
Returns "true" if target qubit is a Z basis eigenstate.
Definition: qunitclifford.hpp:482
void IISwap(bitLenInt c, bitLenInt t)
Inverse ISwap - Swap values of two bits in register, and apply phase factor of -i if bits are differe...
Definition: qunitclifford.hpp:437
QStabilizerPtr EntangleInCurrentBasis(std::vector< bitLenInt * >::iterator first, std::vector< bitLenInt * >::iterator last)
Definition: qunitclifford.cpp:269
bool IsSeparableY(const bitLenInt &t)
Returns "true" if target qubit is a Y basis eigenstate.
Definition: qunitclifford.hpp:501
void Decompose(bitLenInt start, QUnitCliffordPtr dest)
Definition: qunitclifford.hpp:553
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Compose() a QInterface peer, inserting its qubit into index order at start index.
Definition: qunitclifford.hpp:545
std::vector< CliffordShard > shards
Definition: qunitclifford.hpp:45
std::map< bitCapInt, complex > GetQuantumState()
Convert the state to sparse ket notation.
Definition: qunitclifford.cpp:419
bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
Two-qubit TrySeparate()
Definition: qunitclifford.hpp:821
bool isClifford(bitLenInt qubit)
Returns "true" if current qubit state is identifiably within the Clifford set, or "false" if it is no...
Definition: qunitclifford.hpp:204
void Clear()
Definition: qunitclifford.hpp:238
bitLenInt ThrowIfQubitSetInvalid(const std::vector< bitLenInt > &controls, bitLenInt t, std::string methodName)
Definition: qunitclifford.hpp:158
bool IsSeparableX(const bitLenInt &t)
Returns "true" if target qubit is an X basis eigenstate.
Definition: qunitclifford.hpp:492
void MCPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase, with arbitrary control bits.
Definition: qunitclifford.hpp:650
bitLenInt Compose(QUnitCliffordPtr toCopy)
Definition: qunitclifford.hpp:527
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:364
void X(bitLenInt t)
X gate.
Definition: qunitclifford.hpp:403
bool TrySeparate(const std::vector< bitLenInt > &qubits, real1_f ignored)
Qrack::QUnit types maintain explicit separation of representations of qubits, which reduces memory us...
Definition: qunitclifford.hpp:810
bitCapInt PermCount()
Definition: qunitclifford.hpp:222
void Detach(bitLenInt start, bitLenInt length, QUnitCliffordPtr dest)
Definition: qunitclifford.cpp:200
QStabilizerPtr EntangleAll()
Definition: qunitclifford.hpp:79
QInterfacePtr CloneBody(QUnitCliffordPtr copyPtr)
Definition: qunitclifford.cpp:29
virtual void H(bitLenInt qubit)
Apply a Hadamard gate to target.
Definition: qinterface.hpp:913
void SetPermutation(const bitCapInt &perm, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qunitclifford.cpp:181
real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qunitclifford.hpp:622
void OrderContiguous(QStabilizerPtr unit)
Definition: qunitclifford.cpp:334
std::map< bitCapInt, int > MultiShotMeasureMask(const std::vector< bitCapInt > &qPowers, unsigned shots)
Statistical measure of masked permutation probability.
Definition: qunitclifford.cpp:593
bitLenInt GetQubitCount()
Get the count of bits in this register.
Definition: qunitclifford.hpp:206
void Z(bitLenInt t)
Apply a phase gate (|0>->|0>, |1>->-|1>, or "Z") to qubit b.
Definition: qunitclifford.hpp:394
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: qunitclifford.hpp:246
std::function< void(QStabilizerPtr unit, const bitLenInt &c, const bitLenInt &t, const complex *mtrx)> CGateFn
Definition: qunitclifford.hpp:100
void SetAmplitude(const bitCapInt &perm, const complex &amp)
Sets the representational amplitude of a full permutation.
Definition: qunitclifford.hpp:284
void CNOT(bitLenInt c, bitLenInt t)
Apply a CNOT gate with control and target.
Definition: qunitclifford.hpp:290
void IS(bitLenInt t)
Apply an inverse phase gate (|0>->|0>, |1>->-i|1>, or "S adjoint") to qubit b.
Definition: qunitclifford.hpp:386
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: qunitclifford.hpp:257
void Invert(const complex &topRight, const complex &bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase.
Definition: qunitclifford.hpp:643
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qunitclifford.hpp:549
bool ForceM(bitLenInt t, bool result, bool doForce=true, bool doApply=true)
Measure qubit t.
Definition: qunitclifford.cpp:570
bitCapInt MAll()
Measure all qubits.
Definition: qunitclifford.hpp:447
void SwapGate(bitLenInt control, bitLenInt target, SwapGateFn ufn, const complex &phaseFac)
Definition: qunitclifford.hpp:127
void S(bitLenInt t)
Apply a phase gate (|0>->|0>, |1>->i|1>, or "S") to qubit b.
Definition: qunitclifford.hpp:378
complex GetAmplitude(const bitCapInt &perm)
Get a single basis state amplitude.
Definition: qunitclifford.cpp:453
friend std::istream & operator>>(std::istream &is, const QUnitCliffordPtr s)
Definition: qunitclifford.cpp:860
void MCMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt t)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: qunitclifford.hpp:746
void AntiCY(bitLenInt c, bitLenInt t)
Apply an (anti-)CY gate with control and target.
Definition: qunitclifford.hpp:345
void Copy(QInterfacePtr orig)
Definition: qunitclifford.hpp:48
std::function< void(QStabilizerPtr unit, const bitLenInt &c, const bitLenInt &t)> SwapGateFn
Definition: qunitclifford.hpp:102
void H(bitLenInt t)
Hadamard gate.
Definition: qunitclifford.hpp:371
~QUnitClifford()
Definition: qunitclifford.hpp:188
bool SeparateBit(bool value, bitLenInt qubit)
Definition: qunitclifford.cpp:533
QUnitStateVectorPtr GetDecomposedQuantumState()
Convert the state to Schmidt-decomposed sparse ket notation.
Definition: qunitclifford.cpp:427
void Y(bitLenInt t)
Apply a Pauli Y gate to target.
Definition: qunitclifford.hpp:410
void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qunitclifford.hpp:210
void MACPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase, with arbitrary (anti-)control bits.
Definition: qunitclifford.hpp:674
real1_f ExpectationFloatsFactorized(const std::vector< bitLenInt > &bits, const std::vector< real1_f > &weights)
Get expectation value of bits, given a (floating-point) array of qubit weights.
Definition: qunitclifford.hpp:252
void Dispose(bitLenInt start, bitLenInt length, const bitCapInt &disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qunitclifford.hpp:564
std::vector< complex > GetAmplitudes(std::vector< bitCapInt > perms)
Get a single basis state amplitude.
Definition: qunitclifford.cpp:482
bool isClifford()
Returns "true" if current state is identifiably within the Clifford set, or "false" if it is not or c...
Definition: qunitclifford.hpp:203
void FSim(real1_f theta, real1_f phi, bitLenInt c, bitLenInt t)
The 2-qubit "fSim" gate, (useful in the simulation of particles with fermionic statistics)
Definition: qunitclifford.hpp:796
QUnitCliffordPtr CloneEmpty()
Definition: qunitclifford.hpp:197
uint8_t IsSeparable(const bitLenInt &t)
Returns: 0 if target qubit is not separable 1 if target qubit is a Z basis eigenstate 2 if target qub...
Definition: qunitclifford.hpp:514
bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
Definition: qunitclifford.hpp:521
void GetProbs(real1 *outputProbs)
Get all probabilities corresponding to ket notation.
Definition: qunitclifford.cpp:445
real1_f VarianceFloatsFactorized(const std::vector< bitLenInt > &bits, const std::vector< real1_f > &weights)
Direct measure of variance of listed bit string probability.
Definition: qunitclifford.hpp:263
void ResetPhaseOffset()
Definition: qunitclifford.hpp:219
void CY(bitLenInt c, bitLenInt t)
Apply a CY gate with control and target.
Definition: qunitclifford.hpp:307
void Copy(QUnitCliffordPtr orig)
Definition: qunitclifford.hpp:49
void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qunitclifford.hpp:563
void ThrowIfQubitInvalid(bitLenInt t, std::string methodName)
Definition: qunitclifford.hpp:150
friend std::ostream & operator<<(std::ostream &os, const QUnitCliffordPtr s)
Definition: qunitclifford.cpp:839
std::function< void(QStabilizerPtr unit, const bitLenInt &t, const complex *mtrx)> GateFn
Definition: qunitclifford.hpp:101
real1_f ExpVarBitsFactorized(bool isExp, const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Definition: qunitclifford.cpp:46
void ISwap(bitLenInt c, bitLenInt t)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: qunitclifford.hpp:431
void CombinePhaseOffsets(QStabilizerPtr unit)
Definition: qunitclifford.hpp:56
complex GetPhaseOffset()
Definition: qunitclifford.hpp:220
void CGate(bitLenInt control, bitLenInt target, const complex *mtrx, CGateFn cfn, GateFn fn, bool isAnti)
Definition: qunitclifford.hpp:103
QInterfacePtr Decompose(bitLenInt start, bitLenInt length)
Schmidt decompose a length of qubits.
Definition: qunitclifford.hpp:554
void AntiCZ(bitLenInt c, bitLenInt t)
Apply an (anti-)CZ gate with control and target.
Definition: qunitclifford.hpp:355
virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
Calculates (1 - <\psi_e|\psi_c>) between states |\psi_c> and |\psi_e>.
Definition: qunitclifford.hpp:599
complex phaseOffset
Definition: qunitclifford.hpp:44
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: qunitclifford.hpp:594
void SortUnit(QStabilizerPtr unit, std::vector< QSortEntry > &bits, bitLenInt low, bitLenInt high)
Definition: qunitclifford.cpp:360
bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qunitclifford.hpp:528
void CZ(bitLenInt c, bitLenInt t)
Apply a CZ gate with control and target.
Definition: qunitclifford.hpp:315
QUnitClifford(bitLenInt n, const bitCapInt &perm=ZERO_BCI, qrack_rand_gen_ptr rgp=nullptr, const complex &phasFac=CMPLX_DEFAULT_ARG, bool doNorm=false, bool randomGlobalPhase=true, bool ignored2=false, int64_t ignored3=-1, bool useHardwareRNG=true, bool ignored4=false, real1_f ignored5=REAL1_EPSILON, std::vector< int64_t > ignored6={}, bitLenInt ignored7=0U, real1_f ignored8=_qrack_qunit_sep_thresh)
Definition: qunitclifford.cpp:20
void Swap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register.
Definition: qunitclifford.hpp:418
real1_f ProbMask(const bitCapInt &mask, const bitCapInt &permutation)
Direct measure of masked permutation probability.
Definition: qunitclifford.cpp:153
bool ApproxCompare(QUnitCliffordPtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qunitclifford.hpp:608
void SetQuantumState(const complex *inputState)
Set an arbitrary pure quantum state representation.
Definition: qunitclifford.cpp:757
QInterfacePtr Clone()
Clone this QInterface.
Definition: qunitclifford.hpp:190
QStabilizerPtr MakeStabilizer(bitLenInt length=1U, const bitCapInt &perm=ZERO_BCI, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Definition: qunitclifford.hpp:274
bitLenInt Allocate(bitLenInt start, bitLenInt length)
Allocate new "length" count of |0> state qubits at specified qubit index start position.
Definition: qunitclifford.hpp:566
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: qunitclifford.hpp:587
bitLenInt Compose(QUnitCliffordPtr toCopy, bitLenInt start)
Definition: qunitclifford.hpp:529
void MCInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunitclifford.hpp:698
real1_f ExpVarFloatsFactorized(bool isExp, const std::vector< bitLenInt > &bits, const std::vector< real1_f > &weights)
Definition: qunitclifford.cpp:80
bool ApproxCompare(QInterfacePtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Compare state vectors approximately, to determine whether this state vector is the same as the target...
Definition: qunitclifford.hpp:604
Half-precision floating-point type.
Definition: half.hpp:2222
virtual void H(bitLenInt qubit)
Hadamard gate.
Definition: qinterface.hpp:913
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1084
virtual void U(bitLenInt target, real1_f theta, real1_f phi, real1_f lambda)
General unitary gate.
Definition: rotational.cpp:18
virtual bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: qinterface.hpp:2350
virtual void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qinterface.hpp:2843
virtual QInterfacePtr Copy()
Copy this QInterface.
Definition: qinterface.hpp:2965
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:29
const real1_f _qrack_qunit_sep_thresh
Definition: qrack_functions.hpp:235
QRACK_CONST real1_f TRYDECOMPOSE_EPSILON
Definition: qrack_types.hpp:260
void U(quid sid, bitLenInt q, real1_f theta, real1_f phi, real1_f lambda)
(External API) 3-parameter unitary gate
Definition: wasm_api.cpp:1143
std::complex< real1 > complex
Definition: qrack_types.hpp:128
std::shared_ptr< QUnitStateVector > QUnitStateVectorPtr
Definition: qunitstatevector.hpp:17
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:258
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:136
std::shared_ptr< QUnitClifford > QUnitCliffordPtr
Definition: qunitclifford.hpp:20
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:101
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:200
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:252
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:185
float real1_f
Definition: qrack_types.hpp:95
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:257
std::shared_ptr< QStabilizer > QStabilizerPtr
Definition: qstabilizer.hpp:42
QRACK_CONST complex I_CMPLX
Definition: qrack_types.hpp:254
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:253
const bitCapInt ONE_BCI
Definition: qrack_types.hpp:129
const bitCapInt ZERO_BCI
Definition: qrack_types.hpp:130
#define IS_SAME(c1, c2)
Definition: qrack_types.hpp:26
#define REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:177
#define bitLenInt
Definition: qrack_types.hpp:38
#define ZERO_R1_F
Definition: qrack_types.hpp:160
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:156
#define bitCapInt
Definition: qrack_types.hpp:62
#define ONE_R1_F
Definition: qrack_types.hpp:163
Definition: qunitclifford.hpp:23
QStabilizerPtr unit
Definition: qunitclifford.hpp:25
CliffordShard(const CliffordShard &o)
Definition: qunitclifford.hpp:34
bitLenInt mapped
Definition: qunitclifford.hpp:24
CliffordShard(bitLenInt m=0U, QStabilizerPtr u=NULL)
Definition: qunitclifford.hpp:27
Definition: qunitclifford.hpp:66
bool operator>(const QSortEntry &rhs)
Definition: qunitclifford.hpp:70
bitLenInt bit
Definition: qunitclifford.hpp:67
bool operator<(const QSortEntry &rhs)
Definition: qunitclifford.hpp:69
bitLenInt mapped
Definition: qunitclifford.hpp:68