19 #include "qureg/qureg.hpp" 20 #include "util/tinymatrix.hpp" 37 using TMDP = qhipster::TinyMatrix<ComplexDP, 2, 2, 32>;
38 using QRDP = QubitRegister<ComplexDP>;
39 using CST =
const std::size_t;
50 gates(5),
uid( reinterpret_cast<std::size_t>(this) ){
53 gates[0](0,0) = ComplexDP(0.,0.);
gates[0](0,1) = ComplexDP(1.,0.);
54 gates[0](1,0) = ComplexDP(1.,0.);
gates[0](1,1) = ComplexDP(0.,0.);
57 gates[1](0,0) = ComplexDP(0.,0.);
gates[1](0,1) = -ComplexDP(0.,1.);
58 gates[1](1,0) = ComplexDP(0.,1.);
gates[1](1,1) = ComplexDP(0.,0.);
61 gates[2](0,0) = ComplexDP(1.,0.);
gates[2](0,1) = ComplexDP(0.,0.);
62 gates[2](1,0) = ComplexDP(0.,0.);
gates[2](1,1) = ComplexDP(-1.,0.);
65 gates[3](0,0) = ComplexDP(1.,0.);
gates[3](0,1) = ComplexDP(0.,0.);
66 gates[3](1,0) = ComplexDP(0.,0.);
gates[3](1,1) = ComplexDP(1.,0.);
69 double coeff = (1./sqrt(2.));
70 gates[4](0,0) = coeff*ComplexDP(1.,0.);
gates[4](0,1) = coeff*ComplexDP(1.,0.);
71 gates[4](1,0) = coeff*ComplexDP(1.,0.);
gates[4](1,1) = -coeff*ComplexDP(1.,0.);
76 #ifdef ENABLE_MPI //If for some strange reason the MPI environement is not enable through the Base CRTP class, enable using Intel-QS 78 MPI_Initialized(&mpi_is_init);
81 char** argv_tmp =
new char*[argc_tmp];
83 qhipster::mpi::Environment env(argc_tmp, argv_tmp);
86 MPI_Comm_rank(MPI_COMM_WORLD, &
rank);
95 std::mt19937 mt_(
rd());
96 std::uniform_real_distribution<double> dist_(0.0,1.0);
99 if(useFusion ==
true){
101 std::cerr <<
"Warning: enabling fusion may cause inconsistent results." << std::endl;
122 #ifndef RESOURCE_ESTIMATE 129 writer.oneQubitGateCall(label, U.tostr(), qubitIndex);
139 #ifndef RESOURCE_ESTIMATE 146 writer.oneQubitGateCall(
"I",
getGateI().tostr(), qubitIndex);
159 U(1, 1) = ComplexDP(cos(angle), sin(angle));
161 #ifndef RESOURCE_ESTIMATE 162 applyGateU(U, qubit_idx,
"Phase:=" + std::to_string(angle));
168 writer.oneQubitGateCall(
"PShift(theta=" + std::to_string(angle) +
")", U.tostr(), qubitIndex);
181 std::cerr <<
"NOT YET IMPLEMENTED" << std::endl;
193 inline void applyGateCCX(std::size_t ctrl_qubit0, std::size_t ctrl_qubit1, std::size_t target_qubit){
194 this->
applyGateNCU(this->
getGateX(), std::vector<std::size_t> {ctrl_qubit0, ctrl_qubit1}, target_qubit,
"X");
205 inline void applyGateCSwap(std::size_t ctrl_qubit, std::size_t qubit_swap0, std::size_t qubit_swap1){
209 V(0,1) = {0.5, -0.5};
210 V(1,0) = {0.5, -0.5};
214 V_dag(0,0) = {0.5, -0.5};
215 V_dag(0,1) = {0.5, 0.5};
216 V_dag(1,0) = {0.5, 0.5};
217 V_dag(1,1) = {0.5, -0.5};
237 #ifndef RESOURCE_ESTIMATE 244 writer.oneQubitGateCall(
"X",
getGateX().tostr(), qubitIndex);
254 #ifndef RESOURCE_ESTIMATE 261 writer.oneQubitGateCall(
"Y",
getGateY().tostr(), qubitIndex);
271 #ifndef RESOURCE_ESTIMATE 278 writer.oneQubitGateCall(
"Z",
getGateZ().tostr(), qubitIndex);
288 #ifndef RESOURCE_ESTIMATE 295 writer.oneQubitGateCall(
"H",
getGateH().tostr(), qubitIndex);
305 #ifndef RESOURCE_ESTIMATE 312 writer.oneQubitGateCall(
327 #ifndef RESOURCE_ESTIMATE 334 writer.oneQubitGateCall(
335 "R_X(\\theta=" + std::to_string(angle) +
")",
349 #ifndef RESOURCE_ESTIMATE 356 writer.oneQubitGateCall(
357 "R_Y(\\theta=" + std::to_string(angle) +
")",
371 #ifndef RESOURCE_ESTIMATE 378 writer.oneQubitGateCall(
379 "R_Z(\\theta=" + std::to_string(angle) +
")",
425 #ifndef RESOURCE_ESTIMATE 432 writer.twoQubitGateCall( label, U.tostr(), control,
target );
443 #ifndef RESOURCE_ESTIMATE 450 writer.twoQubitGateCall(
"X",
getGateX().tostr(), control,
target );
461 #ifndef RESOURCE_ESTIMATE 468 writer.twoQubitGateCall(
"Y",
getGateY().tostr(), control,
target );
479 #ifndef RESOURCE_ESTIMATE 486 writer.twoQubitGateCall(
"Z",
getGateZ().tostr(), control,
target );
497 #ifndef RESOURCE_ESTIMATE 504 writer.twoQubitGateCall(
"H",
getGateH().tostr(), control,
target );
517 U(1, 1) = ComplexDP(cos(angle), sin(angle));
519 #ifndef RESOURCE_ESTIMATE 526 writer.twoQubitGateCall(
"CPhase", U.tostr(), control,
target );
538 #ifndef RESOURCE_ESTIMATE 545 writer.twoQubitGateCall(
"CR_X",
getGateI().tostr(), control,
target );
557 #ifndef RESOURCE_ESTIMATE 564 writer.twoQubitGateCall(
"CR_Y",
getGateI().tostr(), control,
target );
576 #ifndef RESOURCE_ESTIMATE 583 writer.twoQubitGateCall(
"CR_Z",
getGateI().tostr(), control,
target );
596 writer.twoQubitGateCall(
"SWAP",
getGateI().tostr(), qubit_idx0, qubit_idx1 );
661 MPI_Bcast(&rand, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
662 MPI_Barrier(MPI_COMM_WORLD);
690 inline void PrintStates(std::string
x, std::vector<std::size_t> qubits = {}){
700 GateWriter& getGateWriter(){
710 std::cout <<
"######### Gate counts #########" << std::endl;
714 std::cout <<
"###############################" << std::endl;
724 if(
sim.uid != this->uid){
728 return std::numeric_limits<double>::quiet_NaN();
746 std::random_device
rd;
748 std::uniform_real_distribution<double>
dist;
void applyGateCRotX(CST control, CST target, const double theta)
Apply the given Controlled Rotation about X-axis to the given qubit.
std::size_t gate_count_2qubit
void applyGateZ(CST qubitIndex)
Apply the Pauli Z gate to the given qubit.
TMDP getGateI()
Get the Identity.
QubitRegister< ComplexDP > & getQubitRegister()
Get the Qubit Register object.
void applyGateY(CST qubitIndex)
Apply the Pauli Y gate to the given qubit.
void applyGateCH(CST control, CST target)
Apply Controlled Hadamard on target qubit.
void applyGatePhaseShift(std::size_t qubit_idx, double angle)
Apply phase shift to given Qubit; [[1 0] [0 exp(i*angle)]].
Class definition for IntelSimulator. The purpose of this class is to map the functionality of the und...
IntelSimulator(int numQubits, bool useFusion=false)
Construct a new Intel Simulator object. The constructor also sets up and initialises the MPI environe...
~IntelSimulator()
Destroy the Intel Simulator object.
QubitRegister< ComplexDP > QRDP
void applyGateCZ(CST control, CST target)
Apply Controlled Pauli-Z on target qubit.
void applyGateNCU(const Mat2x2Type &U, const std::vector< std::size_t > &ctrlIndices, std::size_t target, std::string label)
Apply n-control unitary gate to the given qubit target.
CRTP defined class for simulator implementations.
void applyAmplitudeNorm()
Apply normalization to the amplitudes of each state. This is required after a qubit in a state is col...
void applyGateU(const TMDP &U, CST qubitIndex, std::string label="U")
Apply arbitrary user-defined unitary gate to qubit at qubit_idx.
double getStateProbability(CST target)
Get the probability of the specified qubit being in the state |1>
std::pair< std::size_t, std::size_t > getGateCounts()
Print 1 and 2 qubit gate call counts.
void applyGateCY(CST control, CST target)
Apply Controlled Pauli-Y on target qubit.
void applyGateI(std::size_t qubitIndex)
Apply the Identity gate to the given qubit.
void initRegister()
(Re)Initialise the underlying register of the encapsulated simulator to well-defined state (|0....
void applyGateSqrtSwap(std::size_t qubit_idx0, std::size_t qubit_idx1)
Performs Sqrt SWAP gate between two given qubits (half way SWAP)
void applyGateCX(CST control, CST target)
Apply Controlled Pauli-X (CNOT) on target qubit.
void applyGateCU(const TMDP &U, CST control, CST target, std::string label="U")
Apply the given controlled unitary gate on target qubit.
void applyGateCPhaseShift(double angle, unsigned int control, unsigned int target)
Perform controlled phase shift gate.
void applyGateRotZ(CST qubitIndex, double angle)
Apply the given Rotation about Z-axis to the given qubit.
void applyGateSwap(CST qubit_idx0, CST qubit_idx1)
Swap the qubits at the given indices.
qhipster::TinyMatrix< ComplexDP, 2, 2, 32 > TMDP
TMDP getGateX()
Get the Pauli-X gate.
void applyGateCRotY(CST control, CST target, double theta)
Apply the given Controlled Rotation about Y-axis to the given qubit.
void applyGateH(CST qubitIndex)
Apply the Hadamard gate to the given qubit.
void collapseQubit(CST target, bool collapseValue)
Collapses specified qubit in register to the collapseValue without applying normalization.
std::size_t getNumQubits()
Get the number of Qubits.
void PrintStates(std::string x, std::vector< std::size_t > qubits={})
Prints the string x and then for each state of the specified qubits in the superposition,...
bool applyMeasurement(CST target, bool normalize=true)
Apply measurement to a target qubit, randomly collapsing the qubit proportional to the amplitude and ...
std::uniform_real_distribution< double > dist
std::vector< TMDP > gates
void applyGateCCX(std::size_t ctrl_qubit0, std::size_t ctrl_qubit1, std::size_t target_qubit)
Controlled controlled NOT (CCNOT, CCX) gate.
std::size_t gate_count_1qubit
void applyGateRotY(CST qubitIndex, double angle)
Apply the given Rotation about Y-axis to the given qubit.
void applyGateCSwap(std::size_t ctrl_qubit, std::size_t qubit_swap0, std::size_t qubit_swap1)
void applyGateCRotZ(CST control, CST target, const double theta)
Apply the given Controlled Rotation about Z-axis to the given qubit.
complex< double > overlap(IntelSimulator &sim)
Compute overlap between different simulators. Number of qubits must be the same.
TMDP getGateY()
Get the Pauli-Y gate.
void initCaches()
Initialise caches used in NCU operation.
void collapseToBasisZ(CST target, bool collapseValue)
Apply measurement to a target qubit with respect to the Z-basis, collapsing to a specified value (0 o...
void applyGateSqrtX(CST qubitIndex)
Apply the Sqrt{Pauli X} gate to the given qubit.
void applyGateRotX(CST qubitIndex, double angle)
Apply the given Rotation about X-axis to the given qubit.
TMDP getGateZ()
Get the Pauli-Z gate.
Mat2x2Type matrixSqrt(const Mat2x2Type &U)
Calculates the unitary matrix square root (U == VV, where V is returned)
void applyGateX(CST qubitIndex)
Apply the Pauli X gate to the given qubit.
TMDP getGateH()
Get the Hadamard gate.
const QubitRegister< ComplexDP > & getQubitRegister() const
Get the Qubit Register object.