Qrack  1.7
General classical-emulating-quantum development framework
qengine_cpu.hpp
Go to the documentation of this file.
1 //
3 // (C) Daniel Strano 2017, 2018. All rights reserved.
4 //
5 // This is a multithreaded, universal quantum register simulation, allowing
6 // (nonphysical) register cloning and direct measurement of probability and
7 // phase, to leverage what advantages classical emulation of qubits can have.
8 //
9 // Licensed under the GNU General Public License V3.
10 // See LICENSE.md in the project root or https://www.gnu.org/licenses/gpl-3.0.en.html
11 // for details.
12 
13 #pragma once
14 
15 #include <algorithm>
16 #include <memory>
17 #include <random>
18 
19 #include "qinterface.hpp"
20 
21 #include "common/parallel_for.hpp"
22 
23 #define ALIGN_SIZE 64
24 
25 namespace Qrack {
26 
27 class QEngineCPU;
28 typedef std::shared_ptr<QEngineCPU> QEngineCPUPtr;
29 
30 template <class BidirectionalIterator>
31 void reverse(BidirectionalIterator first, BidirectionalIterator last, bitCapInt stride);
32 template <class BidirectionalIterator>
33 void rotate(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, bitCapInt stride);
34 
38 class QEngineCPU : public QInterface, public ParallelFor {
39 protected:
40  uint32_t randomSeed;
41  double runningNorm;
43 
44  std::shared_ptr<std::default_random_engine> rand_generator;
45  std::uniform_real_distribution<double> rand_distribution;
46 
47 public:
48  QEngineCPU(bitLenInt qBitCount, bitCapInt initState, std::shared_ptr<std::default_random_engine> rgp = nullptr,
49  complex phaseFac = complex(-999.0, -999.0));
50  ~QEngineCPU() { delete[] stateVec; }
51 
52  virtual void SetQuantumState(complex* inputState);
53  virtual void SetPermutation(bitCapInt perm) { SetReg(0, qubitCount, perm); }
54  virtual void SetRandomSeed(uint32_t seed) { rand_generator->seed(seed); }
55 
56  virtual bitLenInt Cohere(QInterfacePtr toCopy) { return Cohere(std::dynamic_pointer_cast<QEngineCPU>(toCopy)); }
57  std::map<QInterfacePtr, bitLenInt> Cohere(std::vector<QInterfacePtr> toCopy);
58 
59  virtual void Decohere(bitLenInt start, bitLenInt length, QInterfacePtr dest)
60  {
61  Decohere(start, length, std::dynamic_pointer_cast<QEngineCPU>(dest));
62  }
63 
64  virtual bitLenInt Cohere(QEngineCPUPtr toCopy);
65  virtual void Decohere(bitLenInt start, bitLenInt length, QEngineCPUPtr dest);
66  virtual void Dispose(bitLenInt start, bitLenInt length);
67 
73  virtual void CCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target);
74  virtual void AntiCCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target);
75  virtual void CNOT(bitLenInt control, bitLenInt target);
76  virtual void AntiCNOT(bitLenInt control, bitLenInt target);
77  virtual void H(bitLenInt qubitIndex);
78  virtual bool M(bitLenInt qubitIndex);
79  virtual void X(bitLenInt qubitIndex);
80  virtual void Y(bitLenInt qubitIndex);
81  virtual void Z(bitLenInt qubitIndex);
82  virtual void CY(bitLenInt control, bitLenInt target);
83  virtual void CZ(bitLenInt control, bitLenInt target);
84 
96  virtual void AND(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit);
97  virtual void OR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit);
98  virtual void XOR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit);
99  virtual void CLAND(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit);
100  virtual void CLOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit);
101  virtual void CLXOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit);
102 
114  virtual void RT(double radians, bitLenInt qubitIndex);
115  virtual void RX(double radians, bitLenInt qubitIndex);
116  virtual void CRX(double radians, bitLenInt control, bitLenInt target);
117  virtual void RY(double radians, bitLenInt qubitIndex);
118  virtual void CRY(double radians, bitLenInt control, bitLenInt target);
119  virtual void RZ(double radians, bitLenInt qubitIndex);
120  virtual void CRZ(double radians, bitLenInt control, bitLenInt target);
121  virtual void CRT(double radians, bitLenInt control, bitLenInt target);
122 
134  using QInterface::H;
135  virtual void X(bitLenInt start, bitLenInt length);
136  virtual void CNOT(bitLenInt control, bitLenInt target, bitLenInt length);
137  virtual void AntiCNOT(bitLenInt control, bitLenInt target, bitLenInt length);
138  virtual void CCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target, bitLenInt length);
139  virtual void AntiCCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target, bitLenInt length);
140  virtual void AND(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit, bitLenInt length);
141  virtual void OR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit, bitLenInt length);
142  virtual void XOR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit, bitLenInt length);
143 
152  virtual void ROL(bitLenInt shift, bitLenInt start, bitLenInt length);
153  virtual void ROR(bitLenInt shift, bitLenInt start, bitLenInt length);
154  virtual void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length);
155  virtual void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
156  virtual void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex);
157  virtual void INCSC(
158  bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex);
159  virtual void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
160  virtual void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length);
161  virtual void INCBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
162  virtual void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length);
163  virtual void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
164  virtual void DECS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex);
165  virtual void DECSC(
166  bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex);
167  virtual void DECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
168  virtual void DECBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length);
169  virtual void DECBCDC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex);
170 
179  virtual void ZeroPhaseFlip(bitLenInt start, bitLenInt length);
180  virtual void CPhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex);
181  virtual void PhaseFlip();
182  virtual void SetReg(bitLenInt start, bitLenInt length, bitCapInt value);
183  virtual bitCapInt MReg(bitLenInt start, bitLenInt length);
184  virtual bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
185  bitLenInt valueLength, unsigned char* values);
186  virtual bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
187  bitLenInt valueLength, bitLenInt carryIndex, unsigned char* values);
188  virtual bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart,
189  bitLenInt valueLength, bitLenInt carryIndex, unsigned char* values);
190  virtual void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2);
191  virtual void Swap(bitLenInt start1, bitLenInt start2, bitLenInt length);
192 
201  virtual complex* GetState();
202  virtual void CopyState(QInterfacePtr orig);
203  virtual double Prob(bitLenInt qubitIndex);
204  virtual double ProbAll(bitCapInt fullRegister);
205  virtual void SetBit(bitLenInt qubitIndex1, bool value);
206 
209 protected:
211  double Rand() { return rand_distribution(*rand_generator); }
212 
213  virtual void ResetStateVec(complex* nStateVec);
214  virtual void Apply2x2(bitCapInt offset1, bitCapInt offset2, const complex* mtrx, const bitLenInt bitCount,
215  const bitCapInt* qPowersSorted, bool doCalcNorm);
216  virtual void ApplySingleBit(bitLenInt qubitIndex, const complex* mtrx, bool doCalcNorm);
217  virtual void ApplyControlled2x2(bitLenInt control, bitLenInt target, const complex* mtrx, bool doCalcNorm);
218  virtual void ApplyAntiControlled2x2(bitLenInt control, bitLenInt target, const complex* mtrx, bool doCalcNorm);
219  virtual void ApplyDoublyControlled2x2(
220  bitLenInt control1, bitLenInt control2, bitLenInt target, const complex* mtrx, bool doCalcNorm);
221  virtual void ApplyDoublyAntiControlled2x2(
222  bitLenInt control1, bitLenInt control2, bitLenInt target, const complex* mtrx, bool doCalcNorm);
223  virtual void NormalizeState();
224  virtual void UpdateRunningNorm();
225  virtual complex* AllocStateVec(bitCapInt elemCount);
226 };
227 } // namespace Qrack
virtual void Y(bitLenInt qubitIndex)
Apply Pauli Y matrix to bit.
Definition: gates.cpp:123
virtual void H(bitLenInt qubitIndex)=0
Hadamard gate.
virtual void H(bitLenInt qubitIndex)
Hadamard gate.
Definition: gates.cpp:104
virtual void ROL(bitLenInt shift, bitLenInt start, bitLenInt length)
"Circular shift left" - shift bits left, and carry last bits.
Definition: operators.cpp:18
virtual void CY(bitLenInt control, bitLenInt target)
Apply controlled Pauli Y matrix to bit.
Definition: gates.cpp:141
virtual void INCSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Add an integer to the register, with sign and with carry.
Definition: operators.cpp:349
virtual void ResetStateVec(complex *nStateVec)
Definition: state.cpp:70
Definition: parallel_for.hpp:22
virtual void ZeroPhaseFlip(bitLenInt start, bitLenInt length)
For chips with a zero flag, flip the phase of the state where the register equals zero...
Definition: operators.cpp:779
virtual void AntiCCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target)
"Anti-doubly-controlled not" - Apply "not" if control bits are both zero, do not apply if either cont...
Definition: gates.cpp:62
virtual void INCBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add BCD integer (without sign)
Definition: operators.cpp:166
virtual void RY(double radians, bitLenInt qubitIndex)
y axis rotation gate - Rotates as e^(-i*/2) around Pauli y axis
Definition: rotational.cpp:36
virtual void INCBCDC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add BCD integer (without sign, with carry)
Definition: operators.cpp:217
virtual bitCapInt IndexedSBC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char *values)
Subtract based on an indexed load from classical memory.
Definition: operators.cpp:1037
virtual void CZ(bitLenInt control, bitLenInt target)
Apply controlled Pauli Z matrix to bit.
Definition: gates.cpp:152
virtual void CRX(double radians, bitLenInt control, bitLenInt target)
Controlled x axis rotation - if control bit is true, rotates as e^(-i*/2) around Pauli x axis...
Definition: rotational.cpp:67
virtual void SetQuantumState(complex *inputState)
Set arbitrary pure quantum state, in unsigned int permutation basis.
Definition: state.cpp:77
virtual void CLXOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit)
"XOR" compare a qubit in QEngineCPU with a classical bit, and store result in outputBit ...
Definition: operators.cpp:160
virtual void CRY(double radians, bitLenInt control, bitLenInt target)
Controlled y axis rotation - if control bit is true, rotates as e^(-i*) around Pauli y axis...
Definition: rotational.cpp:78
virtual bitCapInt IndexedADC(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, bitLenInt carryIndex, unsigned char *values)
Add based on an indexed load from classical memory.
Definition: operators.cpp:936
virtual void CopyState(QInterfacePtr orig)
Direct copy of raw state vector to produce a clone.
Definition: state.cpp:60
virtual void INCS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Add an integer to the register, with sign and without carry.
Definition: operators.cpp:297
virtual void RT(double radians, bitLenInt qubitIndex)
"Phase shift gate" - Rotates as e^(-i*/2) around |1> state
Definition: rotational.cpp:18
virtual void ApplyDoublyAntiControlled2x2(bitLenInt control1, bitLenInt control2, bitLenInt target, const complex *mtrx, bool doCalcNorm)
Definition: qengine.cpp:79
virtual void CCNOT(bitLenInt control1, bitLenInt control2, bitLenInt target)
Doubly-controlled not.
Definition: gates.cpp:45
virtual void DECBCDC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract BCD integer (without sign, with carry)
Definition: operators.cpp:705
virtual void ApplyDoublyControlled2x2(bitLenInt control1, bitLenInt control2, bitLenInt target, const complex *mtrx, bool doCalcNorm)
Definition: qengine.cpp:66
virtual complex * AllocStateVec(bitCapInt elemCount)
Definition: state.cpp:439
virtual void XOR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit)
"XOR" compare two bits in QEngineCPU, and store result in outputBit
Definition: operators.cpp:122
virtual void CRT(double radians, bitLenInt control, bitLenInt target)
Controlled "phase shift gate" - if control bit is true, rotates target bit as e^(-i*/2) around |1> st...
Definition: rotational.cpp:54
virtual void AND(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit)
"AND" compare two bits in QEngineCPU, and store result in outputBit
Definition: operators.cpp:20
virtual bitLenInt Cohere(QInterfacePtr toCopy)
Combine another QInterface with this one, after the last bit index of this one.
Definition: qengine_cpu.hpp:56
virtual void ApplyAntiControlled2x2(bitLenInt control, bitLenInt target, const complex *mtrx, bool doCalcNorm)
Definition: qengine.cpp:55
virtual void INCC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Add integer (without sign, with carry)
Definition: operators.cpp:75
#define complex
Definition: qinterface.hpp:30
virtual bitCapInt MReg(bitLenInt start, bitLenInt length)
Measure permutation state of a register.
Definition: operators.cpp:821
virtual void ApplySingleBit(bitLenInt qubitIndex, const complex *mtrx, bool doCalcNorm)
Definition: qengine.cpp:37
virtual void Decohere(bitLenInt start, bitLenInt length, QInterfacePtr dest)
Minimally decohere a set of contiguous bits from the full coherent unit, into "destination.".
Definition: qengine_cpu.hpp:59
virtual void SetRandomSeed(uint32_t seed)
Definition: qengine_cpu.hpp:54
std::shared_ptr< QEngineCPU > QEngineCPUPtr
Definition: qengine_cpu.hpp:27
virtual void SetBit(bitLenInt qubitIndex1, bool value)
Set individual bit to pure |0> (false) or |1> (true) state.
Definition: gates.cpp:20
virtual void ApplyControlled2x2(bitLenInt control, bitLenInt target, const complex *mtrx, bool doCalcNorm)
Definition: qengine.cpp:44
virtual void Dispose(bitLenInt start, bitLenInt length)
Minimally decohere a set of contigious bits from the full coherent unit, throwing these qubits away...
Definition: state.cpp:349
virtual bitCapInt IndexedLDA(bitLenInt indexStart, bitLenInt indexLength, bitLenInt valueStart, bitLenInt valueLength, unsigned char *values)
Set 8 bit register bits based on read from classical memory.
Definition: operators.cpp:894
virtual void Z(bitLenInt qubitIndex)
Apply Pauli Z matrix to bit.
Definition: gates.cpp:132
virtual void CLOR(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit)
"OR" compare a qubit in QEngineCPU with a classical bit, and store result in outputBit ...
Definition: operators.cpp:111
virtual void CNOT(bitLenInt control, bitLenInt target)
Controlled not.
Definition: gates.cpp:78
virtual void UpdateRunningNorm()
Definition: state.cpp:437
virtual void PhaseFlip()
Phase flip always - equivalent to Z X Z X on any bit in the QEngineCPU.
Definition: gates.cpp:258
double runningNorm
Definition: qengine_cpu.hpp:41
~QEngineCPU()
Definition: qengine_cpu.hpp:50
virtual void OR(bitLenInt inputBit1, bitLenInt inputBit2, bitLenInt outputBit)
"OR" compare two bits in QEngineCPU, and store result in outputBit
Definition: operators.cpp:71
#define bitCapInt
Definition: qinterface.hpp:21
QEngineCPU(bitLenInt qBitCount, bitCapInt initState, std::shared_ptr< std::default_random_engine > rgp=nullptr, complex phaseFac=complex(-999.0,-999.0))
Initialize a coherent unit with qBitCount number of bits, to initState unsigned integer permutation s...
Definition: state.cpp:26
virtual void CPhaseFlipIfLess(bitCapInt greaterPerm, bitLenInt start, bitLenInt length, bitLenInt flagIndex)
The 6502 uses its carry flag also as a greater-than/less-than flag, for the CMP operation.
Definition: operators.cpp:786
#define bitLenInt
Definition: qinterface.hpp:20
virtual void INC(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Add integer (without sign)
Definition: operators.cpp:144
void rotate(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, bitCapInt stride)
Definition: qengine.cpp:28
virtual void RZ(double radians, bitLenInt qubitIndex)
z axis rotation gate - Rotates as e^(-i*/2) around Pauli z axis
Definition: rotational.cpp:45
virtual void RX(double radians, bitLenInt qubitIndex)
x axis rotation gate - Rotates as e^(-i*/2) around Pauli x axis
Definition: rotational.cpp:27
virtual void Apply2x2(bitCapInt offset1, bitCapInt offset2, const complex *mtrx, const bitLenInt bitCount, const bitCapInt *qPowersSorted, bool doCalcNorm)
Apply a 2x2 matrix to the state vector.
Definition: state.cpp:144
General purpose QEngineCPU implementation.
Definition: qengine_cpu.hpp:38
virtual complex * GetState()
Definition: state.cpp:58
std::shared_ptr< std::default_random_engine > rand_generator
Definition: qengine_cpu.hpp:44
virtual bool M(bitLenInt qubitIndex)
Measurement gate.
Definition: gates.cpp:18
A "Qrack::QInterface" is an abstract interface exposing qubit permutation state vector with methods t...
Definition: qinterface.hpp:81
virtual void Swap(bitLenInt qubitIndex1, bitLenInt qubitIndex2)
Swap values of two bits in register.
Definition: gates.cpp:28
virtual void DECS(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex)
Subtract an integer from the register, with sign and without carry.
Definition: operators.cpp:538
virtual void X(bitLenInt qubitIndex)
NOT gate, which is also Pauli x matrix.
Definition: gates.cpp:114
double Rand()
Generate a random double from 0 to 1.
Definition: qengine_cpu.hpp:211
virtual void DECC(bitCapInt toSub, bitLenInt start, bitLenInt length, bitLenInt carryIndex)
Subtract integer (without sign, with carry)
Definition: operators.cpp:109
virtual void SetReg(bitLenInt start, bitLenInt length, bitCapInt value)
Set register bits to given permutation.
Definition: operators.cpp:798
bitLenInt qubitCount
Definition: qinterface.hpp:83
uint32_t randomSeed
Definition: qengine_cpu.hpp:40
virtual void ROR(bitLenInt shift, bitLenInt start, bitLenInt length)
"Circular shift right" - shift bits right, and carry first bits.
Definition: operators.cpp:46
virtual void CLAND(bitLenInt inputQBit, bool inputClassicalBit, bitLenInt outputBit)
"AND" compare a qubit in QEngineCPU with a classical bit, and store result in outputBit ...
Definition: operators.cpp:60
virtual void DECBCD(bitCapInt toAdd, bitLenInt start, bitLenInt length)
Subtract BCD integer (without sign)
Definition: operators.cpp:482
std::shared_ptr< QInterface > QInterfacePtr
Definition: qinterface.hpp:34
virtual void NormalizeState()
Definition: state.cpp:426
virtual void DEC(bitCapInt toSub, bitLenInt start, bitLenInt length)
Subtract integer (without sign)
Definition: operators.cpp:461
virtual double ProbAll(bitCapInt fullRegister)
PSEUDO-QUANTUM Direct measure of full register probability to be in permutation state.
Definition: state.cpp:417
void reverse(BidirectionalIterator first, BidirectionalIterator last, bitCapInt stride)
Definition: qengine.cpp:18
virtual void AntiCNOT(bitLenInt control, bitLenInt target)
"Anti-controlled not" - Apply "not" if control bit is zero, do not apply if control bit is one...
Definition: gates.cpp:91
Definition: complex16simd.hpp:21
virtual void CRZ(double radians, bitLenInt control, bitLenInt target)
Controlled z axis rotation - if control bit is true, rotates as e^(-i*) around Pauli z axis...
Definition: rotational.cpp:89
complex * stateVec
Definition: qengine_cpu.hpp:42
virtual void DECSC(bitCapInt toAdd, bitLenInt start, bitLenInt length, bitLenInt overflowIndex, bitLenInt carryIndex)
Subtract an integer from the register, with sign and with carry.
Definition: operators.cpp:590
std::uniform_real_distribution< double > rand_distribution
Definition: qengine_cpu.hpp:45
virtual double Prob(bitLenInt qubitIndex)
PSEUDO-QUANTUM Direct measure of bit probability to be in |1> state.
Definition: state.cpp:397
virtual void SetPermutation(bitCapInt perm)
Set to a specific permutation.
Definition: qengine_cpu.hpp:53