Qrack  10.0
General classical-emulating-quantum development framework
qstabilizer.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // Adapted from:
6 //
7 // CHP: CNOT-Hadamard-Phase
8 // Stabilizer Quantum Computer Simulator
9 // by Scott Aaronson
10 // Last modified June 30, 2004
11 //
12 // Thanks to Simon Anders and Andrew Cross for bugfixes
13 //
14 // https://www.scottaaronson.com/chp/
15 //
16 // Daniel Strano and the Qrack contributers appreciate Scott Aaronson's open sharing of the CHP code, and we hope that
17 // vm6502q/qrack is one satisfactory framework by which CHP could be adapted to enter the C++ STL. Our project
18 // philosophy aims to raise the floor of decentralized quantum computing technology access across all modern platforms,
19 // for all people, not commercialization.
20 //
21 // Licensed under the GNU Lesser General Public License V3.
22 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
23 // for details.
24 
25 #pragma once
26 
27 #include "qinterface.hpp"
28 
29 #if BOOST_AVAILABLE
30 #include <boost/dynamic_bitset.hpp>
31 #endif
32 
33 namespace Qrack {
34 
38 
39  AmplitudeEntry(const bitCapInt& p, const complex& a)
40  : permutation(p)
41  , amplitude(a)
42  {
43  }
44 };
45 
46 class QStabilizer;
47 typedef std::shared_ptr<QStabilizer> QStabilizerPtr;
48 
49 class QStabilizer : public QInterface {
50 protected:
51  unsigned rawRandBools;
59 #if BOOST_AVAILABLE
60  bool isTransposed;
61 #endif
62 
63  // Typedef for special type std::vector<bool> compatibility
64 #if BOOST_AVAILABLE
65  typedef boost::dynamic_bitset<> BoolVector;
66 #else
67  typedef std::vector<bool> BoolVector;
68 #endif
69  // Phase bits: 0 for +1, 1 for i, 2 for -1, 3 for -i. Normally either 0 or 2.
70  std::vector<BoolVector> r;
71  // (2n+1)*n matrix for stabilizer/destabilizer x bits (there's one "scratch row" at the bottom)
72  std::vector<BoolVector> x;
73  // (2n+1)*n matrix for z bits
74  std::vector<BoolVector> z;
75 
76  // Phase buffers for non-Clifford gates
77  std::vector<complex> bBuffer;
78  std::vector<complex> pBuffer;
79  std::vector<bool> bPhase;
80  std::vector<bool> pPhase;
81 
82  typedef std::function<void(const bitLenInt&)> StabilizerParallelFunc;
83  typedef std::function<void(void)> DispatchFn;
84  void Dispatch(DispatchFn fn) { fn(); }
85 
86  void ParFor(StabilizerParallelFunc fn, std::vector<bitLenInt> qubits);
87 
89  {
90  return complex((real1)FixAnglePeriod((real1_f)real(angle)), (real1)FixAnglePeriod((real1_f)imag(angle)));
91  }
92 
94  {
95  angle = fmod(angle, 2 * PI_R1);
96  if (angle > PI_R1) {
97  angle -= 2 * PI_R1;
98  } else if (angle <= -PI_R1) {
99  angle += 2 * PI_R1;
100  }
101 
102  return angle;
103  }
104 
105  void SetPhaseOffset(real1_f phaseArg)
106  {
107  phaseOffset = (real1)phaseArg;
108  const bool isNeg = phaseOffset < 0;
109  if (isNeg) {
111  }
112  phaseOffset -= (real1)(((size_t)(phaseOffset / (2 * PI_R1))) * (2 * PI_R1));
113  if (phaseOffset > PI_R1) {
114  phaseOffset -= 2 * PI_R1;
115  }
116  if (isNeg) {
118  }
119  }
120 
121  uint8_t GetR(size_t i) { return (r[0U][i] ? 1U : 0U) | (r[1U][i] ? 2U : 0U); }
122  void ResetR(size_t i)
123  {
124 #if BOOST_AVAILABLE
125  r[0U].reset(i);
126  r[1U].reset(i);
127 #else
128  r[0U][i] = false;
129  r[1U][i] = false;
130 #endif
131  }
132 
133  using QInterface::Copy;
134  void Copy(QInterfacePtr orig) { Copy(std::dynamic_pointer_cast<QStabilizer>(orig)); }
135  void Copy(QStabilizerPtr orig)
136  {
137  QInterface::Copy(std::dynamic_pointer_cast<QInterface>(orig));
138  rawRandBools = orig->rawRandBools;
139  rawRandBoolsRemaining = orig->rawRandBoolsRemaining;
140  phaseOffset = orig->phaseOffset;
141  isGaussianCached = orig->isGaussianCached;
142  gaussianCached = orig->gaussianCached;
143 #if BOOST_AVAILABLE
144  isTransposed = orig->isTransposed;
145 #endif
146  maxStateMapCacheQubitCount = orig->maxStateMapCacheQubitCount;
147  r = orig->r;
148  x = orig->x;
149  z = orig->z;
150  bBuffer = orig->bBuffer;
151  pBuffer = orig->pBuffer;
152  bPhase = orig->bPhase;
153  pPhase = orig->pPhase;
154  }
155 
156 #if BOOST_AVAILABLE
157  // By Elara (OpenAI custom GPT)
158  std::vector<boost::dynamic_bitset<>> FastTranspose(const std::vector<boost::dynamic_bitset<>>& matrix)
159  {
160  const size_t num_rows = matrix.size();
161  const size_t num_cols = matrix[0].size();
162 
163  std::vector<BoolVector> transposed(num_cols, BoolVector(num_rows));
164 
165  for (size_t row = 0; row < num_rows; ++row) {
166  const BoolVector& bit_row = matrix[row];
167  for (size_t col = bit_row.find_first(); col != BoolVector::npos; col = bit_row.find_next(col)) {
168  transposed[col].set(row);
169  }
170  }
171 
172  return transposed;
173  }
174 
175  void SetTransposeState(bool isTrans)
176  {
177  if (isTrans == isTransposed) {
178  return;
179  }
180 
181  if (!isTransposed) {
182  x.pop_back();
183  z.pop_back();
184  r[0U].pop_back();
185  r[1U].pop_back();
186  }
187 
188  x = FastTranspose(x);
189  z = FastTranspose(z);
190  isTransposed = isTrans;
191 
192  if (!isTransposed) {
193  x.emplace_back(qubitCount);
194  z.emplace_back(qubitCount);
195  r[0U].push_back(0U);
196  r[1U].push_back(0U);
197  }
198  }
199 #endif
200 
202  {
203  if (qubit >= qubitCount) {
204  throw std::domain_error("QStabilizer gate qubit indices are out-of-bounds!");
205  }
206  }
207 
208 public:
209  QStabilizer(bitLenInt n, const bitCapInt& perm = ZERO_BCI, qrack_rand_gen_ptr rgp = nullptr,
210  const complex& phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
211  bool ignored2 = false, int64_t ignored3 = -1, bool useHardwareRNG = true, bool ignored4 = false,
212  real1_f ignored5 = REAL1_EPSILON, std::vector<int64_t> ignored6 = {}, bitLenInt ignored7 = 0U,
213  real1_f ignored8 = _qrack_qunit_sep_thresh);
214 
216 
218 
219  bool isClifford() { return true; };
220  bool isClifford(bitLenInt qubit) { return true; };
221 
223 
225 
227  complex GetPhaseOffset() { return std::polar(ONE_R1, phaseOffset); }
228 
229  void SetStochastic(bool s) { isStochastic = s; }
230  void SetMajorQuadrant(bool q) { isMajorQuadrant = q; }
231  void SetMajorQuadrant(bitLenInt t, bool b)
232  {
233  const real1_f angle = std::real(pPhase[t] ? -pBuffer[t] : pBuffer[t]);
234  if (b != ((2 * std::abs(angle)) < HALF_PI_R1)) {
235  FlipQuadrant(t);
236  }
237  }
239  {
240  real1_f angle = std::real(pPhase[t] ? -pBuffer[t] : pBuffer[t]);
241  if (std::abs(angle) <= (FP_NORM_EPSILON * HALF_PI_R1)) {
242  return;
243  }
244  if (angle > 0) {
245  SBase(t);
246  angle = FixAnglePeriod(angle - HALF_PI_R1);
247  } else {
248  ISBase(t);
249  angle = FixAnglePeriod(angle + HALF_PI_R1);
250  }
251  pBuffer[t].real((real1)(pPhase[t] ? -angle : angle));
252  }
253 
254  void SetPermutation(const bitCapInt& perm, const complex& phaseFac = CMPLX_DEFAULT_ARG);
255 
256  void SetRandomSeed(uint32_t seed)
257  {
258  if (!!rand_generator) {
259  rand_generator->seed(seed);
260  }
261  }
262 
263  bool Rand()
264  {
265  if (!!hardware_rand_generator) {
266  if (!rawRandBoolsRemaining) {
268  rawRandBoolsRemaining = sizeof(unsigned) * bitsInByte;
269  }
271 
272  return (bool)((rawRandBools >> rawRandBoolsRemaining) & 1U);
273  } else {
275  }
276  }
277 
279  {
280  if (!!hardware_rand_generator) {
281  return hardware_rand_generator->Next();
282  } else {
284  }
285  }
286 
287  void Clear()
288  {
289  x.clear();
290  z.clear();
291 #if BOOST_AVAILABLE
292  r[0U].resize(0U);
293  r[1U].resize(0U);
294  isTransposed = false;
295 #else
296  r[0U].clear();
297  r[1U].clear();
298 #endif
299  bBuffer.clear();
300  pBuffer.clear();
301  bPhase.clear();
302  pPhase.clear();
304  qubitCount = 0U;
305  maxQPower = ONE_BCI;
306  }
307 
308 protected:
310  void rowcopy(const bitLenInt& i, const bitLenInt& k)
311  {
312  if (i == k) {
313  return;
314  }
315 
316  x[i] = x[k];
317  z[i] = z[k];
318  r[0U][i] = r[0U][k];
319  r[1U][i] = r[1U][k];
320  }
322  void rowswap(const bitLenInt& i, const bitLenInt& k)
323  {
324  if (i == k) {
325  return;
326  }
327 
328  std::swap(x[k], x[i]);
329  std::swap(z[k], z[i]);
330 #if BOOST_AVAILABLE
331  bool _r = r[0U][k];
332  r[0U][k] = r[0U][i];
333  r[0U][i] = _r;
334  _r = r[1U][k];
335  r[1U][k] = r[1U][i];
336  r[1U][i] = _r;
337 #else
338  BoolVector::swap(r[0U][k], r[0U][i]);
339  BoolVector::swap(r[1U][k], r[1U][i]);
340 #endif
341  }
343  void rowset(const bitLenInt& i, bitLenInt b)
344  {
345  ResetR(i);
346 
347  BoolVector& xi = x[i];
348  BoolVector& zi = z[i];
349 #if BOOST_AVAILABLE
350  xi.reset();
351  zi.reset();
352 
353  if (b < qubitCount) {
354  xi.set(b);
355  } else {
356  b -= qubitCount;
357  zi.set(b);
358  }
359 #else
360  std::fill(xi.begin(), xi.end(), false);
361  std::fill(zi.begin(), zi.end(), false);
362 
363  if (b < qubitCount) {
364  xi[b] = true;
365  } else {
366  b -= qubitCount;
367  zi[b] = true;
368  }
369 #endif
370  }
372  void rowmult(const bitLenInt& i, const bitLenInt& k)
373  {
374  uint8_t phase = clifford(i, k);
375  r[0U][i] = (bool)(phase & 1U);
376  r[1U][i] = (bool)(phase & 2U);
377  BoolVector& xi = x[i];
378  BoolVector& zi = z[i];
379 
380 #if BOOST_AVAILABLE
381  xi ^= x[k];
382  zi ^= z[k];
383 #else
384  for (bitLenInt j = 0U; j < qubitCount; ++j) {
385  xi[j] = xi[j] ^ x[k][j];
386  zi[j] = zi[j] ^ z[k][j];
387  }
388 #endif
389  }
391  uint8_t clifford(const bitLenInt& i, const bitLenInt& k);
392 
398  void seed(const bitLenInt& g);
399 
401  AmplitudeEntry getBasisAmp(const real1_f& nrm);
402 
404  void setBasisState(const real1_f& nrm, complex* stateVec);
405 
407  void setBasisState(const real1_f& nrm, QInterfacePtr eng);
408 
410  void setBasisState(const real1_f& nrm, std::map<bitCapInt, complex>& stateMap);
411 
413  void setBasisProb(const real1_f& nrm, real1* outputProbs);
414 
416  real1_f getExpectation(const real1_f& nrm, const std::vector<bitCapInt>& bitPowers,
417  const std::vector<bitCapInt>& perms, const bitCapInt& offset);
418 
421  const real1_f& nrm, const std::vector<bitCapInt>& bitPowers, const std::vector<real1_f>& weights);
422 
424  real1_f getVariance(const real1_f& mean, const real1_f& nrm, const std::vector<bitCapInt>& bitPowers,
425  const std::vector<bitCapInt>& perms, const bitCapInt& offset);
426 
428  real1_f getVariance(const real1_f& mean, const real1_f& nrm, const std::vector<bitCapInt>& bitPowers,
429  const std::vector<real1_f>& weights);
430 
431  void DecomposeDispose(const bitLenInt start, const bitLenInt length, QStabilizerPtr toCopy);
432 
434  QStabilizerPtr toCompare, real1_f error_tol = TRYDECOMPOSE_EPSILON, bool isDiscrete = false);
435 
437  {
438  return pPhase[t] || bPhase[t] || (norm(pBuffer[t]) > FP_NORM_EPSILON) || (norm(bBuffer[t]) > FP_NORM_EPSILON);
439  }
440 
442  {
443  std::swap(bBuffer[t], bBuffer[c]);
444  std::swap(pBuffer[t], pBuffer[c]);
445  std::vector<bool>::swap(bPhase[t], bPhase[c]);
446  std::vector<bool>::swap(pPhase[t], pPhase[c]);
447  }
448 
449  void HBase(bitLenInt qubitIndex);
450  void SBase(bitLenInt qubitIndex);
451  void ISBase(bitLenInt qubitIndex);
455 
456 public:
463  bitLenInt gaussian(bool s = true);
464 
465  bitCapInt PermCount() { return pow2(gaussian(false)); }
466 
467  void SetQuantumState(const complex* inputState);
468  void SetAmplitude(const bitCapInt& perm, const complex& amp)
469  {
470  throw std::domain_error("QStabilizer::SetAmplitude() not implemented!");
471  }
472 
473  void SetRandGlobalPhase(bool isRand) { randGlobalPhase = isRand; }
474 
476  void CNOT(bitLenInt control, bitLenInt target);
478  void CY(bitLenInt control, bitLenInt target);
480  void CZ(bitLenInt control, bitLenInt target);
482  void AntiCNOT(bitLenInt control, bitLenInt target);
484  void AntiCY(bitLenInt control, bitLenInt target);
486  void AntiCZ(bitLenInt control, bitLenInt target);
488  using QInterface::H;
489  void H(bitLenInt qubitIndex);
491  using QInterface::X;
492  void X(bitLenInt qubitIndex);
494  void Y(bitLenInt qubitIndex);
496  void Z(bitLenInt qubitIndex);
498  void S(bitLenInt qubitIndex);
500  void IS(bitLenInt qubitIndex);
502  void T(bitLenInt t) { RZ(PI_R1 / 4, t); }
504  void IT(bitLenInt t) { RZ(-PI_R1 / 4, t); }
506  void RZ(real1_f angle, bitLenInt qubitIndex);
507  // Swap two bits
508  void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2);
509  // Swap two bits and apply a phase factor of i if they are different
510  void ISwap(bitLenInt c, bitLenInt t);
511  // Swap two bits and apply a phase factor of -i if they are different
512  void IISwap(bitLenInt c, bitLenInt t);
513 
515  bool ForceM(bitLenInt t, bool result, bool doForce = true, bool doApply = true);
516 
519 
521  void GetQuantumState(complex* stateVec);
522 
524  void GetQuantumState(QInterfacePtr eng);
525 
527  std::map<bitCapInt, complex> GetQuantumState();
528 
530  void GetProbs(real1* outputProbs);
531 
533  complex GetAmplitude(const bitCapInt& perm);
534 
536  std::vector<complex> GetAmplitudes(std::vector<bitCapInt> perms);
537 
540 
543 
546  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI);
547  real1_f ExpectationFloatsFactorized(const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights);
550  const std::vector<bitLenInt>& bits, const std::vector<bitCapInt>& perms, const bitCapInt& offset = ZERO_BCI);
551  real1_f VarianceFloatsFactorized(const std::vector<bitLenInt>& bits, const std::vector<real1_f>& weights);
552 
555  real1_f ProbPermRdm(const bitCapInt& perm, bitLenInt ancillaeStart);
556 
558  real1_f ProbMask(const bitCapInt& mask, const bitCapInt& permutation);
559 
561  std::vector<bitLenInt> EntangledQubits(const bitLenInt& target, const bool& g = true);
563  bool IsSeparableZ(const bitLenInt& target);
565  bool IsSeparableX(const bitLenInt& target);
567  bool IsSeparableY(const bitLenInt& target);
575  uint8_t IsSeparable(const bitLenInt& target);
576 
577  using QInterface::Compose;
578  bitLenInt Compose(QInterfacePtr toCopy) { return Compose(std::dynamic_pointer_cast<QStabilizer>(toCopy)); }
579  bitLenInt Compose(QStabilizerPtr toCopy) { return Compose(toCopy, qubitCount); }
581  {
582  return Compose(std::dynamic_pointer_cast<QStabilizer>(toCopy), start);
583  }
584  bitLenInt Compose(QStabilizerPtr toCopy, bitLenInt start);
586  {
587  DecomposeDispose(start, dest->GetQubitCount(), std::dynamic_pointer_cast<QStabilizer>(dest));
588  }
590  void Dispose(bitLenInt start, bitLenInt length) { DecomposeDispose(start, length, (QStabilizerPtr) nullptr); }
591  void Dispose(bitLenInt start, bitLenInt length, const bitCapInt& ignored)
592  {
593  DecomposeDispose(start, length, (QStabilizerPtr) nullptr);
594  }
595  bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length);
596  using QInterface::Allocate;
598  {
599  if (!length) {
600  return start;
601  }
602 
603  if (start > qubitCount) {
604  throw std::out_of_range("QStabilizer::Allocate() cannot start past end of register!");
605  }
606 
607  if (!qubitCount) {
608  SetQubitCount(length);
610  return 0U;
611  }
612 
613  QStabilizerPtr nQubits = std::make_shared<QStabilizer>(length, ZERO_BCI, rand_generator, CMPLX_DEFAULT_ARG,
614  false, randGlobalPhase, false, -1, !!hardware_rand_generator);
615  return Compose(nQubits, start);
616  }
617 
619  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
620  {
621  if (!randGlobalPhase) {
622  SetPhaseOffset(phaseOffset + (real1)phaseArg);
623  }
624  }
626  {
627  // Intentionally left blank
628  }
629 
631  {
632  return ApproxCompareHelper(std::dynamic_pointer_cast<QStabilizer>(toCompare));
633  }
635  {
636  return ApproxCompare(std::dynamic_pointer_cast<QStabilizer>(toCompare), error_tol);
637  }
639  {
640  return error_tol >= ApproxCompareHelper(toCompare, error_tol, true);
641  }
643  {
644  return GlobalPhaseCompare(std::dynamic_pointer_cast<QStabilizer>(toCompare), error_tol);
645  }
647  {
648  const AmplitudeEntry thisAmpEntry = GetAnyAmplitude();
649  real1 argDiff = (real1)abs(
650  (std::arg(thisAmpEntry.amplitude) - std::arg(toCompare->GetAmplitude(thisAmpEntry.permutation))) /
651  (2 * PI_R1));
652  argDiff -= (real1)(size_t)argDiff;
653  if (argDiff > HALF_R1) {
654  argDiff -= ONE_R1;
655  }
656  if (FP_NORM_EPSILON >= abs(argDiff)) {
657  return false;
658  }
659  return error_tol >= ApproxCompareHelper(toCompare, error_tol, true);
660  }
661 
662  real1_f Prob(bitLenInt qubit);
663 
664  void Mtrx(const complex* mtrx, bitLenInt target);
665  void Phase(const complex& topLeft, const complex& bottomRight, bitLenInt target);
666  void Invert(const complex& topRight, const complex& bottomLeft, bitLenInt target);
667  void MCPhase(
668  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target);
669  void MACPhase(
670  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target);
671  void MCInvert(
672  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target);
673  void MACInvert(
674  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target);
675  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
676  {
677  if (IS_NORM_0(mtrx[1U]) && IS_NORM_0(mtrx[2U])) {
678  return MCPhase(controls, mtrx[0U], mtrx[3U], target);
679  }
680 
681  if (IS_NORM_0(mtrx[0U]) && IS_NORM_0(mtrx[3U])) {
682  return MCInvert(controls, mtrx[1U], mtrx[2U], target);
683  }
684 
685  throw std::domain_error("QStabilizer::MCMtrx() not implemented for non-Clifford/Pauli cases!");
686  }
687  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
688  {
689  if (IS_NORM_0(mtrx[1U]) && IS_NORM_0(mtrx[2U])) {
690  return MACPhase(controls, mtrx[0U], mtrx[3U], target);
691  }
692 
693  if (IS_NORM_0(mtrx[0U]) && IS_NORM_0(mtrx[3U])) {
694  return MACInvert(controls, mtrx[1U], mtrx[2U], target);
695  }
696 
697  throw std::domain_error("QStabilizer::MACMtrx() not implemented for non-Clifford/Pauli cases!");
698  }
699  void FSim(real1_f theta, real1_f phi, bitLenInt qubit1, bitLenInt qubit2);
700 
701  bool TrySeparate(const std::vector<bitLenInt>& qubits, real1_f ignored);
702  bool TrySeparate(bitLenInt qubit) { return CanDecomposeDispose(qubit, 1U); }
703  bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
704  {
705  if (qubit2 < qubit1) {
706  std::swap(qubit1, qubit2);
707  }
708 
709  Swap(qubit1, 0U);
710  Swap(qubit2, 1U);
711 
712  const bool toRet = CanDecomposeDispose(0U, 2U);
713 
714  Swap(qubit2, 1U);
715  Swap(qubit1, 0U);
716 
717  return toRet;
718  }
719 
720  friend std::ostream& operator<<(std::ostream& os, const QStabilizerPtr s);
721  friend std::istream& operator>>(std::istream& is, const QStabilizerPtr s);
722 };
723 } // 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
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
std::uniform_real_distribution< real1_s > rand_distribution
Definition: qinterface.hpp:151
bitLenInt qubitCount
Definition: qinterface.hpp:146
Definition: qstabilizer.hpp:49
bitCapInt PermCount()
Definition: qstabilizer.hpp:465
void seed(const bitLenInt &g)
Finds a Pauli operator P such that the basis state P|0...0> occurs with nonzero amplitude in q,...
Definition: qstabilizer.cpp:341
real1_f getVariance(const real1_f &mean, const real1_f &nrm, const std::vector< bitCapInt > &bitPowers, const std::vector< bitCapInt > &perms, const bitCapInt &offset)
Returns the (partial) variance from a state vector amplitude.
Definition: qstabilizer.cpp:464
void S(bitLenInt qubitIndex)
Apply a phase gate (|0>->|0>, |1>->i|1>, or "S") to qubit b.
Definition: qstabilizer.cpp:1595
void MACInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qstabilizer.cpp:3151
bool TrySeparate(bitLenInt qubit1, bitLenInt qubit2)
Two-qubit TrySeparate()
Definition: qstabilizer.hpp:703
bool CanDecomposeDispose(const bitLenInt start, const bitLenInt length)
Definition: qstabilizer.cpp:2353
bool isMajorQuadrant
Definition: qstabilizer.hpp:57
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qstabilizer.hpp:585
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: qstabilizer.cpp:764
bool GlobalPhaseCompare(QStabilizerPtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qstabilizer.hpp:646
void CZ(bitLenInt control, bitLenInt target)
Apply a CZ gate with control and target.
Definition: qstabilizer.cpp:1144
void ParFor(StabilizerParallelFunc fn, std::vector< bitLenInt > qubits)
Definition: qstabilizer.cpp:68
void setBasisState(const real1_f &nrm, complex *stateVec)
Returns the result of applying the Pauli operator in the "scratch space" of q to |0....
Definition: qstabilizer.cpp:414
friend std::ostream & operator<<(std::ostream &os, const QStabilizerPtr s)
Definition: qstabilizer.cpp:3253
void SetQuantumState(const complex *inputState)
Set an arbitrary pure quantum state representation.
Definition: qstabilizer.cpp:2726
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: qstabilizer.cpp:3234
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: qstabilizer.hpp:618
std::vector< bool > pPhase
Definition: qstabilizer.hpp:80
QStabilizer(bitLenInt n, const bitCapInt &perm=ZERO_BCI, qrack_rand_gen_ptr rgp=nullptr, const complex &phaseFac=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: qstabilizer.cpp:39
complex FixAnglePeriod(complex angle)
Definition: qstabilizer.hpp:88
void AntiCY(bitLenInt control, bitLenInt target)
Apply an (anti-)CY gate with control and target.
Definition: qstabilizer.cpp:1089
void ResetR(size_t i)
Definition: qstabilizer.hpp:122
std::vector< bool > bPhase
Definition: qstabilizer.hpp:79
std::vector< complex > bBuffer
Definition: qstabilizer.hpp:77
bool Rand()
Definition: qstabilizer.hpp:263
friend std::istream & operator>>(std::istream &is, const QStabilizerPtr s)
Definition: qstabilizer.cpp:3284
bool isGaussianCached
Definition: qstabilizer.hpp:58
void SetStochastic(bool s)
Toggle probabilistic approximate near-Clifford vs.
Definition: qstabilizer.hpp:229
uint8_t GetR(size_t i)
Definition: qstabilizer.hpp:121
bitCapInt HighestProbAll()
Get the highest-probability basis dimension in the Hilbert space.
Definition: qstabilizer.cpp:490
void SetRandGlobalPhase(bool isRand)
Definition: qstabilizer.hpp:473
void SetPhaseOffset(real1_f phaseArg)
Definition: qstabilizer.hpp:105
unsigned rawRandBoolsRemaining
Definition: qstabilizer.hpp:52
void ISwap(bitLenInt c, bitLenInt t)
Swap values of two bits in register, and apply phase factor of i if bits are different.
Definition: qstabilizer.cpp:1289
void rowmult(const bitLenInt &i, const bitLenInt &k)
Left-multiply row i by row k - does not change the logical state.
Definition: qstabilizer.hpp:372
bool isNearClifford(bitLenInt t)
Definition: qstabilizer.hpp:436
unsigned rawRandBools
Definition: qstabilizer.hpp:51
void T(bitLenInt t)
Apply half a phase gate.
Definition: qstabilizer.hpp:502
real1_f ExpectationBitsFactorized(const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get expectation of qubits, interpreting each permutation as an unsigned integer.
Definition: qstabilizer.cpp:728
void AntiCNOT(bitLenInt control, bitLenInt target)
Apply an (anti-)CNOT gate with control and target.
Definition: qstabilizer.cpp:991
void ValidateQubitIndex(bitLenInt qubit)
Definition: qstabilizer.hpp:201
void SetPermutation(const bitCapInt &perm, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qstabilizer.cpp:103
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: qstabilizer.hpp:625
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:382
void IS(bitLenInt qubitIndex)
Apply an inverse phase gate (|0>->|0>, |1>->-i|1>, or "S adjoint") to qubit b.
Definition: qstabilizer.cpp:1655
void MCMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Definition: qstabilizer.hpp:675
void Y(bitLenInt qubitIndex)
Apply a Pauli Y gate to target.
Definition: qstabilizer.cpp:1527
void rowset(const bitLenInt &i, bitLenInt b)
Sets row i equal to the bth observable (X_1,...X_n,Z_1,...,Z_n)
Definition: qstabilizer.hpp:343
virtual void H(bitLenInt qubit)
Apply a Hadamard gate to target.
Definition: qinterface.hpp:931
bool ForceM(bitLenInt t, bool result, bool doForce=true, bool doApply=true)
Measure qubit t.
Definition: qstabilizer.cpp:1999
void Dispose(bitLenInt start, bitLenInt length, const bitCapInt &ignored)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qstabilizer.hpp:591
bool IsSeparableY(const bitLenInt &target)
Returns "true" if target qubit is a Y basis eigenstate.
Definition: qstabilizer.cpp:1965
AmplitudeEntry GetQubitAmplitude(bitLenInt t, bool m)
Get any single basis state amplitude where qubit "t" has value "m".
Definition: qstabilizer.cpp:695
real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qstabilizer.cpp:2743
real1_f SumSqrDiff(QInterfacePtr toCompare)
Calculates (1 - <\psi_e|\psi_c>) between states |\psi_c> and |\psi_e>.
Definition: qstabilizer.hpp:630
bitLenInt Compose(QStabilizerPtr toCopy)
Definition: qstabilizer.hpp:579
std::function< void(void)> DispatchFn
Definition: qstabilizer.hpp:83
void Z(bitLenInt qubitIndex)
Apply a phase gate (|0>->|0>, |1>->-|1>, or "Z") to qubit b.
Definition: qstabilizer.cpp:1557
void RZ(real1_f angle, bitLenInt qubitIndex)
Approximate an arbitrary phase angle.
Definition: qstabilizer.cpp:1799
void SetMajorQuadrant(bitLenInt t, bool b)
Set major vs.
Definition: qstabilizer.hpp:231
real1_f ProbMask(const bitCapInt &mask, const bitCapInt &permutation)
Direct measure of masked permutation probability.
Definition: qstabilizer.cpp:915
bitLenInt maxStateMapCacheQubitCount
Definition: qstabilizer.hpp:54
AmplitudeEntry getBasisAmp(const real1_f &nrm)
Helper for setBasisState() and setBasisProb()
Definition: qstabilizer.cpp:380
real1_f ApproxCompareHelper(QStabilizerPtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON, bool isDiscrete=false)
Definition: qstabilizer.cpp:2626
void DecomposeDispose(const bitLenInt start, const bitLenInt length, QStabilizerPtr toCopy)
Definition: qstabilizer.cpp:2417
void ISBase(bitLenInt qubitIndex)
Apply a phase gate (|0>->|0>, |1>->i|1>, or "S") to qubit b.
Definition: qstabilizer.cpp:1670
void SetRandomSeed(uint32_t seed)
Definition: qstabilizer.hpp:256
void Mtrx(const complex *mtrx, bitLenInt target)
Definition: qstabilizer.cpp:2753
real1 phaseOffset
Definition: qstabilizer.hpp:53
virtual void X(bitLenInt qubit)
Apply an X (or NOT) gate to target.
Definition: qinterface.hpp:1116
bitLenInt gaussian(bool s=true)
Do Gaussian elimination to put the stabilizer generators in the following form: At the top,...
Definition: qstabilizer.cpp:259
void Invert(const complex &topRight, const complex &bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase.
Definition: qstabilizer.cpp:2912
QInterfacePtr Clone()
Clone this QInterface.
Definition: qstabilizer.cpp:82
real1_f getExpectation(const real1_f &nrm, const std::vector< bitCapInt > &bitPowers, const std::vector< bitCapInt > &perms, const bitCapInt &offset)
Returns the (partial) expectation value from a state vector amplitude.
Definition: qstabilizer.cpp:441
std::vector< bool > BoolVector
Definition: qstabilizer.hpp:67
std::function< void(const bitLenInt &)> StabilizerParallelFunc
Definition: qstabilizer.hpp:82
bool IsSeparableZ(const bitLenInt &target)
Returns "true" if target qubit is a Z basis eigenstate.
Definition: qstabilizer.cpp:1923
uint8_t IsSeparable(const bitLenInt &target)
Returns: 0 if target qubit is not separable 1 if target qubit is a Z basis eigenstate 2 if target qub...
Definition: qstabilizer.cpp:1981
bool IsSeparableX(const bitLenInt &target)
Returns "true" if target qubit is an X basis eigenstate.
Definition: qstabilizer.cpp:1953
void AntiCZ(bitLenInt control, bitLenInt target)
Apply an (anti-)CZ gate with control and target.
Definition: qstabilizer.cpp:1200
void SwapNearClifford(bitLenInt c, bitLenInt t)
Definition: qstabilizer.hpp:441
bitCapInt GetMaxQPower()
Get the maximum number of basis states, namely for qubits.
Definition: qstabilizer.hpp:224
void Phase(const complex &topLeft, const complex &bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase.
Definition: qstabilizer.cpp:2878
void HBase(bitLenInt qubitIndex)
Apply a Hadamard gate to target.
Definition: qstabilizer.cpp:1431
real1_f FixAnglePeriod(real1_f angle)
Definition: qstabilizer.hpp:93
void CNOT(bitLenInt control, bitLenInt target)
Apply a CNOT gate with control and target.
Definition: qstabilizer.cpp:944
real1_f ProbPermRdm(const bitCapInt &perm, bitLenInt ancillaeStart)
Under assumption of a QStabilizerHybrid ancillary buffer, trace out the permutation probability of th...
Definition: qstabilizer.cpp:875
void SBase(bitLenInt qubitIndex)
Apply a phase gate (|0>->|0>, |1>->i|1>, or "S") to qubit b.
Definition: qstabilizer.cpp:1610
complex GetAmplitude(const bitCapInt &perm)
Get a single basis state amplitude.
Definition: qstabilizer.cpp:610
std::map< bitCapInt, complex > GetQuantumState()
Convert the state to sparse ket notation.
Definition: qstabilizer.cpp:557
std::vector< BoolVector > x
Definition: qstabilizer.hpp:72
void ResetPhaseOffset()
Definition: qstabilizer.hpp:226
complex GetPhaseOffset()
Definition: qstabilizer.hpp:227
std::vector< complex > GetAmplitudes(std::vector< bitCapInt > perms)
Get a single basis state amplitude.
Definition: qstabilizer.cpp:641
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Compose() a QInterface peer, inserting its qubit into index order at start index.
Definition: qstabilizer.hpp:580
bool GlobalPhaseCompare(QInterfacePtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qstabilizer.hpp:642
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: qstabilizer.hpp:634
bool isStochastic
Definition: qstabilizer.hpp:56
void rowswap(const bitLenInt &i, const bitLenInt &k)
Swaps row i and row k - does not change the logical state.
Definition: qstabilizer.hpp:322
void SetMajorQuadrant(bool q)
Set major vs.
Definition: qstabilizer.hpp:230
void MCInvert(const std::vector< bitLenInt > &controls, const complex &topRight, const complex &bottomLeft, bitLenInt target)
Apply a single bit transformation that reverses bit probability and might effect phase,...
Definition: qstabilizer.cpp:3085
void GetProbs(real1 *outputProbs)
Get all probabilities corresponding to ket notation.
Definition: qstabilizer.cpp:584
std::vector< complex > pBuffer
Definition: qstabilizer.hpp:78
bitLenInt Allocate(bitLenInt start, bitLenInt length)
Allocate new "length" count of |0> state qubits at specified qubit index start position.
Definition: qstabilizer.hpp:597
bool isClifford()
Returns "true" if current state is identifiably within the Clifford set, or "false" if it is not or c...
Definition: qstabilizer.hpp:219
void FSim(real1_f theta, real1_f phi, bitLenInt qubit1, bitLenInt qubit2)
The 2-qubit "fSim" gate, (useful in the simulation of particles with fermionic statistics)
Definition: qstabilizer.cpp:3217
real1_f VarianceBitsFactorized(const std::vector< bitLenInt > &bits, const std::vector< bitCapInt > &perms, const bitCapInt &offset=ZERO_BCI)
Get variance of qubits, interpreting each permutation as an unsigned integer.
Definition: qstabilizer.cpp:801
void CY(bitLenInt control, bitLenInt target)
Apply a CY gate with control and target.
Definition: qstabilizer.cpp:1037
bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qstabilizer.hpp:578
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: qstabilizer.cpp:1356
void IT(bitLenInt t)
Apply half an inverse phase gate.
Definition: qstabilizer.hpp:504
real1_f VarianceFloatsFactorized(const std::vector< bitLenInt > &bits, const std::vector< real1_f > &weights)
Direct measure of variance of listed bit string probability.
Definition: qstabilizer.cpp:838
bool ApproxCompare(QStabilizerPtr toCompare, real1_f error_tol=TRYDECOMPOSE_EPSILON)
Definition: qstabilizer.hpp:638
std::vector< BoolVector > z
Definition: qstabilizer.hpp:74
void Copy(QStabilizerPtr orig)
Definition: qstabilizer.hpp:135
void CNotNearClifford(bitLenInt c, bitLenInt t)
Definition: qstabilizer.cpp:1782
void MACMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Definition: qstabilizer.hpp:687
void FlipQuadrant(bitLenInt t)
Toggle major vs.
Definition: qstabilizer.hpp:238
uint8_t clifford(const bitLenInt &i, const bitLenInt &k)
Return the phase (0,1,2,3) when row i is LEFT-multiplied by row k.
Definition: qstabilizer.cpp:172
void SetAmplitude(const bitCapInt &perm, const complex &amp)
Sets the representational amplitude of a full permutation.
Definition: qstabilizer.hpp:468
void MACPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase, with arbitrary (anti-)control bits.
Definition: qstabilizer.cpp:3012
bitLenInt GetQubitCount()
Get the count of bits in this register.
Definition: qstabilizer.hpp:222
bool TrySeparate(bitLenInt qubit)
Single-qubit TrySeparate()
Definition: qstabilizer.hpp:702
std::vector< BoolVector > r
Definition: qstabilizer.hpp:70
AmplitudeEntry GetAnyAmplitude()
Get any single basis state amplitude.
Definition: qstabilizer.cpp:684
void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qstabilizer.hpp:590
void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register.
Definition: qstabilizer.cpp:1256
std::vector< bitLenInt > EntangledQubits(const bitLenInt &target, const bool &g=true)
Returns all qubits entangled with "target" (including itself)
Definition: qstabilizer.cpp:1848
void setBasisProb(const real1_f &nrm, real1 *outputProbs)
Returns the probability from applying the Pauli operator in the "scratch space" of q to |0....
Definition: qstabilizer.cpp:435
void rowcopy(const bitLenInt &i, const bitLenInt &k)
Sets row i equal to row k.
Definition: qstabilizer.hpp:310
bitLenInt gaussianCached
Definition: qstabilizer.hpp:55
~QStabilizer()
Definition: qstabilizer.hpp:215
void Copy(QInterfacePtr orig)
Definition: qstabilizer.hpp:134
void MCPhase(const std::vector< bitLenInt > &controls, const complex &topLeft, const complex &bottomRight, bitLenInt target)
Apply a single bit transformation that only effects phase, with arbitrary control bits.
Definition: qstabilizer.cpp:2949
void FlushNearClifford(bitLenInt t)
Definition: qstabilizer.cpp:1707
void CZNearClifford(bitLenInt c, bitLenInt t)
Definition: qstabilizer.cpp:1766
real1_f RandFloat()
Definition: qstabilizer.hpp:278
bool isClifford(bitLenInt qubit)
Returns "true" if current qubit state is identifiably within the Clifford set, or "false" if it is no...
Definition: qstabilizer.hpp:220
void Dispatch(DispatchFn fn)
Definition: qstabilizer.hpp:84
void Clear()
Definition: qstabilizer.hpp:287
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 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
QRACK_CONST real1 HALF_R1
Definition: qrack_types.hpp:187
half_float::half real1
Definition: qrack_types.hpp:106
std::complex< real1 > complex
Definition: qrack_types.hpp:140
QRACK_CONST real1 FP_NORM_EPSILON
Definition: qrack_types.hpp:263
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:156
double norm(const complex2 &c)
Definition: complex16x2simd.hpp:122
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:203
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:188
QRACK_CONST real1 ZERO_R1
Definition: qrack_types.hpp:186
float real1_f
Definition: qrack_types.hpp:107
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:262
std::shared_ptr< QStabilizer > QStabilizerPtr
Definition: qstabilizer.hpp:46
QRACK_CONST real1 HALF_PI_R1
Definition: qrack_types.hpp:183
QRACK_CONST real1 PI_R1
Definition: qrack_types.hpp:180
const bitCapInt ONE_BCI
Definition: qrack_types.hpp:141
const bitCapInt ZERO_BCI
Definition: qrack_types.hpp:142
HALF_CONSTEXPR half abs(half arg)
Absolute value.
Definition: half.hpp:2958
half fmod(half x, half y)
Remainder of division.
Definition: half.hpp:2966
#define HALF_R1_F
Definition: qrack_types.hpp:164
#define bitsInByte
Definition: qrack_types.hpp:156
#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 IS_NORM_0(c)
Definition: qrack_types.hpp:28
Definition: qstabilizer.hpp:35
bitCapInt permutation
Definition: qstabilizer.hpp:36
complex amplitude
Definition: qstabilizer.hpp:37
AmplitudeEntry(const bitCapInt &p, const complex &a)
Definition: qstabilizer.hpp:39