Qrack  9.13
General classical-emulating-quantum development framework
qtensornetwork.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano and the Qrack contributors 2017-2023. All rights reserved.
4 //
5 // QTensorNetwork is a gate-based QInterface descendant wrapping cuQuantum.
6 //
7 // Licensed under the GNU Lesser General Public License V3.
8 // See LICENSE.md in the project root or https://www.gnu.org/licenses/lgpl-3.0.en.html
9 // for details.
10 
11 #pragma once
12 
13 #include "qcircuit.hpp"
14 
15 namespace Qrack {
16 
17 class QTensorNetwork;
18 typedef std::shared_ptr<QTensorNetwork> QTensorNetworkPtr;
19 
20 // #if ENABLE_CUDA
21 // struct TensorMeta {
22 // std::vector<std::vector<int32_t>> modes;
23 // std::vector<std::vector<int64_t>> extents;
24 // };
25 // typedef std::vector<TensorMeta> TensorNetworkMeta;
26 // typedef std::shared_ptr<TensorNetworkMeta> TensorNetworkMetaPtr;
27 // #endif
28 
29 class QTensorNetwork : public QInterface {
30 protected:
31  bool useHostRam;
32  bool isSparse;
34  bool useTGadget;
36 #if ENABLE_OPENCL || ENABLE_CUDA
37  bool isCpu;
38 #endif
39 #if ENABLE_QBDT
40  bool isQBdt;
41 #endif
42  int64_t devID;
46  std::vector<int64_t> deviceIDs;
47  std::vector<QInterfaceEngine> engines;
48  std::vector<QCircuitPtr> circuit;
49  std::vector<std::map<bitLenInt, bool>> measurements;
50 
51  QCircuitPtr GetCircuit(bitLenInt target, std::vector<bitLenInt> controls = std::vector<bitLenInt>())
52  {
53  for (size_t i = 0U; i < measurements.size(); ++i) {
54  size_t l = measurements.size() - (i + 1U);
55  std::map<bitLenInt, bool>& m = measurements[l];
56  ++l;
57 
58  if (m.find(target) != m.end()) {
59  if (circuit.size() == l) {
60  circuit.push_back(std::make_shared<QCircuit>());
61  }
62 
63  return circuit[l];
64  }
65 
66  for (size_t j = 0U; j < controls.size(); ++j) {
67  if (m.find(controls[j]) != m.end()) {
68  if (circuit.size() == l) {
69  circuit.push_back(std::make_shared<QCircuit>());
70  }
71 
72  return circuit[l];
73  }
74  }
75  }
76 
77  return circuit[0U];
78  }
79 
81  {
82  if (target >= qubitCount) {
83  throw std::invalid_argument("QTensorNetwork qubit index values must be within allocated qubit bounds!");
84  }
85  }
86 
87  void CheckQubitCount(bitLenInt target, const std::vector<bitLenInt>& controls)
88  {
89  CheckQubitCount(target);
91  controls, qubitCount, "QTensorNetwork qubit index values must be within allocated qubit bounds!");
92  }
93 
94  void RunMeasurmentLayer(size_t layerId)
95  {
96  const std::map<bitLenInt, bool>& mLayer = measurements[layerId];
97  std::vector<bitLenInt> bits;
98  bits.reserve(mLayer.size());
99  std::vector<bool> values;
100  values.reserve(mLayer.size());
101 
102  for (const auto& m : mLayer) {
103  bits.push_back(m.first);
104  values.push_back(m.second);
105  }
106 
107  layerStack->ForceM(bits, values);
108  }
109 
111 
112  void MakeLayerStack(std::set<bitLenInt> qubits = std::set<bitLenInt>());
113 
114  template <typename Fn> void RunAsAmplitudes(Fn fn, const std::set<bitLenInt>& qubits = std::set<bitLenInt>())
115  {
116  if (qubits.empty()) {
117  MakeLayerStack();
118  return fn(layerStack);
119  }
120 
121  const bitLenInt maxQb = GetThresholdQb();
122  if (qubitCount <= maxQb) {
123  MakeLayerStack();
124  return fn(layerStack);
125  } else {
126  MakeLayerStack(qubits);
128  layerStack = NULL;
129  return fn(ls);
130  }
131  }
132 
133  void Copy(QInterfacePtr orig)
134  {
135  throw std::domain_error("Can't TryDecompose() on QTensorNetwork! (QTensorNetwork does not allow Schmidt "
136  "decomposition in general!)");
137  }
138 
139 public:
140  QTensorNetwork(std::vector<QInterfaceEngine> eng, bitLenInt qBitCount, const bitCapInt& initState = ZERO_BCI,
141  qrack_rand_gen_ptr rgp = nullptr, const complex& phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false,
142  bool randomGlobalPhase = true, bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true,
143  bool useSparseStateVec = false, real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> ignored = {},
144  bitLenInt qubitThreshold = 0, real1_f separation_thresh = _qrack_qunit_sep_thresh);
145 
146  QTensorNetwork(bitLenInt qBitCount, const bitCapInt& initState = ZERO_BCI, qrack_rand_gen_ptr rgp = nullptr,
147  const complex& phaseFac = CMPLX_DEFAULT_ARG, bool doNorm = false, bool randomGlobalPhase = true,
148  bool useHostMem = false, int64_t deviceId = -1, bool useHardwareRNG = true, bool useSparseStateVec = false,
149  real1_f norm_thresh = REAL1_EPSILON, std::vector<int64_t> devList = {}, bitLenInt qubitThreshold = 0U,
150  real1_f separation_thresh = _qrack_qunit_sep_thresh)
151  : QTensorNetwork({}, qBitCount, initState, rgp, phaseFac, doNorm, randomGlobalPhase, useHostMem, deviceId,
152  useHardwareRNG, useSparseStateVec, norm_thresh, devList, qubitThreshold, separation_thresh)
153  {
154  }
155 
156  void SetSdrp(real1_f sdrp)
157  {
158  separabilityThreshold = sdrp;
160  }
161 
162  void SetReactiveSeparate(bool isAggSep) { isReactiveSeparate = isAggSep; }
163 
165  {
166  double toRet;
167  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->GetUnitaryFidelity(); });
168  return toRet;
169  }
170 
171  void SetDevice(int64_t dID) { devID = dID; }
172 
173  void Finish()
174  {
175  if (layerStack) {
176  layerStack->Finish();
177  }
178  };
179 
180  bool isFinished() { return !layerStack || layerStack->isFinished(); }
181 
182  void Dump()
183  {
184  if (layerStack) {
185  layerStack->Dump();
186  }
187  }
188 
190  {
191  if (layerStack) {
192  layerStack->UpdateRunningNorm(norm_thresh);
193  }
194  }
195 
197  real1_f nrm = REAL1_DEFAULT_ARG, real1_f norm_thresh = REAL1_DEFAULT_ARG, real1_f phaseArg = ZERO_R1_F)
198  {
199  if (layerStack) {
200  layerStack->NormalizeState(nrm, norm_thresh, phaseArg);
201  }
202  }
203 
205  {
206  return SumSqrDiff(std::dynamic_pointer_cast<QTensorNetwork>(toCompare));
207  }
209  {
210  real1_f toRet;
211  toCompare->MakeLayerStack();
212  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->SumSqrDiff(toCompare->layerStack); });
213  return toRet;
214  }
215 
216  void SetPermutation(const bitCapInt& initState, const complex& phaseFac = CMPLX_DEFAULT_ARG)
217  {
218  circuit.clear();
219  measurements.clear();
220  layerStack = NULL;
221 
222  circuit.push_back(std::make_shared<QCircuit>());
223 
224  for (bitLenInt i = 0U; i < qubitCount; ++i) {
225  if (bi_compare_0(pow2(i) & initState) != 0) {
226  X(i);
227  }
228  }
229 
230  if ((phaseFac == CMPLX_DEFAULT_ARG) && randGlobalPhase) {
231  real1_f angle = Rand() * 2 * (real1_f)PI_R1;
232  globalPhase = complex((real1)cos(angle), (real1)sin(angle));
233  } else if (phaseFac == CMPLX_DEFAULT_ARG) {
235  } else {
236  globalPhase = phaseFac;
237  }
238  }
239 
241 
243  {
244  RunAsAmplitudes([&](QInterfacePtr ls) { ls->GetQuantumState(state); });
245  }
246  void SetQuantumState(const complex* state)
247  {
248  throw std::domain_error("QTensorNetwork::SetQuantumState() not implemented!");
249  }
251  {
252  throw std::domain_error("QTensorNetwork::SetQuantumState() not implemented!");
253  }
254  void GetProbs(real1* outputProbs)
255  {
256  RunAsAmplitudes([&](QInterfacePtr ls) { ls->GetProbs(outputProbs); });
257  }
258 
260  {
261  complex toRet;
262  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->GetAmplitude(perm); });
263  return toRet;
264  }
265  void SetAmplitude(const bitCapInt& perm, const complex& amp)
266  {
267  throw std::domain_error("QTensorNetwork::SetAmplitude() not implemented!");
268  }
269 
270  using QInterface::Compose;
272  {
273  throw std::domain_error("QTensorNetwork::Compose() not implemented!");
274  }
276  {
277  throw std::domain_error("QTensorNetwork::Decompose() not implemented!");
278  }
280  {
281  throw std::domain_error("QTensorNetwork::Decompose() not implemented!");
282  }
283  void Dispose(bitLenInt start, bitLenInt length)
284  {
285  throw std::domain_error("QTensorNetwork::Dispose() not implemented!");
286  }
287  void Dispose(bitLenInt start, bitLenInt length, const bitCapInt& disposedPerm)
288  {
289  throw std::domain_error("QTensorNetwork::Dispose() not implemented!");
290  }
291 
292  using QInterface::Allocate;
294  {
295  if (start > qubitCount) {
296  throw std::invalid_argument("QTensorNetwork::Allocate() 'start' argument is out-of-bounds!");
297  }
298 
299  if (!length) {
300  return start;
301  }
302 
303  const bitLenInt movedQubits = qubitCount - start;
304  SetQubitCount(qubitCount + length);
305  if (!movedQubits) {
306  return start;
307  }
308 
309  for (bitLenInt i = 0U; i < movedQubits; ++i) {
310  const bitLenInt q = start + movedQubits - (i + 1U);
311  Swap(q, q + length);
312  }
313 
314  return start;
315  }
316 
318  {
319  real1_f toRet;
320  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->Prob(qubit); }, { qubit });
321  return toRet;
322  }
323  real1_f ProbAll(const bitCapInt& fullRegister)
324  {
325  real1_f toRet;
326  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->ProbAll(fullRegister); });
327  return toRet;
328  }
329 
330  bool ForceM(bitLenInt qubit, bool result, bool doForce = true, bool doApply = true);
331 
333  {
334  bitCapInt toRet = ZERO_BCI;
335 
336  const bitLenInt maxQb = GetThresholdQb();
337  if (qubitCount <= maxQb) {
338  MakeLayerStack();
339  toRet = layerStack->MAll();
340  } else {
341  for (bitLenInt i = 0U; i < qubitCount; ++i) {
342  if (M(i)) {
343  bi_or_ip(&toRet, pow2(i));
344  }
345  }
346  }
347 
348  SetPermutation(toRet);
349 
350  return toRet;
351  }
352 
353  std::map<bitCapInt, int> MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots)
354  {
355  std::map<bitCapInt, int> toRet;
356  if (qubitCount <= GetThresholdQb()) {
357  std::set<bitLenInt> qubits;
358  for (const bitCapInt& qPow : qPowers) {
359  qubits.insert(log2(qPow));
360  }
361  RunAsAmplitudes([&](QInterfacePtr ls) { toRet = ls->MultiShotMeasureMask(qPowers, shots); }, qubits);
362  } else {
363  std::vector<bitLenInt> qubits;
364  qubits.reserve(qPowers.size());
365  for (const bitCapInt& qPow : qPowers) {
366  qubits.push_back(log2(qPow));
367  }
368 #if ENABLE_QBDT && !ENABLE_QBDT_CPU_PARALLEL
369  if (isQBdt) {
370  std::mutex mapMtx;
371  par_for(0U, shots, [&](const bitCapIntOcl& ignored, const unsigned& ignored2) {
372  QInterfacePtr clone = Clone();
373  bitCapInt result = ZERO_BCI;
374  for (size_t i = 0U; i < qubits.size(); ++i) {
375  if (clone->M(qubits[i])) {
376  bi_or_ip(&result, pow2(i));
377  }
378  }
379  std::lock_guard<std::mutex> mapLock(mapMtx);
380  ++toRet[result];
381  });
382 
383  return toRet;
384  }
385 #endif
386  for (unsigned shot = 0U; shot < shots; ++shot) {
387  QInterfacePtr clone = Clone();
388  bitCapInt result = ZERO_BCI;
389  for (size_t i = 0U; i < qubits.size(); ++i) {
390  if (clone->M(qubits[i])) {
391  bi_or_ip(&result, pow2(i));
392  }
393  }
394  ++toRet[result];
395  }
396  }
397 
398  return toRet;
399  }
400  void MultiShotMeasureMask(const std::vector<bitCapInt>& qPowers, unsigned shots, unsigned long long* shotsArray)
401  {
402  std::map<bitCapInt, int> toRet;
403  if (qubitCount <= GetThresholdQb()) {
404  std::set<bitLenInt> qubits;
405  for (const bitCapInt& qPow : qPowers) {
406  qubits.insert(log2(qPow));
407  }
408  RunAsAmplitudes([&](QInterfacePtr ls) { ls->MultiShotMeasureMask(qPowers, shots, shotsArray); }, qubits);
409  } else {
410  std::vector<bitLenInt> qubits;
411  qubits.reserve(qPowers.size());
412  for (const bitCapInt& qPow : qPowers) {
413  qubits.push_back(log2(qPow));
414  }
415 #if ENABLE_QBDT && !ENABLE_QBDT_CPU_PARALLEL
416  if (isQBdt) {
417  par_for(0U, shots, [&](const bitCapIntOcl& shot, const unsigned& ignored) {
418  QInterfacePtr clone = Clone();
419  bitCapInt result = ZERO_BCI;
420  for (size_t i = 0U; i < qubits.size(); ++i) {
421  if (clone->M(qubits[i])) {
422  bi_or_ip(&result, pow2(i));
423  }
424  }
425  shotsArray[shot] = (bitCapIntOcl)result;
426  });
427  return;
428  }
429 #endif
430  for (unsigned shot = 0U; shot < shots; ++shot) {
431  QInterfacePtr clone = Clone();
432  bitCapInt result = ZERO_BCI;
433  for (size_t i = 0U; i < qubits.size(); ++i) {
434  if (clone->M(qubits[i])) {
435  bi_or_ip(&result, pow2(i));
436  }
437  }
438  shotsArray[shot] = (bitCapIntOcl)result;
439  }
440  }
441  }
442 
443  void Mtrx(const complex* mtrx, bitLenInt target)
444  {
445  CheckQubitCount(target);
446  layerStack = NULL;
447  GetCircuit(target)->AppendGate(std::make_shared<QCircuitGate>(target, mtrx));
448  }
449  void MCMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
450  {
451  CheckQubitCount(target, controls);
452  layerStack = NULL;
453  bitCapInt m = pow2(controls.size());
454  bi_decrement(&m, 1U);
455  GetCircuit(target, controls)
456  ->AppendGate(std::make_shared<QCircuitGate>(
457  target, mtrx, std::set<bitLenInt>{ controls.begin(), controls.end() }, m));
458  }
459  void MACMtrx(const std::vector<bitLenInt>& controls, const complex* mtrx, bitLenInt target)
460  {
461  CheckQubitCount(target, controls);
462  layerStack = NULL;
463  GetCircuit(target, controls)
464  ->AppendGate(std::make_shared<QCircuitGate>(
465  target, mtrx, std::set<bitLenInt>{ controls.begin(), controls.end() }, ZERO_BCI));
466  }
467  void MCPhase(
468  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target)
469  {
470  CheckQubitCount(target, controls);
471  layerStack = NULL;
472  std::shared_ptr<complex> lMtrx(new complex[4U], std::default_delete<complex[]>());
473  lMtrx.get()[0U] = topLeft;
474  lMtrx.get()[1U] = ZERO_CMPLX;
475  lMtrx.get()[2U] = ZERO_CMPLX;
476  lMtrx.get()[3U] = bottomRight;
477  bitCapInt m = pow2(controls.size());
478  bi_decrement(&m, 1U);
479  GetCircuit(target, controls)
480  ->AppendGate(std::make_shared<QCircuitGate>(
481  target, lMtrx.get(), std::set<bitLenInt>{ controls.begin(), controls.end() }, m));
482  }
483  void MACPhase(
484  const std::vector<bitLenInt>& controls, const complex& topLeft, const complex& bottomRight, bitLenInt target)
485  {
486  CheckQubitCount(target, controls);
487  layerStack = NULL;
488  std::shared_ptr<complex> lMtrx(new complex[4U], std::default_delete<complex[]>());
489  lMtrx.get()[0U] = topLeft;
490  lMtrx.get()[1U] = ZERO_CMPLX;
491  lMtrx.get()[2U] = ZERO_CMPLX;
492  lMtrx.get()[3U] = bottomRight;
493  GetCircuit(target, controls)
494  ->AppendGate(std::make_shared<QCircuitGate>(
495  target, lMtrx.get(), std::set<bitLenInt>{ controls.begin(), controls.end() }, ZERO_BCI));
496  }
497  void MCInvert(
498  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target)
499  {
500  CheckQubitCount(target, controls);
501  layerStack = NULL;
502  std::shared_ptr<complex> lMtrx(new complex[4U], std::default_delete<complex[]>());
503  lMtrx.get()[0U] = ZERO_CMPLX;
504  lMtrx.get()[1U] = topRight;
505  lMtrx.get()[2U] = bottomLeft;
506  lMtrx.get()[3U] = ZERO_CMPLX;
507  bitCapInt m = pow2(controls.size());
508  bi_decrement(&m, 1U);
509  GetCircuit(target, controls)
510  ->AppendGate(std::make_shared<QCircuitGate>(
511  target, lMtrx.get(), std::set<bitLenInt>{ controls.begin(), controls.end() }, m));
512  }
513  void MACInvert(
514  const std::vector<bitLenInt>& controls, const complex& topRight, const complex& bottomLeft, bitLenInt target)
515  {
516  CheckQubitCount(target, controls);
517  layerStack = NULL;
518  std::shared_ptr<complex> lMtrx(new complex[4U], std::default_delete<complex[]>());
519  lMtrx.get()[0U] = ZERO_CMPLX;
520  lMtrx.get()[1U] = topRight;
521  lMtrx.get()[2U] = bottomLeft;
522  lMtrx.get()[3U] = ZERO_CMPLX;
523  GetCircuit(target, controls)
524  ->AppendGate(std::make_shared<QCircuitGate>(
525  target, lMtrx.get(), std::set<bitLenInt>{ controls.begin(), controls.end() }, ZERO_BCI));
526  }
527 
528  void FSim(real1_f theta, real1_f phi, bitLenInt qubit1, bitLenInt qubit2);
529 
531  {
532  if (lambda <= ZERO_R1) {
533  return;
534  }
535 
536  // "lambda" is the overall depolarization strength.
537  // ChatGPT (custom GPT "Elara") reasons that
538  // \epsilon(p) = (1 - p) * \rho + (p / 3) * (X \rho X + Y \rho Y + Z \rho Z),
539  // so we use lambda / 3 for 3 checks.
540  lambda = lambda / 3;
541  if (Rand() < lambda) {
542  Z(qubit);
543  }
544  if (Rand() < lambda) {
545  X(qubit);
546  }
547  if (Rand() < lambda) {
548  Y(qubit);
549  }
550  }
551 };
552 } // namespace Qrack
void bi_or_ip(BigInteger *left, const BigInteger &right)
Definition: big_integer.hpp:429
void bi_decrement(BigInteger *pBigInt, const BIG_INTEGER_WORD &value)
Definition: big_integer.hpp:229
int bi_compare_0(const BigInteger &left)
Definition: big_integer.hpp:134
void par_for(const bitCapIntOcl begin, const bitCapIntOcl end, ParallelFunc fn)
Call fn once for every numerical value between begin and end.
Definition: parallel_for.cpp:50
A "Qrack::QInterface" is an abstract interface exposing qubit permutation state vector with methods t...
Definition: qinterface.hpp:141
virtual bitLenInt Allocate(bitLenInt length)
Allocate new "length" count of |0> state qubits at end of qubit index position.
Definition: qinterface.hpp:470
virtual bitLenInt Compose(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qinterface.hpp:364
bool randGlobalPhase
Definition: qinterface.hpp:144
virtual void SetQubitCount(bitLenInt qb)
Definition: qinterface.hpp:268
bitLenInt qubitCount
Definition: qinterface.hpp:146
real1_f Rand()
Generate a random real number between 0 and 1.
Definition: qinterface.hpp:286
Definition: qtensornetwork.hpp:29
void GetProbs(real1 *outputProbs)
Get the pure quantum state representation.
Definition: qtensornetwork.hpp:254
bitLenInt GetThresholdQb()
Definition: qtensornetwork.cpp:109
QTensorNetwork(bitLenInt qBitCount, const bitCapInt &initState=ZERO_BCI, qrack_rand_gen_ptr rgp=nullptr, const complex &phaseFac=CMPLX_DEFAULT_ARG, bool doNorm=false, bool randomGlobalPhase=true, bool useHostMem=false, int64_t deviceId=-1, bool useHardwareRNG=true, bool useSparseStateVec=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > devList={}, bitLenInt qubitThreshold=0U, real1_f separation_thresh=_qrack_qunit_sep_thresh)
Definition: qtensornetwork.hpp:146
bool useTGadget
Definition: qtensornetwork.hpp:34
void SetQuantumState(const complex *state)
Set an arbitrary pure quantum state representation.
Definition: qtensornetwork.hpp:246
void Decompose(bitLenInt start, QInterfacePtr dest)
Minimally decompose a set of contiguous bits from the separably composed unit, into "destination".
Definition: qtensornetwork.hpp:275
bool isSparse
Definition: qtensornetwork.hpp:32
void MCMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary control bits.
Definition: qtensornetwork.hpp:449
bool useHostRam
Definition: qtensornetwork.hpp:31
QCircuitPtr GetCircuit(bitLenInt target, std::vector< bitLenInt > controls=std::vector< bitLenInt >())
Definition: qtensornetwork.hpp:51
void CheckQubitCount(bitLenInt target)
Definition: qtensornetwork.hpp:80
real1_f Prob(bitLenInt qubit)
Direct measure of bit probability to be in |1> state.
Definition: qtensornetwork.hpp:317
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: qtensornetwork.hpp:497
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: qtensornetwork.hpp:467
QInterfacePtr Clone()
Clone this QInterface.
Definition: qtensornetwork.cpp:197
void Mtrx(const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation.
Definition: qtensornetwork.hpp:443
bool isReactiveSeparate
Definition: qtensornetwork.hpp:33
bitLenInt Allocate(bitLenInt start, bitLenInt length)
Allocate new "length" count of |0> state qubits at specified qubit index start position.
Definition: qtensornetwork.hpp:293
real1_f SumSqrDiff(QInterfacePtr toCompare)
Calculates (1 - <\psi_e|\psi_c>) between states |\psi_c> and |\psi_e>.
Definition: qtensornetwork.hpp:204
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: qtensornetwork.hpp:483
bool isNearClifford
Definition: qtensornetwork.hpp:35
void Copy(QInterfacePtr orig)
Definition: qtensornetwork.hpp:133
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: qtensornetwork.hpp:513
std::map< bitCapInt, int > MultiShotMeasureMask(const std::vector< bitCapInt > &qPowers, unsigned shots)
Statistical measure of masked permutation probability.
Definition: qtensornetwork.hpp:353
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: qtensornetwork.cpp:326
complex globalPhase
Definition: qtensornetwork.hpp:44
complex GetAmplitude(const bitCapInt &perm)
Get the representational amplitude of a full permutation.
Definition: qtensornetwork.hpp:259
real1_f ProbAll(const bitCapInt &fullRegister)
Direct measure of full permutation probability.
Definition: qtensornetwork.hpp:323
void GetQuantumState(complex *state)
Get the pure quantum state representation.
Definition: qtensornetwork.hpp:242
void SetPermutation(const bitCapInt &initState, const complex &phaseFac=CMPLX_DEFAULT_ARG)
Set to a specific permutation of all qubits.
Definition: qtensornetwork.hpp:216
void SetAmplitude(const bitCapInt &perm, const complex &amp)
Sets the representational amplitude of a full permutation.
Definition: qtensornetwork.hpp:265
void DepolarizingChannelWeak1Qb(bitLenInt qubit, real1_f lambda)
Simulate a local qubit depolarizing noise channel, under a stochastic "weak simulation condition....
Definition: qtensornetwork.hpp:530
QInterfacePtr Decompose(bitLenInt start, bitLenInt length)
Schmidt decompose a length of qubits.
Definition: qtensornetwork.hpp:279
int64_t devID
Definition: qtensornetwork.hpp:42
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: qtensornetwork.hpp:196
void SetDevice(int64_t dID)
Set the device index, if more than one device is available.
Definition: qtensornetwork.hpp:171
void CheckQubitCount(bitLenInt target, const std::vector< bitLenInt > &controls)
Definition: qtensornetwork.hpp:87
void SetQuantumState(QInterfacePtr eng)
Definition: qtensornetwork.hpp:250
std::vector< std::map< bitLenInt, bool > > measurements
Definition: qtensornetwork.hpp:49
void SetReactiveSeparate(bool isAggSep)
Set reactive separation option (on by default if available)
Definition: qtensornetwork.hpp:162
void SetSdrp(real1_f sdrp)
Set the "Schmidt decomposition rounding parameter" value, (between 0 and 1)
Definition: qtensornetwork.hpp:156
real1_f separabilityThreshold
Definition: qtensornetwork.hpp:43
double GetUnitaryFidelity()
When "Schmidt-decomposition rounding parameter" ("SDRP") is being used, starting from initial 1....
Definition: qtensornetwork.hpp:164
void MultiShotMeasureMask(const std::vector< bitCapInt > &qPowers, unsigned shots, unsigned long long *shotsArray)
Statistical measure of masked permutation probability (returned as array)
Definition: qtensornetwork.hpp:400
bitLenInt Compose(QInterfacePtr toCopy, bitLenInt start)
Compose() a QInterface peer, inserting its qubit into index order at start index.
Definition: qtensornetwork.hpp:271
void RunMeasurmentLayer(size_t layerId)
Definition: qtensornetwork.hpp:94
std::vector< int64_t > deviceIDs
Definition: qtensornetwork.hpp:46
void MakeLayerStack(std::set< bitLenInt > qubits=std::set< bitLenInt >())
Definition: qtensornetwork.cpp:147
QTensorNetwork(std::vector< QInterfaceEngine > eng, bitLenInt qBitCount, const bitCapInt &initState=ZERO_BCI, qrack_rand_gen_ptr rgp=nullptr, const complex &phaseFac=CMPLX_DEFAULT_ARG, bool doNorm=false, bool randomGlobalPhase=true, bool useHostMem=false, int64_t deviceId=-1, bool useHardwareRNG=true, bool useSparseStateVec=false, real1_f norm_thresh=REAL1_EPSILON, std::vector< int64_t > ignored={}, bitLenInt qubitThreshold=0, real1_f separation_thresh=_qrack_qunit_sep_thresh)
Definition: qtensornetwork.cpp:35
bitCapInt MAll()
Measure permutation state of all coherent bits.
Definition: qtensornetwork.hpp:332
QInterfacePtr layerStack
Definition: qtensornetwork.hpp:45
real1_f SumSqrDiff(QTensorNetworkPtr toCompare)
Definition: qtensornetwork.hpp:208
void Finish()
If asynchronous work is still running, block until it finishes.
Definition: qtensornetwork.hpp:173
bool isFinished()
Returns "false" if asynchronous work is still running, and "true" if all previously dispatched asynch...
Definition: qtensornetwork.hpp:180
void Dispose(bitLenInt start, bitLenInt length)
Minimally decompose a set of contiguous bits from the separably composed unit, and discard the separa...
Definition: qtensornetwork.hpp:283
void MACMtrx(const std::vector< bitLenInt > &controls, const complex *mtrx, bitLenInt target)
Apply an arbitrary single bit unitary transformation, with arbitrary (anti-)control bits.
Definition: qtensornetwork.hpp:459
bool ForceM(bitLenInt qubit, bool result, bool doForce=true, bool doApply=true)
Act as if is a measurement was applied, except force the (usually random) result.
Definition: qtensornetwork.cpp:218
void Dispose(bitLenInt start, bitLenInt length, const bitCapInt &disposedPerm)
Dispose a a contiguous set of qubits that are already in a permutation eigenstate.
Definition: qtensornetwork.hpp:287
std::vector< QInterfaceEngine > engines
Definition: qtensornetwork.hpp:47
std::vector< QCircuitPtr > circuit
Definition: qtensornetwork.hpp:48
void RunAsAmplitudes(Fn fn, const std::set< bitLenInt > &qubits=std::set< bitLenInt >())
Definition: qtensornetwork.hpp:114
void Dump()
If asynchronous work is still running, let the simulator know that it can be aborted.
Definition: qtensornetwork.hpp:182
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: qtensornetwork.hpp:189
Half-precision floating-point type.
Definition: half.hpp:2222
virtual void Y(bitLenInt qubit)
Y gate.
Definition: qinterface.hpp:1101
virtual void X(bitLenInt qubit)
X gate.
Definition: qinterface.hpp:1084
virtual void Z(bitLenInt qubit)
Z gate.
Definition: qinterface.hpp:1117
virtual void U(bitLenInt target, real1_f theta, real1_f phi, real1_f lambda)
General unitary gate.
Definition: rotational.cpp:18
virtual bool M(bitLenInt qubit)
Measurement gate.
Definition: qinterface.hpp:1013
virtual void Swap(bitLenInt qubit1, bitLenInt qubit2)
Swap values of two bits in register.
Definition: gates.cpp:167
GLOSSARY: bitLenInt - "bit-length integer" - unsigned integer ID of qubit position in register bitCap...
Definition: complex16x2simd.hpp:25
void ThrowIfQbIdArrayIsBad(const std::vector< bitLenInt > &controls, const bitLenInt &qubitCount, std::string message)
Definition: qrack_functions.hpp:178
QRACK_CONST real1_f FP_NORM_EPSILON_F
Definition: qrack_types.hpp:259
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:29
const real1_f _qrack_qunit_sep_thresh
Definition: qrack_functions.hpp:235
std::complex< real1 > complex
Definition: qrack_types.hpp:128
bitCapInt pow2(const bitLenInt &p)
Definition: qrack_functions.hpp:136
std::shared_ptr< QTensorNetwork > QTensorNetworkPtr
Definition: qtensornetwork.hpp:17
QRACK_CONST real1 REAL1_EPSILON
Definition: qrack_types.hpp:200
QRACK_CONST real1 ONE_R1
Definition: qrack_types.hpp:185
QRACK_CONST real1 ZERO_R1
Definition: qrack_types.hpp:183
float real1_f
Definition: qrack_types.hpp:95
QRACK_CONST complex CMPLX_DEFAULT_ARG
Definition: qrack_types.hpp:257
std::shared_ptr< QCircuit > QCircuitPtr
Definition: qcircuit.hpp:602
QRACK_CONST complex ZERO_CMPLX
Definition: qrack_types.hpp:253
QRACK_CONST real1 PI_R1
Definition: qrack_types.hpp:178
const bitCapInt ZERO_BCI
Definition: qrack_types.hpp:130
bitLenInt log2(bitCapInt n)
Definition: qrack_functions.hpp:134
half sin(half arg)
Sine function.
Definition: half.hpp:3885
half cos(half arg)
Cosine function.
Definition: half.hpp:3922
#define REAL1_DEFAULT_ARG
Definition: qrack_types.hpp:177
#define bitLenInt
Definition: qrack_types.hpp:38
#define ZERO_R1_F
Definition: qrack_types.hpp:160
#define qrack_rand_gen_ptr
Definition: qrack_types.hpp:156
#define bitCapInt
Definition: qrack_types.hpp:62
#define bitCapIntOcl
Definition: qrack_types.hpp:50