QuEST_cpu_local.c
Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
2 
12 # include "QuEST.h"
13 # include "QuEST_internal.h"
14 # include "QuEST_precision.h"
15 # include "mt19937ar.h"
16 
17 # include "QuEST_cpu_internal.h"
18 
19 # include <stdlib.h>
20 # include <stdio.h>
21 # include <math.h>
22 # include <time.h>
23 # include <sys/types.h>
24 
25 # ifdef _OPENMP
26 # include <omp.h>
27 # endif
28 
29 
30 void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel) {
31  if (depolLevel == 0)
32  return;
33 
34  densmatr_mixDepolarisingLocal(qureg, targetQubit, depolLevel);
35 }
36 
37 void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping) {
38  if (damping == 0)
39  return;
40 
41  densmatr_mixDampingLocal(qureg, targetQubit, damping);
42 }
43 
44 void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel){
45  if (depolLevel == 0)
46  return;
47  qreal eta = 2/depolLevel;
48  qreal delta = eta - 1 - sqrt( (eta-1)*(eta-1) - 1 );
49  qreal gamma = 1+delta;
50  // TODO -- test delta too small
51 
52  gamma = 1/(gamma*gamma*gamma);
53  densmatr_mixTwoQubitDephasing(qureg, qubit1, qubit2, depolLevel);
54  densmatr_mixTwoQubitDepolarisingLocal(qureg, qubit1, qubit2, delta, gamma);
55 }
56 
58 
59  return densmatr_calcPurityLocal(qureg);
60 }
61 
63 
65  qreal dist = sqrt(distSquared);
66  return dist;
67 }
68 
70 
72  return scalar;
73 }
74 
76 
77  // save pointers to qureg's pair state
78  qreal* quregPairRePtr = qureg.pairStateVec.real;
79  qreal* quregPairImPtr = qureg.pairStateVec.imag;
80 
81  // populate qureg pair state with pure state (by repointing)
82  qureg.pairStateVec.real = pureState.stateVec.real;
83  qureg.pairStateVec.imag = pureState.stateVec.imag;
84 
85  // calculate fidelity using pairState
86  qreal fid = densmatr_calcFidelityLocal(qureg, pureState);
87 
88  // restore pointers
89  qureg.pairStateVec.real = quregPairRePtr;
90  qureg.pairStateVec.imag = quregPairImPtr;
91 
92  return fid;
93 }
94 
95 void densmatr_initPureState(Qureg qureg, Qureg pureState) {
96 
97  // save pointers to qureg's pair state
98  qreal* quregPairRePtr = qureg.pairStateVec.real;
99  qreal* quregPairImPtr = qureg.pairStateVec.imag;
100 
101  // populate qureg pair state with pure state (by repointing)
102  qureg.pairStateVec.real = pureState.stateVec.real;
103  qureg.pairStateVec.imag = pureState.stateVec.imag;
104 
105  // populate density matrix via it's pairState
106  densmatr_initPureStateLocal(qureg, pureState);
107 
108  // restore pointers
109  qureg.pairStateVec.real = quregPairRePtr;
110  qureg.pairStateVec.imag = quregPairImPtr;
111 }
112 
114 
115  return statevec_calcInnerProductLocal(bra, ket);
116 }
117 
119 
120  // computes the trace using Kahan summation
121  qreal pTotal=0;
122  qreal y, t, c;
123  c = 0;
124 
125  long long int numCols = 1LL << qureg.numQubitsRepresented;
126  long long diagIndex;
127 
128  for (int col=0; col< numCols; col++) {
129  diagIndex = col*(numCols + 1);
130  y = qureg.stateVec.real[diagIndex] - c;
131  t = pTotal + y;
132  c = ( t - pTotal ) - y; // brackets are important
133  pTotal = t;
134  }
135 
136  // does not check imaginary component, by design
137 
138  return pTotal;
139 }
140 
142  // implemented using Kahan summation for greater accuracy at a slight floating
143  // point operation overhead. For more details see https://en.wikipedia.org/wiki/Kahan_summation_algorithm
144  qreal pTotal=0;
145  qreal y, t, c;
146  long long int index;
147  long long int numAmpsPerRank = qureg.numAmpsPerChunk;
148  c = 0.0;
149  for (index=0; index<numAmpsPerRank; index++){
150  // Perform pTotal+=qureg.stateVec.real[index]*qureg.stateVec.real[index]; by Kahan
151 
152  y = qureg.stateVec.real[index]*qureg.stateVec.real[index] - c;
153  t = pTotal + y;
154  // Don't change the bracketing on the following line
155  c = ( t - pTotal ) - y;
156  pTotal = t;
157 
158  // Perform pTotal+=qureg.stateVec.imag[index]*qureg.stateVec.imag[index]; by Kahan
159 
160  y = qureg.stateVec.imag[index]*qureg.stateVec.imag[index] - c;
161  t = pTotal + y;
162  // Don't change the bracketing on the following line
163  c = ( t - pTotal ) - y;
164  pTotal = t;
165  }
166  return pTotal;
167 }
168 
169 
171  // init MPI environment
172 
173  QuESTEnv env;
174  env.rank=0;
175  env.numRanks=1;
176 
177  env.seeds = NULL;
178  env.numSeeds = 0;
179  seedQuESTDefault(&env);
180 
181  return env;
182 }
183 
185  // MPI Barrier goes here in MPI version.
186 }
187 
188 int syncQuESTSuccess(int successCode){
189  return successCode;
190 }
191 
193  free(env.seeds);
194 }
195 
197  printf("EXECUTION ENVIRONMENT:\n");
198  printf("Running locally on one node\n");
199  printf("Number of ranks is %d\n", env.numRanks);
200 # ifdef _OPENMP
201  printf("OpenMP enabled\n");
202  printf("Number of threads available is %d\n", omp_get_max_threads());
203 # else
204  printf("OpenMP disabled\n");
205 # endif
206  printf("Precision: size of qreal is %ld bytes\n", sizeof(qreal));
207 }
208 
209 void getEnvironmentString(QuESTEnv env, char str[200]){
210  int ompStatus=0;
211  int numThreads=1;
212 # ifdef _OPENMP
213  ompStatus=1;
214  numThreads=omp_get_max_threads();
215 # endif
216  sprintf(str, "CUDA=0 OpenMP=%d MPI=0 threads=%d ranks=1", ompStatus, numThreads);
217 }
218 
219 qreal statevec_getRealAmp(Qureg qureg, long long int index){
220  return qureg.stateVec.real[index];
221 }
222 
223 qreal statevec_getImagAmp(Qureg qureg, long long int index){
224  return qureg.stateVec.imag[index];
225 }
226 
227 void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
228 {
229  statevec_compactUnitaryLocal(qureg, targetQubit, alpha, beta);
230 }
231 
232 void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
233 {
234  statevec_unitaryLocal(qureg, targetQubit, u);
235 }
236 
237 void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
238 {
239  statevec_controlledCompactUnitaryLocal(qureg, controlQubit, targetQubit, alpha, beta);
240 }
241 
242 void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
243 {
244  statevec_controlledUnitaryLocal(qureg, controlQubit, targetQubit, u);
245 }
246 
247 void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
248 {
249  statevec_multiControlledUnitaryLocal(qureg, targetQubit, ctrlQubitsMask, ctrlFlipMask, u);
250 }
251 
252 void statevec_pauliX(Qureg qureg, int targetQubit)
253 {
254  statevec_pauliXLocal(qureg, targetQubit);
255 }
256 
257 void statevec_pauliY(Qureg qureg, int targetQubit)
258 {
259  int conjFac = 1;
260  statevec_pauliYLocal(qureg, targetQubit, conjFac);
261 }
262 
263 void statevec_pauliYConj(Qureg qureg, int targetQubit)
264 {
265  int conjFac = -1;
266  statevec_pauliYLocal(qureg, targetQubit, conjFac);
267 }
268 
269 void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
270 {
271  int conjFac = 1;
272  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
273 }
274 
275 void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
276 {
277  int conjFac = -1;
278  statevec_controlledPauliYLocal(qureg, controlQubit, targetQubit, conjFac);
279 }
280 
281 void statevec_hadamard(Qureg qureg, int targetQubit)
282 {
283  statevec_hadamardLocal(qureg, targetQubit);
284 }
285 
286 void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
287 {
288  statevec_controlledNotLocal(qureg, controlQubit, targetQubit);
289 }
290 
291 void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask) {
292 
293  statevec_multiControlledMultiQubitNotLocal(qureg, ctrlMask, targMask);
294 }
295 
296 qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
297 {
298  qreal outcomeProb = statevec_findProbabilityOfZeroLocal(qureg, measureQubit);
299  if (outcome==1)
300  outcomeProb = 1.0 - outcomeProb;
301  return outcomeProb;
302 }
303 
304 qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome) {
305 
306  qreal outcomeProb = densmatr_findProbabilityOfZeroLocal(qureg, measureQubit);
307  if (outcome == 1)
308  outcomeProb = 1.0 - outcomeProb;
309  return outcomeProb;
310 }
311 
312 void statevec_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
313 
314  statevec_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
315 }
316 
317 void densmatr_calcProbOfAllOutcomes(qreal* retProbs, Qureg qureg, int* qubits, int numQubits) {
318 
319  densmatr_calcProbOfAllOutcomesLocal(retProbs, qureg, qubits, numQubits);
320 }
321 
322 void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
323 {
324  statevec_collapseToKnownProbOutcomeLocal(qureg, measureQubit, outcome, stateProb);
325 }
326 
327 void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds) {
328 
329  // free existing seed array, if exists
330  if (env->seeds != NULL)
331  free(env->seeds);
332 
333  // record keys in permanent heap
334  env->seeds = malloc(numSeeds * sizeof *(env->seeds));
335  for (int i=0; i<numSeeds; i++)
336  (env->seeds)[i] = seedArray[i];
337  env->numSeeds = numSeeds;
338 
339  // pass keys to Mersenne Twister seeder
340  init_by_array(seedArray, numSeeds);
341 }
342 
343 void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
344 {
345  statevec_multiControlledTwoQubitUnitaryLocal(qureg, ctrlMask, q1, q2, u);
346 }
347 
348 void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int* targs, int numTargs, ComplexMatrixN u)
349 {
350  statevec_multiControlledMultiQubitUnitaryLocal(qureg, ctrlMask, targs, numTargs, u);
351 }
352 
353 void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
354 {
355  statevec_swapQubitAmpsLocal(qureg, qb1, qb2);
356 }
357 
359 
360  // we must preload qureg.pairStateVec with the elements of op.
361  // instead of needless cloning, we'll just temporarily swap the pointers
362  qreal* rePtr = qureg.pairStateVec.real;
363  qreal* imPtr = qureg.pairStateVec.imag;
364  qureg.pairStateVec.real = op.real;
365  qureg.pairStateVec.imag = op.imag;
366 
368 
369  qureg.pairStateVec.real = rePtr;
370  qureg.pairStateVec.imag = imPtr;
371 }
372 
374 
375  return statevec_calcExpecDiagonalOpLocal(qureg, op);
376 }
377 
379 
380  return densmatr_calcExpecDiagonalOpLocal(qureg, op);
381 }
qreal densmatr_calcTotalProb(Qureg qureg)
void statevec_pauliYConj(Qureg qureg, int targetQubit)
void destroyQuESTEnv(QuESTEnv env)
Destroy the QuEST environment.
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
void init_by_array(unsigned long init_key[], int key_length)
Definition: mt19937ar.c:80
void statevec_multiControlledMultiQubitNot(Qureg qureg, int ctrlMask, int targMask)
void syncQuESTEnv(QuESTEnv env)
Guarantees that all code up to the given point has been executed on all nodes (if running in distribu...
void statevec_controlledNotLocal(Qureg qureg, int controlQubit, int targetQubit)
Definition: QuEST_cpu.c:2679
void statevec_pauliYLocal(Qureg qureg, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2887
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
qreal densmatr_calcHilbertSchmidtDistanceSquaredLocal(Qureg a, Qureg b)
computes Tr((a-b) conjTrans(a-b)) = sum of abs values of (a-b)
Definition: QuEST_cpu.c:934
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal stateProb)
int rank
Definition: QuEST.h:364
void statevec_compactUnitary(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
void seedQuESTDefault(QuESTEnv *env)
Seeds the random number generator with the (master node) current time and process ID.
Definition: QuEST.c:1614
void densmatr_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3616
ComplexArray pairStateVec
Temporary storage for a chunk of the state vector received from another process in the MPI version.
Definition: QuEST.h:343
void getEnvironmentString(QuESTEnv env, char str[200])
Sets str to a string containing information about the runtime environment, including whether simulati...
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
int numSeeds
Definition: QuEST.h:367
void statevec_swapQubitAmpsLocal(Qureg qureg, int qb1, int qb2)
It is ensured that all amplitudes needing to be swapped are on this node.
Definition: QuEST_cpu.c:3922
void statevec_multiControlledUnitary(Qureg qureg, long long int ctrlQubitsMask, long long int ctrlFlipMask, int targetQubit, ComplexMatrix2 u)
void statevec_controlledPauliY(Qureg qureg, int controlQubit, int targetQubit)
void statevec_multiControlledMultiQubitNotLocal(Qureg qureg, int ctrlMask, int targMask)
Definition: QuEST_cpu.c:2778
void statevec_collapseToKnownProbOutcomeLocal(Qureg qureg, int measureQubit, int outcome, qreal totalProbability)
Update the state vector to be consistent with measuring measureQubit=0 if outcome=0 and measureQubit=...
Definition: QuEST_cpu.c:3767
void statevec_hadamard(Qureg qureg, int targetQubit)
void densmatr_mixDepolarising(Qureg qureg, int targetQubit, qreal depolLevel)
void statevec_multiControlledTwoQubitUnitary(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
void statevec_compactUnitaryLocal(Qureg qureg, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:1754
qreal densmatr_calcPurityLocal(Qureg qureg)
Definition: QuEST_cpu.c:872
Complex statevec_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4124
void statevec_multiControlledMultiQubitUnitary(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
This calls swapQubitAmps only when it would involve a distributed communication; if the qubit chunks ...
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
Information about the environment the program is running in.
Definition: QuEST.h:362
void statevec_multiControlledMultiQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int *targs, int numTargs, ComplexMatrixN u)
Definition: QuEST_cpu.c:1912
void statevec_multiControlledTwoQubitUnitaryLocal(Qureg qureg, long long int ctrlMask, int q1, int q2, ComplexMatrix4 u)
Definition: QuEST_cpu.c:1813
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
void statevec_controlledNot(Qureg qureg, int controlQubit, int targetQubit)
#define qreal
void statevec_controlledCompactUnitary(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
void statevec_calcProbOfAllOutcomesLocal(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_cpu.c:3549
void statevec_controlledPauliYConj(Qureg qureg, int controlQubit, int targetQubit)
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
void densmatr_initPureState(Qureg qureg, Qureg pureState)
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
void densmatr_mixTwoQubitDepolarisingLocal(Qureg qureg, int qubit1, int qubit2, qreal delta, qreal gamma)
Definition: QuEST_cpu.c:393
void statevec_controlledPauliYLocal(Qureg qureg, int controlQubit, int targetQubit, int conjFac)
Definition: QuEST_cpu.c:2982
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
void statevec_controlledUnitary(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
qreal densmatr_calcPurity(Qureg qureg)
int numRanks
Definition: QuEST.h:365
void densmatr_mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal dephase)
Definition: QuEST_cpu.c:90
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
void statevec_multiControlledUnitaryLocal(Qureg qureg, int targetQubit, long long int ctrlQubitsMask, long long int ctrlFlipMask, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2268
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
Complex densmatr_calcExpecDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4167
void statevec_pauliXLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:2593
void densmatr_initPureStateLocal(Qureg targetQureg, Qureg copyQureg)
Definition: QuEST_cpu.c:1195
unsigned long int * seeds
Definition: QuEST.h:366
void statevec_pauliY(Qureg qureg, int targetQubit)
void statevec_pauliX(Qureg qureg, int targetQubit)
void densmatr_mixDampingLocal(Qureg qureg, int targetQubit, qreal damping)
Definition: QuEST_cpu.c:180
Represents a system of qubits.
Definition: QuEST.h:322
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
qreal densmatr_calcInnerProductLocal(Qureg a, Qureg b)
computes Tr(conjTrans(a) b) = sum of (a_ij^* b_ij)
Definition: QuEST_cpu.c:969
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)
qreal statevec_calcTotalProb(Qureg qureg)
void densmatr_mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal depolLevel)
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:341
qreal statevec_getImagAmp(Qureg qureg, long long int index)
void densmatr_mixDepolarisingLocal(Qureg qureg, int targetQubit, qreal depolLevel)
Definition: QuEST_cpu.c:131
void statevec_hadamardLocal(Qureg qureg, int targetQubit)
Definition: QuEST_cpu.c:3078
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
void reportQuESTEnv(QuESTEnv env)
Report information about the QuEST environment.
void densmatr_applyDiagonalOpLocal(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4082
void statevec_controlledUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2336
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
int syncQuESTSuccess(int successCode)
Performs a logical AND on all successCodes held by all processes.
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
void densmatr_mixDamping(Qureg qureg, int targetQubit, qreal damping)
void statevec_unitaryLocal(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Definition: QuEST_cpu.c:2026
qreal densmatr_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Definition: QuEST_cpu.c:3402
qreal statevec_getRealAmp(Qureg qureg, long long int index)
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
void seedQuEST(QuESTEnv *env, unsigned long int *seedArray, int numSeeds)
Seeds the random number generator with a custom array of key(s), overriding the default keys.
Represents one complex number.
Definition: QuEST.h:103
QuESTEnv createQuESTEnv(void)
Create the QuEST execution environment.
void statevec_controlledCompactUnitaryLocal(Qureg qureg, int controlQubit, int targetQubit, Complex alpha, Complex beta)
Definition: QuEST_cpu.c:2196
Complex statevec_calcInnerProductLocal(Qureg bra, Qureg ket)
Definition: QuEST_cpu.c:1082
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
void statevec_swapQubitAmps(Qureg qureg, int qb1, int qb2)
qreal densmatr_calcFidelityLocal(Qureg qureg, Qureg pureState)
computes a few dens-columns-worth of (vec^*T) dens * vec
Definition: QuEST_cpu.c:1001
qreal statevec_findProbabilityOfZeroLocal(Qureg qureg, int measureQubit)
Measure the total probability of a specified qubit being in the zero state across all amplitudes in t...
Definition: QuEST_cpu.c:3457