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