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  // Apply half a phase gate
420  void T(bitLenInt t) { RZ(PI_R1 / 4, t); }
422  void IT(bitLenInt t) { RZ(-PI_R1 / 4, t); }
424  void RZ(real1_f angle, bitLenInt t)
425  {
426  ThrowIfQubitInvalid(t, std::string("QUnitClifford::RZ"));
427  CliffordShard& shard = shards[t];
428  shard.unit->RZ(angle, shard.mapped);
429  CombinePhaseOffsets(shard.unit);
430  }
431  // Swap two bits
432  void Swap(bitLenInt qubit1, bitLenInt qubit2)
433  {
434  ThrowIfQubitInvalid(qubit1, std::string("QUnitClifford::Swap"));
435  ThrowIfQubitInvalid(qubit2, std::string("QUnitClifford::Swap"));
436 
437  if (qubit1 == qubit2) {
438  return;
439  }
440 
441  // Simply swap the bit mapping.
442  std::swap(shards[qubit1], shards[qubit2]);
443  }
444  // Swap two bits and apply a phase factor of i if they are different
446  {
447  SwapGate(c, t, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t) { unit->ISwap(c, t); }, I_CMPLX);
448  }
449  // Swap two bits and apply a phase factor of -i if they are different
451  {
452  SwapGate(
453  c, t, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t) { unit->IISwap(c, t); }, -I_CMPLX);
454  }
455 
457  bool ForceM(bitLenInt t, bool result, bool doForce = true, bool doApply = true);
458 
461  {
462  MaxReduce();
463  bitCapInt toRet = QInterface::MAll();
464  SetPermutation(toRet);
465  return toRet;
466  }
467 
468  std::map<bitCapInt, int> MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots);
469 
470  void MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots, unsigned long long* shotsArray);
471 
473  void GetQuantumState(complex* stateVec);
474 
476  void GetQuantumState(QInterfacePtr eng);
477 
479  std::map<bitCapInt, complex> GetQuantumState();
480 
483 
485  void GetProbs(real1* outputProbs);
486 
488  complex GetAmplitude(const bitCapInt& perm);
489 
491  std::vector<complex> GetAmplitudes(std::vector<bitCapInt> perms);
492 
494  std::vector<bitLenInt> EntangledQubits(const bitLenInt& qubit, const bool& g)
495  {
496  ThrowIfQubitInvalid(qubit, std::string("QUnitClifford::EntangledQubits"));
497  const CliffordShard& shard = shards[qubit];
498  QStabilizerPtr unit = shard.unit;
499  std::vector<bitLenInt> eqb = unit->EntangledQubits(shard.mapped, g);
500  for (size_t i = 0U; i < eqb.size(); ++i) {
501  bitLenInt& qb = eqb[i];
502  for (bitLenInt j = 0U; j < qubitCount; ++j) {
503  const CliffordShard& oShard = shards[j];
504  if ((unit == oShard.unit) && (qb == oShard.mapped)) {
505  qb = j;
506  break;
507  }
508  }
509  }
510 
511  return eqb;
512  }
514  bool IsSeparableZ(const bitLenInt& t)
515  {
516  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableZ"));
517  CliffordShard& shard = shards[t];
518  return shard.unit->IsSeparableZ(shard.mapped);
519  }
521  bool IsSeparableX(const bitLenInt& t)
522  {
523  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableX"));
524  CliffordShard& shard = shards[t];
525  return shard.unit->IsSeparableX(shard.mapped);
526  }
528  bool IsSeparableY(const bitLenInt& t)
529  {
530  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableY"));
531  CliffordShard& shard = shards[t];
532  return shard.unit->IsSeparableY(shard.mapped);
533  }
541  uint8_t IsSeparable(const bitLenInt& t)
542  {
543  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparable"));
544  CliffordShard& shard = shards[t];
545  return shard.unit->IsSeparable(shard.mapped);
546  }
547 
548  bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
549  {
550  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->CanDecomposeDispose(start, length);
551  }
552 
553  using QInterface::Compose;
554  bitLenInt Compose(QUnitCliffordPtr toCopy) { return Compose(toCopy, qubitCount); }
555  bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy)); }
557  {
558  if (start > qubitCount) {
559  throw std::invalid_argument("QUnit::Compose start index is out-of-bounds!");
560  }
561 
562  /* Create a clone of the quantum state in toCopy. */
563  QUnitCliffordPtr clone = std::dynamic_pointer_cast<QUnitClifford>(toCopy->Clone());
564 
565  /* Insert the new shards in the middle */
566  shards.insert(shards.begin() + start, clone->shards.begin(), clone->shards.end());
567 
568  SetQubitCount(qubitCount + toCopy->GetQubitCount());
569 
570  return start;
571  }
573  {
574  return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy), start);
575  }
577  {
578  Decompose(start, std::dynamic_pointer_cast<QUnitClifford>(dest));
579  }
580  void Decompose(bitLenInt start, QUnitCliffordPtr dest) { Detach(start, dest->GetQubitCount(), dest); }
582  {
583  QUnitCliffordPtr dest = std::make_shared<QUnitClifford>(
585 
586  Decompose(start, dest);
587 
588  return dest;
589  }
590  void Dispose(bitLenInt start, bitLenInt length) { Detach(start, length, nullptr); }
591  void Dispose(bitLenInt start, bitLenInt length, const bitCapInt& disposedPerm) { Detach(start, length, nullptr); }
592  using QInterface::Allocate;
594  {
595  if (!length) {
596  return start;
597  }
598 
599  if (start > qubitCount) {
600  throw std::out_of_range("QUnitClifford::Allocate() cannot start past end of register!");
601  }
602 
603  if (!qubitCount) {
604  SetQubitCount(length);
606  return 0U;
607  }
608 
609  QUnitCliffordPtr nQubits = std::make_shared<QUnitClifford>(length, ZERO_BCI, rand_generator, CMPLX_DEFAULT_ARG,
610  false, randGlobalPhase, false, -1, !!hardware_rand_generator);
611  return Compose(nQubits, start);
612  }
613 
615  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
616  {
617  if (!randGlobalPhase) {
618  phaseOffset *= std::polar(ONE_R1, (real1)phaseArg);
619  }
620  }
622  {
623  // Intentionally left blank
624  }
625 
626  virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
627  {
628  return SumSqrDiff(std::dynamic_pointer_cast<QUnitClifford>(toCompare));
629  }
630  virtual real1_f SumSqrDiff(QUnitCliffordPtr toCompare);
632  {
633  return ApproxCompare(std::dynamic_pointer_cast<QUnitClifford>(toCompare), error_tol);
634  }
636  {
637  if (!toCompare) {
638  return false;
639  }
640 
641  if (this == toCompare.get()) {
642  return true;
643  }
644 
645  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->ApproxCompare(
646  std::dynamic_pointer_cast<QUnitClifford>(toCompare->Clone())->EntangleAll(), error_tol);
647  }
648 
650  {
651  ThrowIfQubitInvalid(qubit, std::string("QUnitClifford::Prob"));
652  CliffordShard& shard = shards[qubit];
653  return shard.unit->Prob(shard.mapped);
654  }
655 
656  void Mtrx(const complex mtrx[4U], bitLenInt t)
657  {
658  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Mtrx"));
659  CliffordShard& shard = shards[t];
660  shard.unit->Mtrx(mtrx, shard.mapped);
661  CombinePhaseOffsets(shard.unit);
662  }
663  void Phase(const complex& topLeft, const complex& bottomRight, bitLenInt t)
664  {
665  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Phase"));
666  CliffordShard& shard = shards[t];
667  shard.unit->Phase(topLeft, bottomRight, shard.mapped);
668  CombinePhaseOffsets(shard.unit);
669  }
670  void Invert(const complex& topRight, const complex& bottomLeft, bitLenInt t)
671  {
672  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Invert"));
673  CliffordShard& shard = shards[t];
674  shard.unit->Invert(topRight, bottomLeft, shard.mapped);
675  CombinePhaseOffsets(shard.unit);
676  }
677  void MCPhase(
678  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt t)
679  {
680  if (controls.empty()) {
681  return Phase(topLeft, bottomRight, t);
682  }
683 
684  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCPhase"));
685 
686  if (IS_SAME(topLeft, ONE_CMPLX) && IS_SAME(bottomRight, -ONE_CMPLX)) {
687  return CZ(c, t);
688  }
689 
690  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
691  CGate(
692  c, t, mtrx,
693  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
694  unit->MCPhase({ c }, mtrx[0U], mtrx[3U], t);
695  },
696  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Phase(mtrx[0U], mtrx[3U], t); },
697  false);
698  }
699  void MACPhase(
700  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt t)
701  {
702  if (controls.empty()) {
703  return Phase(topLeft, bottomRight, t);
704  }
705 
706  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACPhase"));
707 
708  if (IS_SAME(topLeft, ONE_CMPLX) && IS_SAME(bottomRight, -ONE_CMPLX)) {
709  return AntiCZ(c, t);
710  }
711 
712  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
713  CGate(
714  c, t, mtrx,
715  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
716  unit->MACPhase({ c }, mtrx[0U], mtrx[3U], t);
717  },
718  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Phase(mtrx[0U], mtrx[3U], t); },
719  true);
720  }
721  void MCInvert(
722  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt t)
723  {
724  if (controls.empty()) {
725  return Invert(topRight, bottomLeft, t);
726  }
727 
728  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCInvert"));
729 
730  if (IS_SAME(topRight, ONE_CMPLX) && IS_SAME(bottomLeft, ONE_CMPLX)) {
731  return CNOT(c, t);
732  }
733 
734  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
735  CGate(
736  c, t, mtrx,
737  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
738  unit->MCInvert({ c }, mtrx[1U], mtrx[2U], t);
739  },
740  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Invert(mtrx[1U], mtrx[2U], t); },
741  false);
742  }
743  void MACInvert(
744  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt t)
745  {
746  if (controls.empty()) {
747  return Invert(topRight, bottomLeft, t);
748  }
749 
750  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACInvert"));
751 
752  if (IS_SAME(topRight, ONE_CMPLX) && IS_SAME(bottomLeft, ONE_CMPLX)) {
753  return AntiCNOT(c, t);
754  }
755 
756  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
757  CGate(
758  c, t, mtrx,
759  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
760  unit->MACInvert({ c }, mtrx[1U], mtrx[2U], t);
761  },
762  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Invert(mtrx[1U], mtrx[2U], t); },
763  true);
764  }
765  void MCMtrx(const std::vector<bitLenInt>& controls, const complex mtrx[4U], bitLenInt t)
766  {
767  if ((norm(mtrx[1U]) <= FP_NORM_EPSILON) && (norm(mtrx[2U]) <= FP_NORM_EPSILON)) {
768  return MCPhase(controls, mtrx[0U], mtrx[3U], t);
769  }
770  if ((norm(mtrx[0U]) <= FP_NORM_EPSILON) && (norm(mtrx[3U]) <= FP_NORM_EPSILON)) {
771  return MCInvert(controls, mtrx[1U], mtrx[2U], t);
772  }
773 
774  if (controls.empty()) {
775  return Mtrx(mtrx, t);
776  }
777 
778  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCMtrx"));
779 
780  CGate(
781  c, t, mtrx,
782  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
783  unit->MCMtrx({ c }, mtrx, t);
784  },
785  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Mtrx(mtrx, t); }, false);
786  }
787  void MACMtrx(const std::vector<bitLenInt>& controls, const complex mtrx[4U], bitLenInt t)
788  {
789  if ((norm(mtrx[1U]) <= FP_NORM_EPSILON) && (norm(mtrx[2U]) <= FP_NORM_EPSILON)) {
790  return MACPhase(controls, mtrx[0U], mtrx[3U], t);
791  }
792  if ((norm(mtrx[0U]) <= FP_NORM_EPSILON) && (norm(mtrx[3U]) <= FP_NORM_EPSILON)) {
793  return MACInvert(controls, mtrx[1U], mtrx[2U], t);
794  }
795 
796  if (controls.empty()) {
797  return Mtrx(mtrx, t);
798  }
799 
800  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACMtrx"));
801 
802  CGate(
803  c, t, mtrx,
804  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
805  unit->MACMtrx({ c }, mtrx, t);
806  },
807  [](QStabilizerPtr unit, const bitLenInt& t, const complex* mtrx) { unit->Mtrx(mtrx, t); }, true);
808  }
809  void FSim(real1_f theta, real1_f phi, bitLenInt c, bitLenInt t)
810  {
811  ThrowIfQubitInvalid(c, std::string("QUnitClifford::FSim"));
812  ThrowIfQubitInvalid(t, std::string("QUnitClifford::FSim"));
813 
814  std::vector<bitLenInt> bits{ c, t };
815  std::vector<bitLenInt*> ebits{ &bits[0U], &bits[1U] };
816  QStabilizerPtr unit = EntangleInCurrentBasis(ebits.begin(), ebits.end());
817  unit->FSim(theta, phi, c, t);
818  CombinePhaseOffsets(unit);
819  if (!isReactiveSeparate) {
820  return;
821  }
822  TrySeparate(c);
823  TrySeparate(t);
824  }
825 
826  bool TrySeparate(const std::vector<bitLenInt>& qubits, real1_f ignored)
827  {
828  for (const bitLenInt& qubit : qubits) {
829  if (!TrySeparate(qubit)) {
830  return false;
831  }
832  }
833 
834  return true;
835  }
836  bool TrySeparate(bitLenInt qubit);
837  bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
838  {
839  if (qubit1 == qubit2) {
840  return TrySeparate(qubit1);
841  }
842 
843  const bool q1 = TrySeparate(qubit1);
844  const bool q2 = TrySeparate(qubit2);
845 
846  return q1 && q2;
847  }
848  std::vector<bitLenInt> MaxReduce(bitLenInt qubit);
849  void MaxReduce(const std::vector<bitLenInt>& qubits);
850  void MaxReduce();
851  bool SeparateBit(bool value, bitLenInt qubit);
852 
853  friend std::ostream& operator<<(std::ostream& os, const QUnitCliffordPtr s);
854  friend std::istream& operator>>(std::istream& is, const QUnitCliffordPtr s);
855 };
856 } // 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:488
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: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
bitLenInt qubitCount
Definition: qinterface.hpp:146
bool doNormalize
Definition: qinterface.hpp:143
Definition: qunitclifford.hpp:42
void Phase(const complex &topLeft, const complex &bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase.
Definition: qunitclifford.hpp:663
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:743
void AntiCNOT(bitLenInt c, bitLenInt t)
Apply an (anti-)CNOT gate with control and target.
Definition: qunitclifford.hpp:332
void IT(bitLenInt t)
Apply half an inverse phase gate.
Definition: qunitclifford.hpp:422
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:514
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:450
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:528
void Decompose(bitLenInt start, QUnitCliffordPtr dest)
Definition: qunitclifford.hpp:580
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Compose() a QInterface peer, inserting its qubit into index order at start index.
Definition: qunitclifford.hpp:572
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:837
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:521
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:677
bitLenInt Compose(QUnitCliffordPtr toCopy)
Definition: qunitclifford.hpp:554
std::vector< bitLenInt > EntangledQubits(const bitLenInt &qubit, const bool &g)
Returns all qubits entangled with "qubit" (including itself)
Definition: qunitclifford.hpp:494
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:382
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:826
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:931
void SetPermutation(const bitCapInt &perm, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qunitclifford.cpp:192
void T(bitLenInt t)
T gate.
Definition: qunitclifford.hpp:420
real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qunitclifford.hpp:649
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
void Mtrx(const complex mtrx[4U], bitLenInt t)
Apply an arbitrary single bit unitary transformation.
Definition: qunitclifford.hpp:656
bitLenInt GetQubitCount()
Get the count of bits in this register.
Definition: qunitclifford.hpp:213
void MACMtrx(const std::vector< bitLenInt > &controls, const complex mtrx[4U], bitLenInt t)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
Definition: qunitclifford.hpp:787
void MCMtrx(const std::vector< bitLenInt > &controls, const complex mtrx[4U], bitLenInt t)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: qunitclifford.hpp:765
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:670
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qunitclifford.hpp:576
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:460
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 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:699
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:591
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:809
void RZ(real1_f angle, bitLenInt t)
Approximate an arbitrary phase angle.
Definition: qunitclifford.hpp:424
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:541
bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
Definition: qunitclifford.hpp:548
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:590
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:445
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:581
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:626
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:621
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:555
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:432
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:635
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:593
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:614
bitLenInt Compose(QUnitCliffordPtr toCopy, bitLenInt start)
Definition: qunitclifford.hpp:556
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:721
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:631
Half-precision floating-point type.
Definition: half.hpp:2206
virtual void H(bitLenInt qubit)
Hadamard gate.
Definition: qinterface.hpp:931
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1116
virtual void U(bitLenInt target, real1_f theta, real1_f phi, real1_f lambda)
General unitary gate.
Definition: rotational.cpp:18
virtual bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: qinterface.hpp:2382
virtual void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qinterface.hpp:2887
virtual QInterfacePtr Copy()
Copy this QInterface.
Definition: qinterface.hpp:3058
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:258
QRACK_CONST real1_f TRYDECOMPOSE_EPSILON
Definition: qrack_types.hpp:265
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:140
std::shared_ptr< QUnitStateVector > QUnitStateVectorPtr
Definition: qunitstatevector.hpp:17
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:263
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:156
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:203
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:257
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:188
float real1_f
Definition: qrack_types.hpp:107
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:262
std::shared_ptr< QStabilizer > QStabilizerPtr
Definition: qstabilizer.hpp:46
QRACK_CONST complex I_CMPLX
Definition: qrack_types.hpp:259
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:258
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
#define IS_SAME(c1, c2)
Definition: qrack_types.hpp:29
#define REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:179
#define bitLenInt
Definition: qrack_types.hpp:41
#define ZERO_R1_F
Definition: qrack_types.hpp:162
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:158
#define bitCapInt
Definition: qrack_types.hpp:65
#define ONE_R1_F
Definition: qrack_types.hpp:165
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