Qrack  9.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 
17 namespace Qrack {
18 
19 class QUnitClifford;
20 typedef std::shared_ptr<QUnitClifford> QUnitCliffordPtr;
21 
22 struct CliffordShard {
25 
27  : mapped(m)
28  , unit(u)
29  {
30  // Intentionally left blank
31  }
32 
34  : mapped(o.mapped)
35  , unit(o.unit)
36  {
37  // Intentionally left blank
38  }
39 };
40 
41 class QUnitClifford : public QInterface {
42 protected:
44  std::vector<CliffordShard> shards;
45 
47  {
48  if (randGlobalPhase) {
49  return;
50  }
51 
52  phaseOffset *= unit->GetPhaseOffset();
53  unit->ResetPhaseOffset();
54  }
55 
56  struct QSortEntry {
59  bool operator<(const QSortEntry& rhs) { return mapped < rhs.mapped; }
60  bool operator>(const QSortEntry& rhs) { return mapped > rhs.mapped; }
61  };
62  void SortUnit(QStabilizerPtr unit, std::vector<QSortEntry>& bits, bitLenInt low, bitLenInt high);
63 
64  void Detach(bitLenInt start, bitLenInt length, QUnitCliffordPtr dest);
65 
67  std::vector<bitLenInt*>::iterator first, std::vector<bitLenInt*>::iterator last);
68 
70  {
71  if (!qubitCount) {
72  return MakeStabilizer(0U);
73  }
74  std::vector<bitLenInt> bits(qubitCount);
75  std::vector<bitLenInt*> ebits(qubitCount);
76  for (bitLenInt i = 0U; i < qubitCount; ++i) {
77  bits[i] = i;
78  ebits[i] = &bits[i];
79  }
80 
81  QStabilizerPtr toRet = EntangleInCurrentBasis(ebits.begin(), ebits.end());
82  OrderContiguous(toRet);
83 
84  return toRet;
85  }
86 
88 
89  typedef std::function<void(QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx)>
91  void CGate(bitLenInt control, bitLenInt target, const complex* mtrx, CGateFn fn)
92  {
93  std::vector<bitLenInt> bits{ control, target };
94  std::vector<bitLenInt*> ebits{ &bits[0U], &bits[1U] };
95  QStabilizerPtr unit = EntangleInCurrentBasis(ebits.begin(), ebits.end());
96  fn(unit, bits[0U], bits[1U], mtrx);
97  CombinePhaseOffsets(unit);
98  TrySeparate(control);
99  TrySeparate(target);
100  }
101 
103 
104  bool SeparateBit(bool value, bitLenInt qubit);
105 
106  void ThrowIfQubitInvalid(bitLenInt t, std::string methodName)
107  {
108  if (t >= qubitCount) {
109  throw std::invalid_argument(
110  methodName + std::string(" target qubit index parameter must be within allocated qubit bounds!"));
111  }
112  }
113 
114  bitLenInt ThrowIfQubitSetInvalid(const std::vector<bitLenInt>& controls, bitLenInt t, std::string methodName)
115  {
116  if (t >= qubitCount) {
117  throw std::invalid_argument(
118  methodName + std::string(" target qubit index parameter must be within allocated qubit bounds!"));
119  }
120  if (controls.size() > 1U) {
121  throw std::invalid_argument(methodName + std::string(" can only have one control qubit!"));
122  }
123  const bitLenInt c = controls[0U];
124  if (c >= qubitCount) {
125  throw std::invalid_argument(
126  methodName + std::string(" control qubit index parameter must be within allocated qubit bounds!"));
127  }
128 
129  return controls[0U];
130  }
131 
132 public:
133  QUnitClifford(bitLenInt n, bitCapInt perm = 0U, qrack_rand_gen_ptr rgp = nullptr,
134  complex phasFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true, bool ignored2 = false,
135  int64_t ignored3 = -1, bool useHardwareRNG = true, bool ignored4 = false, real1_f ignored5 = REAL1_EPSILON,
136  std::vector<int64_t> ignored6 = {}, bitLenInt ignored7 = 0U, real1_f ignored8 = FP_NORM_EPSILON_F);
137 
139 
141  {
142  QUnitCliffordPtr copyPtr = std::make_shared<QUnitClifford>(
144 
145  return CloneBody(copyPtr);
146  }
148  {
149  return std::make_shared<QUnitClifford>(
151  }
152 
153  bool isClifford() { return true; };
154  bool isClifford(bitLenInt qubit) { return true; };
155 
157 
159 
160  void SetDevice(int64_t dID) {}
161 
162  void SetRandGlobalPhase(bool isRand)
163  {
164  for (bitLenInt i = 0U; i < qubitCount; ++i) {
165  shards[i].unit->SetRandGlobalPhase(isRand);
166  }
167  }
168 
171 
173  {
174  std::map<QStabilizerPtr, QStabilizerPtr> engines;
175  bitCapInt permCount = 1U;
176  for (bitLenInt i = 0U; i < qubitCount; ++i) {
177  QStabilizerPtr unit = shards[i].unit;
178  if (engines.find(unit) == engines.end()) {
179  permCount *= pow2(unit->gaussian());
180  }
181  }
182 
183  return permCount;
184  }
185 
186  void Clear()
187  {
188  shards = std::vector<CliffordShard>();
190  qubitCount = 0U;
191  maxQPower = 1U;
192  }
193 
195  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, bitCapInt offset = 0U);
196 
197  real1_f ExpectationFloatsFactorized(const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights);
198 
199  real1_f ProbPermRdm(bitCapInt perm, bitLenInt ancillaeStart);
200 
201  real1_f ProbMask(bitCapInt mask, bitCapInt permutation);
202 
203  void SetPermutation(bitCapInt perm, complex phaseFac = CMPLX_DEFAULT_ARG);
204 
206  {
207  QStabilizerPtr toRet = std::make_shared<QStabilizer>(
208  length, perm, rand_generator, phaseFac, false, randGlobalPhase, false, -1, useRDRAND);
209 
210  return toRet;
211  }
212 
213  void SetQuantumState(const complex* inputState);
215  {
216  throw std::domain_error("QUnitClifford::SetAmplitude() not implemented!");
217  }
218 
221  {
222  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
223  unit->CNOT(c, t);
224  });
225  }
227  void CY(bitLenInt c, bitLenInt t)
228  {
229  CGate(c, t, NULL,
230  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) { unit->CY(c, t); });
231  }
233  void CZ(bitLenInt c, bitLenInt t)
234  {
235  CGate(c, t, NULL,
236  [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) { unit->CZ(c, t); });
237  }
240  {
241  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
242  unit->AntiCNOT(c, t);
243  });
244  }
247  {
248  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
249  unit->AntiCY(c, t);
250  });
251  }
254  {
255  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
256  unit->AntiCZ(c, t);
257  });
258  }
260  using QInterface::H;
261  void H(bitLenInt t)
262  {
263  ThrowIfQubitInvalid(t, std::string("QUnitClifford::H"));
264  CliffordShard& shard = shards[t];
265  shard.unit->H(shard.mapped);
266  }
268  void S(bitLenInt t)
269  {
270  ThrowIfQubitInvalid(t, std::string("QUnitClifford::S"));
271  CliffordShard& shard = shards[t];
272  shard.unit->S(shard.mapped);
273  CombinePhaseOffsets(shard.unit);
274  }
276  void IS(bitLenInt t)
277  {
278  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IS"));
279  CliffordShard& shard = shards[t];
280  shard.unit->IS(shard.mapped);
281  CombinePhaseOffsets(shard.unit);
282  }
284  void Z(bitLenInt t)
285  {
286  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Z"));
287  CliffordShard& shard = shards[t];
288  shard.unit->Z(shard.mapped);
289  CombinePhaseOffsets(shard.unit);
290  }
292  using QInterface::X;
293  void X(bitLenInt t)
294  {
295  ThrowIfQubitInvalid(t, std::string("QUnitClifford::X"));
296  CliffordShard& shard = shards[t];
297  shard.unit->X(shard.mapped);
298  }
300  void Y(bitLenInt t)
301  {
302  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Y"));
303  CliffordShard& shard = shards[t];
304  shard.unit->Y(shard.mapped);
305  CombinePhaseOffsets(shard.unit);
306  }
307  // Swap two bits
308  void Swap(bitLenInt qubit1, bitLenInt qubit2)
309  {
310  ThrowIfQubitInvalid(qubit1, std::string("QUnitClifford::Swap"));
311  ThrowIfQubitInvalid(qubit2, std::string("QUnitClifford::Swap"));
312 
313  if (qubit1 == qubit2) {
314  return;
315  }
316 
317  // Simply swap the bit mapping.
318  std::swap(shards[qubit1], shards[qubit2]);
319  }
320  // Swap two bits and apply a phase factor of i if they are different
322  {
323  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
324  unit->ISwap(c, t);
325  });
326  }
327  // Swap two bits and apply a phase factor of -i if they are different
329  {
330  CGate(c, t, NULL, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* unused) {
331  unit->IISwap(c, t);
332  });
333  }
334 
336  bool ForceM(bitLenInt t, bool result, bool doForce = true, bool doApply = true);
337 
340  {
341  bitCapInt toRet = QInterface::MAll();
342  SetPermutation(toRet);
343  return toRet;
344  }
345 
346  std::map<bitCapInt, int> MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots);
347 
348  void MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots, unsigned long long* shotsArray);
349 
351  void GetQuantumState(complex* stateVec);
352 
354  void GetQuantumState(QInterfacePtr eng);
355 
357  std::map<bitCapInt, complex> GetQuantumState();
358 
360  void GetProbs(real1* outputProbs);
361 
364 
366  std::vector<complex> GetAmplitudes(std::vector<bitCapInt> perms);
367 
371  bool IsSeparableZ(const bitLenInt& t)
372  {
373  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableZ"));
374  CliffordShard& shard = shards[t];
375  return shard.unit->IsSeparableZ(shard.mapped);
376  }
377 
381  bool IsSeparableX(const bitLenInt& t)
382  {
383  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableX"));
384  CliffordShard& shard = shards[t];
385  return shard.unit->IsSeparableX(shard.mapped);
386  }
390  bool IsSeparableY(const bitLenInt& t)
391  {
392  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparableY"));
393  CliffordShard& shard = shards[t];
394  return shard.unit->IsSeparableY(shard.mapped);
395  }
403  uint8_t IsSeparable(const bitLenInt& t)
404  {
405  ThrowIfQubitInvalid(t, std::string("QUnitClifford::IsSeparable"));
406  CliffordShard& shard = shards[t];
407  return shard.unit->IsSeparable(shard.mapped);
408  }
409 
410  bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
411  {
412  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->CanDecomposeDispose(start, length);
413  }
414 
415  using QInterface::Compose;
416  bitLenInt Compose(QUnitCliffordPtr toCopy) { return Compose(toCopy, qubitCount); }
417  bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy)); }
419  {
420  if (start > qubitCount) {
421  throw std::invalid_argument("QUnit::Compose start index is out-of-bounds!");
422  }
423 
424  /* Create a clone of the quantum state in toCopy. */
425  QUnitCliffordPtr clone = std::dynamic_pointer_cast<QUnitClifford>(toCopy->Clone());
426 
427  /* Insert the new shards in the middle */
428  shards.insert(shards.begin() + start, clone->shards.begin(), clone->shards.end());
429 
430  SetQubitCount(qubitCount + toCopy->GetQubitCount());
431 
432  return start;
433  }
435  {
436  return Compose(std::dynamic_pointer_cast<QUnitClifford>(toCopy), start);
437  }
439  {
440  Decompose(start, std::dynamic_pointer_cast<QUnitClifford>(dest));
441  }
442  void Decompose(bitLenInt start, QUnitCliffordPtr dest) { Detach(start, dest->GetQubitCount(), dest); }
444  {
445  QUnitCliffordPtr dest = std::make_shared<QUnitClifford>(
447 
448  Decompose(start, dest);
449 
450  return dest;
451  }
452  void Dispose(bitLenInt start, bitLenInt length) { Detach(start, length, nullptr); }
453  void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm) { Detach(start, length, nullptr); }
454  using QInterface::Allocate;
456  {
457  if (!length) {
458  return start;
459  }
460 
461  if (start > qubitCount) {
462  throw std::out_of_range("QUnitClifford::Allocate() cannot start past end of register!");
463  }
464 
465  if (!qubitCount) {
466  SetQubitCount(length);
467  SetPermutation(0U);
468  return 0U;
469  }
470 
471  QUnitCliffordPtr nQubits = std::make_shared<QUnitClifford>(length, 0U, rand_generator, CMPLX_DEFAULT_ARG, false,
472  randGlobalPhase, false, -1, hardware_rand_generator != NULL);
473  return Compose(nQubits, start);
474  }
475 
477  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
478  {
479  if (!randGlobalPhase) {
480  phaseOffset *= std::polar(ONE_R1, (real1)phaseArg);
481  }
482  }
484  {
485  // Intentionally left blank
486  }
487 
488  virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
489  {
490  return SumSqrDiff(std::dynamic_pointer_cast<QUnitClifford>(toCompare));
491  }
492  virtual real1_f SumSqrDiff(QUnitCliffordPtr toCompare);
494  {
495  return ApproxCompare(std::dynamic_pointer_cast<QUnitClifford>(toCompare), error_tol);
496  }
498  {
499  if (!toCompare) {
500  return false;
501  }
502 
503  if (this == toCompare.get()) {
504  return true;
505  }
506 
507  return std::dynamic_pointer_cast<QUnitClifford>(Clone())->EntangleAll()->ApproxCompare(
508  std::dynamic_pointer_cast<QUnitClifford>(toCompare->Clone())->EntangleAll(), error_tol);
509  }
510 
512  {
513  ThrowIfQubitInvalid(qubit, std::string("QUnitClifford::Prob"));
514  CliffordShard& shard = shards[qubit];
515  return shard.unit->Prob(shard.mapped);
516  }
517 
518  void Mtrx(const complex* mtrx, bitLenInt t)
519  {
520  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Mtrx"));
521  CliffordShard& shard = shards[t];
522  shard.unit->Mtrx(mtrx, shard.mapped);
523  CombinePhaseOffsets(shard.unit);
524  }
525  void Phase(complex topLeft, complex bottomRight, bitLenInt t)
526  {
527  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Phase"));
528  CliffordShard& shard = shards[t];
529  shard.unit->Phase(topLeft, bottomRight, shard.mapped);
530  CombinePhaseOffsets(shard.unit);
531  }
532  void Invert(complex topRight, complex bottomLeft, bitLenInt t)
533  {
534  ThrowIfQubitInvalid(t, std::string("QUnitClifford::Invert"));
535  CliffordShard& shard = shards[t];
536  shard.unit->Invert(topRight, bottomLeft, shard.mapped);
537  CombinePhaseOffsets(shard.unit);
538  }
539  void MCPhase(const std::vector<bitLenInt>& controls, complex topLeft, complex bottomRight, bitLenInt t)
540  {
541  if (!controls.size()) {
542  Phase(topLeft, bottomRight, t);
543  return;
544  }
545 
546  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCPhase"));
547 
548  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
549  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
550  unit->MCPhase({ c }, mtrx[0U], mtrx[3U], t);
551  });
552  }
553  void MACPhase(const std::vector<bitLenInt>& controls, complex topLeft, complex bottomRight, bitLenInt t)
554  {
555  if (!controls.size()) {
556  Phase(topLeft, bottomRight, t);
557  return;
558  }
559 
560  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACPhase"));
561 
562  const complex mtrx[4]{ topLeft, ZERO_CMPLX, ZERO_CMPLX, bottomRight };
563  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
564  unit->MACPhase({ c }, mtrx[0U], mtrx[3U], t);
565  });
566  }
567  void MCInvert(const std::vector<bitLenInt>& controls, complex topRight, complex bottomLeft, bitLenInt t)
568  {
569  if (!controls.size()) {
570  Invert(topRight, bottomLeft, t);
571  return;
572  }
573 
574  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCInvert"));
575 
576  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
577  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
578  unit->MCInvert({ c }, mtrx[1U], mtrx[2U], t);
579  });
580  }
581  void MACInvert(const std::vector<bitLenInt>& controls, complex topRight, complex bottomLeft, bitLenInt t)
582  {
583  if (!controls.size()) {
584  Invert(topRight, bottomLeft, t);
585  return;
586  }
587 
588  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACInvert"));
589 
590  const complex mtrx[4]{ ZERO_CMPLX, topRight, bottomLeft, ZERO_CMPLX };
591  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
592  unit->MACInvert({ c }, mtrx[1U], mtrx[2U], t);
593  });
594  }
595  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt t)
596  {
597  if (!controls.size()) {
598  Mtrx(mtrx, t);
599  return;
600  }
601 
602  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MCMtrx"));
603 
604  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
605  unit->MCMtrx({ c }, mtrx, t);
606  });
607  }
608  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt t)
609  {
610  if (!controls.size()) {
611  Mtrx(mtrx, t);
612  return;
613  }
614 
615  const bitLenInt c = ThrowIfQubitSetInvalid(controls, t, std::string("QUnitClifford::MACMtrx"));
616 
617  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
618  unit->MACMtrx({ c }, mtrx, t);
619  });
620  }
621  void FSim(real1_f theta, real1_f phi, bitLenInt c, bitLenInt t)
622  {
623  ThrowIfQubitInvalid(c, std::string("QUnitClifford::FSim"));
624  ThrowIfQubitInvalid(t, std::string("QUnitClifford::FSim"));
625 
626  const complex mtrx[4]{ (real1)theta, (real1)phi, ZERO_CMPLX, ZERO_CMPLX };
627  CGate(c, t, mtrx, [](QStabilizerPtr unit, const bitLenInt& c, const bitLenInt& t, const complex* mtrx) {
628  unit->FSim((real1_f)std::real(mtrx[0U]), (real1_f)std::real(mtrx[1U]), c, t);
629  });
630  }
631 
632  bool TrySeparate(const std::vector<bitLenInt>& qubits, real1_f ignored)
633  {
634  for (size_t i = 0U; i < qubits.size(); ++i) {
635  if (!TrySeparate(qubits[i])) {
636  return false;
637  }
638  }
639 
640  return true;
641  }
642  bool TrySeparate(bitLenInt qubit);
643  bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
644  {
645  if (qubit1 == qubit2) {
646  return TrySeparate(qubit1);
647  }
648 
649  const bool q1 = TrySeparate(qubit1);
650  const bool q2 = TrySeparate(qubit2);
651 
652  return q1 && q2;
653  }
654 
655  friend std::ostream& operator<<(std::ostream& os, const QUnitCliffordPtr s);
656  friend std::istream& operator>>(std::istream& is, const QUnitCliffordPtr s);
657 };
658 } // namespace Qrack
A "Qrack::QInterface" is an abstract interface exposing qubit permutation state vector with methods t...
Definition: qinterface.hpp:146
bitCapInt maxQPower
Definition: qinterface.hpp:154
bool useRDRAND
Definition: qinterface.hpp:150
virtual bitLenInt Allocate(bitLenInt length)
Allocate new "length" count of |0> state qubits at end of qubit index position.
Definition: qinterface.hpp:434
std::shared_ptr< RdRandom > hardware_rand_generator
Definition: qinterface.hpp:157
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:338
qrack_rand_gen_ptr rand_generator
Definition: qinterface.hpp:155
bool randGlobalPhase
Definition: qinterface.hpp:149
virtual void SetQubitCount(bitLenInt qb)
Definition: qinterface.hpp:159
bitLenInt qubitCount
Definition: qinterface.hpp:151
bool doNormalize
Definition: qinterface.hpp:148
Definition: qunitclifford.hpp:41
void Mtrx(const complex *mtrx, bitLenInt t)
Apply an arbitrary single bit unitary transformation.
Definition: qunitclifford.hpp:518
bitCapInt GetMaxQPower()
Get the maximum number of basis states, namely for qubits.
Definition: qunitclifford.hpp:158
real1_f ExpectationBitsFactorized(const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, bitCapInt offset=0U)
Get expectation value of bits, given an array of qubit weights.
Definition: qunitclifford.cpp:46
void Invert(complex topRight, complex bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase.
Definition: qunitclifford.hpp:532
void AntiCNOT(bitLenInt c, bitLenInt t)
Apply an (anti-)CNOT gate with control and target.
Definition: qunitclifford.hpp:239
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:608
void SetRandGlobalPhase(bool isRand)
Definition: qunitclifford.hpp:162
bool IsSeparableZ(const bitLenInt &t)
Returns "true" if target qubit is a Z basis eigenstate.
Definition: qunitclifford.hpp:371
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:328
QStabilizerPtr EntangleInCurrentBasis(std::vector< bitLenInt * >::iterator first, std::vector< bitLenInt * >::iterator last)
Definition: qunitclifford.cpp:257
bool IsSeparableY(const bitLenInt &t)
Returns "true" if target qubit is a Y basis eigenstate.
Definition: qunitclifford.hpp:390
void Decompose(bitLenInt start, QUnitCliffordPtr dest)
Definition: qunitclifford.hpp:442
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Definition: qunitclifford.hpp:434
std::vector< CliffordShard > shards
Definition: qunitclifford.hpp:44
std::map< bitCapInt, complex > GetQuantumState()
Convert the state to sparse ket notation.
Definition: qunitclifford.cpp:407
void SetPermutation(bitCapInt perm, complex phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qunitclifford.cpp:169
bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
Two-qubit TrySeparate()
Definition: qunitclifford.hpp:643
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:154
void Clear()
Definition: qunitclifford.hpp:186
bitLenInt ThrowIfQubitSetInvalid(const std::vector< bitLenInt > &controls, bitLenInt t, std::string methodName)
Definition: qunitclifford.hpp:114
bool IsSeparableX(const bitLenInt &t)
Returns "true" if target qubit is an X basis eigenstate.
Definition: qunitclifford.hpp:381
void MCInvert(const std::vector< bitLenInt > &controls, complex topRight, complex bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunitclifford.hpp:567
bitLenInt Compose(QUnitCliffordPtr toCopy)
Definition: qunitclifford.hpp:416
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:338
void X(bitLenInt t)
X gate.
Definition: qunitclifford.hpp:293
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:632
bitCapInt PermCount()
Definition: qunitclifford.hpp:172
void Detach(bitLenInt start, bitLenInt length, QUnitCliffordPtr dest)
Definition: qunitclifford.cpp:188
QStabilizerPtr EntangleAll()
Definition: qunitclifford.hpp:69
QInterfacePtr CloneBody(QUnitCliffordPtr copyPtr)
Definition: qunitclifford.cpp:29
real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qunitclifford.hpp:511
void OrderContiguous(QStabilizerPtr unit)
Definition: qunitclifford.cpp:322
std::map< bitCapInt, int > MultiShotMeasureMask(const std::vector< bitCapInt > &qPowers, unsigned shots)
Statistical measure of masked permutation probability.
Definition: qunitclifford.cpp:563
bitLenInt GetQubitCount()
Get the count of bits in this register.
Definition: qunitclifford.hpp:156
void Z(bitLenInt t)
Apply a phase gate (|0>->|0>, |1>->-|1>, or "Z") to qubit b.
Definition: qunitclifford.hpp:284
std::function< void(QStabilizerPtr unit, const bitLenInt &c, const bitLenInt &t, const complex *mtrx)> CGateFn
Definition: qunitclifford.hpp:90
void Dispose(bitLenInt start, bitLenInt length, bitCapInt disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qunitclifford.hpp:453
void CNOT(bitLenInt c, bitLenInt t)
Apply a CNOT gate with control and target.
Definition: qunitclifford.hpp:220
complex GetAmplitude(bitCapInt perm)
Get a single basis state amplitude.
Definition: qunitclifford.cpp:423
void IS(bitLenInt t)
Apply an inverse phase gate (|0>->|0>, |1>->-i|1>, or "S adjoint") to qubit b.
Definition: qunitclifford.hpp:276
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qunitclifford.hpp:438
bool ForceM(bitLenInt t, bool result, bool doForce=true, bool doApply=true)
Measure qubit t.
Definition: qunitclifford.cpp:540
bitCapInt MAll()
Measure all qubits.
Definition: qunitclifford.hpp:339
void S(bitLenInt t)
Apply a phase gate (|0>->|0>, |1>->i|1>, or "S") to qubit b.
Definition: qunitclifford.hpp:268
friend std::istream & operator>>(std::istream &is, const QUnitCliffordPtr s)
Definition: qunitclifford.cpp:830
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:595
void AntiCY(bitLenInt c, bitLenInt t)
Apply an (anti-)CY gate with control and target.
Definition: qunitclifford.hpp:246
real1_f ProbPermRdm(bitCapInt perm, bitLenInt ancillaeStart)
Definition: qunitclifford.cpp:103
void H(bitLenInt t)
Hadamard gate.
Definition: qunitclifford.hpp:261
~QUnitClifford()
Definition: qunitclifford.hpp:138
bool SeparateBit(bool value, bitLenInt qubit)
Definition: qunitclifford.cpp:503
void Y(bitLenInt t)
Apply a Pauli Y gate to target.
Definition: qunitclifford.hpp:300
void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qunitclifford.hpp:160
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.cpp:74
std::vector< complex > GetAmplitudes(std::vector< bitCapInt > perms)
Get a single basis state amplitude.
Definition: qunitclifford.cpp:452
bool isClifford()
Returns "true" if current state is identifiably within the Clifford set, or "false" if it is not or c...
Definition: qunitclifford.hpp:153
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:621
QUnitCliffordPtr CloneEmpty()
Definition: qunitclifford.hpp:147
void MCPhase(const std::vector< bitLenInt > &controls, complex topLeft, complex bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase, with arbitrary control bits.
Definition: qunitclifford.hpp:539
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:403
bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
Definition: qunitclifford.hpp:410
void GetProbs(real1 *outputProbs)
Get all probabilities corresponding to ket notation.
Definition: qunitclifford.cpp:415
void ResetPhaseOffset()
Definition: qunitclifford.hpp:169
void CY(bitLenInt c, bitLenInt t)
Apply a CY gate with control and target.
Definition: qunitclifford.hpp:227
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:452
void ThrowIfQubitInvalid(bitLenInt t, std::string methodName)
Definition: qunitclifford.hpp:106
friend std::ostream & operator<<(std::ostream &os, const QUnitCliffordPtr s)
Definition: qunitclifford.cpp:809
void MACInvert(const std::vector< bitLenInt > &controls, complex topRight, complex bottomLeft, bitLenInt t)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qunitclifford.hpp:581
real1_f ProbMask(bitCapInt mask, bitCapInt permutation)
Direct measure of masked permutation probability.
Definition: qunitclifford.cpp:141
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:321
void CombinePhaseOffsets(QStabilizerPtr unit)
Definition: qunitclifford.hpp:46
complex GetPhaseOffset()
Definition: qunitclifford.hpp:170
void Phase(complex topLeft, complex bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase.
Definition: qunitclifford.hpp:525
void SetAmplitude(bitCapInt perm, complex amp)
Sets the representational amplitude of a full permutation.
Definition: qunitclifford.hpp:214
QInterfacePtr Decompose(bitLenInt start, bitLenInt length)
Schmidt decompose a length of qubits.
Definition: qunitclifford.hpp:443
void AntiCZ(bitLenInt c, bitLenInt t)
Apply an (anti-)CZ gate with control and target.
Definition: qunitclifford.hpp:253
QStabilizerPtr MakeStabilizer(bitLenInt length=1U, bitCapInt perm=0U, complex phaseFac=CMPLX_DEFAULT_ARG)
Definition: qunitclifford.hpp:205
void CGate(bitLenInt control, bitLenInt target, const complex *mtrx, CGateFn fn)
Definition: qunitclifford.hpp:91
virtual real1_f SumSqrDiff(QInterfacePtr toCompare)
Definition: qunitclifford.hpp:488
complex phaseOffset
Definition: qunitclifford.hpp:43
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:483
void SortUnit(QStabilizerPtr unit, std::vector< QSortEntry > &bits, bitLenInt low, bitLenInt high)
Definition: qunitclifford.cpp:348
bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qunitclifford.hpp:417
void CZ(bitLenInt c, bitLenInt t)
Apply a CZ gate with control and target.
Definition: qunitclifford.hpp:233
void Swap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register.
Definition: qunitclifford.hpp:308
void MACPhase(const std::vector< bitLenInt > &controls, complex topLeft, complex bottomRight, bitLenInt t)
Apply a single bit transformation that only effects phase, with arbitrary (anti-)control bits.
Definition: qunitclifford.hpp:553
QUnitClifford(bitLenInt n, bitCapInt perm=0U, qrack_rand_gen_ptr rgp=nullptr, 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=FP_NORM_EPSILON_F)
Definition: qunitclifford.cpp:20
bool ApproxCompare(QUnitCliffordPtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qunitclifford.hpp:497
void SetQuantumState(const complex *inputState)
Set an arbitrary pure quantum state representation.
Definition: qunitclifford.cpp:727
QInterfacePtr Clone()
Clone this QInterface.
Definition: qunitclifford.hpp:140
bitLenInt Allocate(bitLenInt start, bitLenInt length)
Allocate new "length" count of |0> state qubits at specified qubit index start position.
Definition: qunitclifford.hpp:455
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:476
bitLenInt Compose(QUnitCliffordPtr toCopy, bitLenInt start)
Definition: qunitclifford.hpp:418
bool ApproxCompare(QInterfacePtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Compare state vectors approximately, component by component, to determine whether this state vector i...
Definition: qunitclifford.hpp:493
Half-precision floating-point type.
Definition: half.hpp:2222
virtual void H(bitLenInt qubit)
Hadamard gate.
Definition: qinterface.hpp:876
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1054
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:2256
virtual void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qinterface.hpp:2588
Definition: complex16x2simd.hpp:25
std::complex< half_float::half > complex
Definition: qrack_types.hpp:62
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:28
QRACK_CONST real1_f TRYDECOMPOSE_EPSILON
Definition: qrack_types.hpp:244
constexpr real1_f ZERO_R1_F
Definition: qrack_types.hpp:152
constexpr real1_f FP_NORM_EPSILON_F
Definition: qrack_types.hpp:245
const real1 ONE_R1
Definition: qrack_types.hpp:153
half_float::half real1
Definition: qrack_types.hpp:63
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:22
std::shared_ptr< QUnitClifford > QUnitCliffordPtr
Definition: qunitclifford.hpp:19
const real1 REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:155
QRACK_CONST complex ONE_CMPLX
Definition: qrack_types.hpp:239
float real1_f
Definition: qrack_types.hpp:64
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:242
std::shared_ptr< QStabilizer > QStabilizerPtr
Definition: qstabilizer.hpp:42
const real1 REAL1_EPSILON
Definition: qrack_types.hpp:157
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:240
MICROSOFT_QUANTUM_DECL void U(_In_ uintq sid, _In_ uintq q, _In_ double theta, _In_ double phi, _In_ double lambda)
(External API) 3-parameter unitary gate
Definition: pinvoke_api.cpp:1362
#define bitLenInt
Definition: qrack_types.hpp:44
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:146
#define bitCapInt
Definition: qrack_types.hpp:105
Definition: qunitclifford.hpp:22
QStabilizerPtr unit
Definition: qunitclifford.hpp:24
CliffordShard(const CliffordShard &o)
Definition: qunitclifford.hpp:33
bitLenInt mapped
Definition: qunitclifford.hpp:23
CliffordShard(bitLenInt m=0U, QStabilizerPtr u=NULL)
Definition: qunitclifford.hpp:26
Definition: qunitclifford.hpp:56
bool operator>(const QSortEntry &rhs)
Definition: qunitclifford.hpp:60
bitLenInt bit
Definition: qunitclifford.hpp:57
bool operator<(const QSortEntry &rhs)
Definition: qunitclifford.hpp:59
bitLenInt mapped
Definition: qunitclifford.hpp:58