Precision-agnostic types and data structures for representing numbers, quantum states, and operators. More...

Data Structures

struct  Complex
 Represents one complex number. More...
 
struct  ComplexMatrix2
 Represents a 2x2 matrix of complex numbers. More...
 
struct  ComplexMatrix4
 Represents a 4x4 matrix of complex numbers. More...
 
struct  ComplexMatrixN
 Represents a general 2^N by 2^N matrix of complex numbers. More...
 
struct  QuESTEnv
 Information about the environment the program is running in. More...
 
struct  Qureg
 Represents a system of qubits. More...
 
struct  Vector
 Represents a 3-vector of real numbers. More...
 

Macros

#define fromComplex(comp)   qcomp(comp.real, comp.imag)
 
#define getStaticComplexMatrixN(numQubits, re, im)
 Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing, but cannot be returned beyond the calling scope. More...
 
#define qcomp
 
#define qreal   double
 
#define QuEST_PREC   2
 
#define toComplex(scalar)   ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})
 

Enumerations

enum  pauliOpType { PAULI_I =0, PAULI_X =1, PAULI_Y =2, PAULI_Z =3 }
 Codes for specifying Pauli operators. More...
 

Functions

Qureg createCloneQureg (Qureg qureg, QuESTEnv env)
 Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix. More...
 
ComplexMatrixN createComplexMatrixN (int numQubits)
 Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions. More...
 
Qureg createDensityQureg (int numQubits, QuESTEnv env)
 Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states. More...
 
QuESTEnv createQuESTEnv (void)
 Create the QuEST execution environment. More...
 
Qureg createQureg (int numQubits, QuESTEnv env)
 Create a Qureg object representing a set of qubits which will remain in a pure state. More...
 
void destroyComplexMatrixN (ComplexMatrixN matr)
 Destroy a ComplexMatrixN instance created with createComplexMatrixN() More...
 
void destroyQuESTEnv (QuESTEnv env)
 Destroy the QuEST environment. More...
 
void destroyQureg (Qureg qureg, QuESTEnv env)
 Deallocate a Qureg object representing a set of qubits. More...
 
void initComplexMatrixN (ComplexMatrixN m, qreal real[][1<< m.numQubits], qreal imag[][1<< m.numQubits])
 Initialises a ComplexMatrixN instance to have the passed real and imag values. More...
 

Detailed Description

Precision-agnostic types and data structures for representing numbers, quantum states, and operators.

Macro Definition Documentation

◆ fromComplex

#define fromComplex (   comp)    qcomp(comp.real, comp.imag)

Converts a Complex struct to a qcomp native type

Author
Tyson Jones

◆ getStaticComplexMatrixN

#define getStaticComplexMatrixN (   numQubits,
  re,
  im 
)
Value:
numQubits, \
(qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR re, \
(qreal[1<<numQubits][1<<numQubits]) UNPACK_ARR im, \
(double*[1<<numQubits]) {NULL}, (double*[1<<numQubits]) {NULL} \
)

Creates a ComplexMatrixN struct which lives in the stack and so does not need freeing, but cannot be returned beyond the calling scope.

That is, the .real and .imag arrays of the returned ComplexMatrixN live in the stack as opposed to that returned by createComplexMatrixN() (which live in the heap). Note the real and imag components must be wrapped in paranthesis, e.g.

ComplexMatrixN u = getStaticComplexMatrixN(1, ({{1,2},{3,4}}), ({{0}}));

Here is an example of an incorrect usage, since a 'local' ComplexMatrixN cannot leave the calling scope (otherwise inducing dangling pointers):

ComplexMatrixN getMyMatrix(void) {
    return getStaticComplexMatrixN(1, ({{1,2},{3,4}}), ({{0}}));
}

This function is actually a single-line anonymous macro, so can be safely invoked within arguments to other functions, e.g.

 multiQubitUnitary(
     qureg, (int[]) {0}, 1, 
     getStaticComplexMatrixN(1, ({{1,0},{0,1}}), ({{0}}))
 );

The returned ComplexMatrixN can be accessed and modified in the same way as that returned by createComplexMatrixN(), e.g.

 ComplexMatrixN u = getStaticComplexMatrixN(3, ({{0}}), ({{0}}));
 for (int i=0; i<8; i++)
     for (int j=0; j<8; j++)
         u.real[i][j] = .1;

Note that the first argument numQubits must be a literal.

This macro is only callable in C, since it invokes the function bindArraysToStackComplexMatrixN() which is only callable in C.

Author
Tyson Jones

Definition at line 3284 of file QuEST.h.

◆ qcomp

#define qcomp

A precision-agnostic operator-overloaded complex number type.
This is a complex analog of qreal and is of single, double or quad precision depending on the value of QuEST_PREC. It resolves to the native complex type provided by <complex.h> for both C99 and C++11, so can be used with operators. It can be constructed with qcomp(real, imag).

For example, in C,

qcomp x = 2 + 3i;
x -= 3.2*x;

and in C++,

qcomp x = qcomp(2, 3);
x -= 3*x;

Assuming QuEST_PREC=4, qcomp will be 'complex long double' in C and 'complex<long double>' in C++.

Can be converted to/from Complex, the struct accepted by the QuEST interface, using toComplex and fromComplex.

Authors
Randy Meyers and Dr. Thomas Plum (created C & C++ agnosticism)
Author
Tyson Jones (created precision agnosticism)

◆ qreal

#define qreal   double

A precision-agnostic floating point number, as determined by QuEST_PREC. Is a single, double or quad precision float when QuEST_PREC is 1, 2 or 4 respectively.

Author
Ania Brown
Tyson Jones (doc)

◆ QuEST_PREC

#define QuEST_PREC   2

Sets the precision of qreal and qcomp, and generally that of the state-vectors stored by QuEST. QuEST_PREC can be 1, 2 or 4 for single, double and quad precision - requires 4, 8 and 16 bytes per real & imag component per amplitude of the statevector respectively. This should be passed as a macro to the preprocessor during compilation, which overwrites the value explicitly defined in QuEST_precision.h. Note that quad precision is not compatible with most GPUs.

Author
Ania Brown
Tyson Jones (doc)

◆ toComplex

#define toComplex (   scalar)    ((Complex) {.real = creal(scalar), .imag = cimag(scalar)})

Creates a Complex struct, which can be passed to the QuEST API, from a qcomp

Author
Tyson Jones

Enumeration Type Documentation

◆ pauliOpType

Codes for specifying Pauli operators.

Author
Tyson Jones
Enumerator
PAULI_I 
PAULI_X 
PAULI_Y 
PAULI_Z 

Definition at line 96 of file QuEST.h.

96 {PAULI_I=0, PAULI_X=1, PAULI_Y=2, PAULI_Z=3};

Function Documentation

◆ createCloneQureg()

Qureg createCloneQureg ( Qureg  qureg,
QuESTEnv  env 
)

Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or a density matrix.

That is, it will have the same dimensions as the passed qureg and begin in an identical quantum state. This must be destroyed by the user later with destroyQureg()

Returns
an object representing the set of qubits
Parameters
[in]quregan existing qureg to be cloned
[in]envobject representing the execution environment (local, multinode etc)
Author
Tyson Jones

Definition at line 62 of file QuEST.c.

62  {
63 
64  Qureg newQureg;
65  statevec_createQureg(&newQureg, qureg.numQubitsInStateVec, env);
66  newQureg.isDensityMatrix = qureg.isDensityMatrix;
69 
70  qasm_setup(&newQureg);
71  statevec_cloneQureg(newQureg, qureg);
72  return newQureg;
73 }

References Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, qasm_setup(), statevec_cloneQureg(), and statevec_createQureg().

Referenced by TEST_CASE().

◆ createComplexMatrixN()

ComplexMatrixN createComplexMatrixN ( int  numQubits)

Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary functions.

The matrix will have dimensions (2^numQubits) by (2^numQubits), and all elements of .real and .imag are initialised to zero. The ComplexMatrixN must eventually be freed using destroyComplexMatrixN(). Like ComplexMatrix2 and ComplexMatrix4, the returned ComplexMatrixN is safe to return from functions.

One can instead use getStaticComplexMatrixN() to create a ComplexMatrixN struct in the stack (which doesn't need to be later destroyed).

Parameters
[in]numQubitsthe number of qubits of which the returned ComplexMatrixN will correspond
Returns
a dynamic ComplexMatrixN struct, that is one where the .real and .imag fields are arrays kept in the heap and must be later destroyed.
Author
Tyson Jones

Definition at line 1000 of file QuEST.c.

1000  {
1001  validateNumQubitsInMatrix(numQubits, __func__);
1002 
1003  int numRows = 1 << numQubits;
1004 
1005  ComplexMatrixN m = {
1006  .numQubits = numQubits,
1007  .real = malloc(numRows * sizeof *m.real),
1008  .imag = malloc(numRows * sizeof *m.imag)};
1009 
1010  for (int n=0; n < 1<<numQubits; n++) {
1011  m.real[n] = calloc(numRows, sizeof **m.real);
1012  m.imag[n] = calloc(numRows, sizeof **m.imag);
1013  }
1014 
1015  // error if the ComplexMatrixN was not successfully malloc'ds
1016  validateMatrixInit(m, __func__);
1017 
1018  return m;
1019  }

References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, validateMatrixInit(), and validateNumQubitsInMatrix().

Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

◆ createDensityQureg()

Qureg createDensityQureg ( int  numQubits,
QuESTEnv  env 
)

Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.

Allocates space for a density matrix of probability amplitudes, including space for temporary values to be copied from one other chunk if running the distributed version. Define properties related to the size of the set of qubits. initZeroState is automatically called allocation, so that the density qureg begins in the zero state |0><0|.

Returns
an object representing the set of qubits
Parameters
[in]numQubitsnumber of qubits in the system
[in]envobject representing the execution environment (local, multinode etc)
Exceptions
exitWithErrorif numQubits <= 0
Author
Tyson Jones

Definition at line 48 of file QuEST.c.

48  {
49  validateNumQubitsInQureg(2*numQubits, env.numRanks, __func__);
50 
51  Qureg qureg;
52  statevec_createQureg(&qureg, 2*numQubits, env);
53  qureg.isDensityMatrix = 1;
54  qureg.numQubitsRepresented = numQubits;
55  qureg.numQubitsInStateVec = 2*numQubits;
56 
57  qasm_setup(&qureg);
58  initZeroState(qureg); // safe call to public function
59  return qureg;
60 }

References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

Referenced by TEST_CASE().

◆ createQuESTEnv()

QuESTEnv createQuESTEnv ( void  )

Create the QuEST execution environment.

This should be called only once, and the environment should be freed with destroyQuESTEnv at the end of the user's code. If something needs to be done to set up the execution environment, such as initializing MPI when running in distributed mode, it is handled here.

Returns
object representing the execution environment. A single instance is used for each program
Author
Ania Brown

Definition at line 129 of file QuEST_cpu_distributed.c.

129  {
130 
131  QuESTEnv env;
132 
133  // init MPI environment
134  int rank, numRanks, initialized;
135  MPI_Initialized(&initialized);
136  if (!initialized){
137  MPI_Init(NULL, NULL);
138  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
139  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
140 
141  env.rank=rank;
142  env.numRanks=numRanks;
143 
144  } else {
145 
146  printf("ERROR: Trying to initialize QuESTEnv multiple times. Ignoring...\n");
147 
148  // ensure env is initialised anyway, so the compiler is happy
149  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
150  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
151  env.rank=rank;
152  env.numRanks=numRanks;
153  }
154 
155  validateNumRanks(env.numRanks, __func__);
156 
158 
159  return env;
160 }

References GPUExists(), QuESTEnv::numRanks, QuESTEnv::rank, seedQuESTDefault(), and validateNumRanks().

Referenced by main().

◆ createQureg()

Qureg createQureg ( int  numQubits,
QuESTEnv  env 
)

Create a Qureg object representing a set of qubits which will remain in a pure state.

Allocate space for state vector of probability amplitudes, including space for temporary values to be copied from one other chunk if running the distributed version. Define properties related to the size of the set of qubits. The qubits are initialised in the zero state (i.e. initZeroState is automatically called)

Returns
an object representing the set of qubits
Parameters
[in]numQubitsnumber of qubits in the system
[in]envobject representing the execution environment (local, multinode etc)
Exceptions
exitWithErrorif numQubits <= 0
Author
Ania Brown

Definition at line 34 of file QuEST.c.

34  {
35  validateNumQubitsInQureg(numQubits, env.numRanks, __func__);
36 
37  Qureg qureg;
38  statevec_createQureg(&qureg, numQubits, env);
39  qureg.isDensityMatrix = 0;
40  qureg.numQubitsRepresented = numQubits;
41  qureg.numQubitsInStateVec = numQubits;
42 
43  qasm_setup(&qureg);
44  initZeroState(qureg); // safe call to public function
45  return qureg;
46 }

References initZeroState(), Qureg::isDensityMatrix, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, QuESTEnv::numRanks, qasm_setup(), statevec_createQureg(), and validateNumQubitsInQureg().

Referenced by TEST_CASE().

◆ destroyComplexMatrixN()

void destroyComplexMatrixN ( ComplexMatrixN  matr)

Destroy a ComplexMatrixN instance created with createComplexMatrixN()

It is invalid to attempt to destroy a matrix created with getStaticComplexMatrixN().

Parameters
[in]matrthe dynamic matrix (created with createComplexMatrixN()) to deallocate
Exceptions
exitWithErrorif matr was not yet allocated.
malloc_errorif matr was static (created with getStaticComplexMatrixN())
Author
Tyson Jones

Definition at line 1021 of file QuEST.c.

1021  {
1022  /* this checks m.real/imag != NULL, which is only ever set when the mallocs
1023  * in createComplexMatrixN fail, which already prompts an error. Hence
1024  * this check if useless
1025  */
1026  validateMatrixInit(m, __func__);
1027 
1028  int numRows = 1 << m.numQubits;
1029  for (int r=0; r < numRows; r++) {
1030  free(m.real[r]);
1031  free(m.imag[r]);
1032  }
1033  free(m.real);
1034  free(m.imag);
1035 }

References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

Referenced by densmatr_mixMultiQubitKrausMap(), and TEST_CASE().

◆ destroyQuESTEnv()

void destroyQuESTEnv ( QuESTEnv  env)

Destroy the QuEST environment.

If something needs to be done to clean up the execution environment, such as finalizing MPI when running in distributed mode, it is handled here

Parameters
[in]envobject representing the execution environment. A single instance is used for each program
Author
Ania Brown

Definition at line 172 of file QuEST_cpu_distributed.c.

172  {
173  int finalized;
174  MPI_Finalized(&finalized);
175  if (!finalized) MPI_Finalize();
176  else printf("ERROR: Trying to close QuESTEnv multiple times. Ignoring\n");
177 }

Referenced by main().

◆ destroyQureg()

void destroyQureg ( Qureg  qureg,
QuESTEnv  env 
)

Deallocate a Qureg object representing a set of qubits.

Free memory allocated to state vector of probability amplitudes, including temporary vector for values copied from another chunk if running the distributed version.

Parameters
[in,out]quregobject to be deallocated
[in]envobject representing the execution environment (local, multinode etc)
Author
Ania Brown

Definition at line 75 of file QuEST.c.

75  {
76  statevec_destroyQureg(qureg, env);
77  qasm_free(qureg);
78 }

References qasm_free(), and statevec_destroyQureg().

Referenced by TEST_CASE().

◆ initComplexMatrixN()

void initComplexMatrixN ( ComplexMatrixN  m,
qreal  real[][1<< m.numQubits],
qreal  imag[][1<< m.numQubits] 
)

Initialises a ComplexMatrixN instance to have the passed real and imag values.

This allows succint population of any-sized ComplexMatrixN, e.g. through 2D arrays:

ComplexMatrixN m = createComplexMatrixN(3);
initComplexMatrixN(m, 
    (qreal[8][8]) {{1,2,3,4,5,6,7,8}, {0}},
    (qreal[8][8]) {{0}});

m can be created by either createComplexMatrixN() or getStaticComplexMatrixN().

This function is only callable in C, since C++ signatures cannot contain variable-length 2D arrays

Parameters
[in]mthe matrix to initialise
[in]realmatrix of real values; can be 2D array of array of pointers
[in]imagmatrix of imaginary values; can be 2D array of array of pointers
Exceptions
exitWithErrorif m has not been allocated (e.g. with createComplexMatrixN())
Author
Tyson Jones

Definition at line 1037 of file QuEST.c.

1037  {
1038  validateMatrixInit(m, __func__);
1039 
1040  int dim = 1 << m.numQubits;
1041  for (int i=0; i<dim; i++)
1042  for (int j=0; j<dim; j++) {
1043  m.real[i][j] = re[i][j];
1044  m.imag[i][j] = im[i][j];
1045  }
1046 }

References ComplexMatrixN::imag, ComplexMatrixN::numQubits, ComplexMatrixN::real, and validateMatrixInit().

@ PAULI_Z
Definition: QuEST.h:96
int rank
Definition: QuEST.h:201
void qasm_free(Qureg qureg)
Definition: QuEST_qasm.c:500
@ PAULI_I
Definition: QuEST.h:96
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
void statevec_destroyQureg(Qureg qureg, QuESTEnv env)
Definition: QuEST_cpu.c:1316
Information about the environment the program is running in.
Definition: QuEST.h:199
ComplexMatrixN bindArraysToStackComplexMatrixN(int numQubits, qreal re[][1<< numQubits], qreal im[][1<< numQubits], qreal **reStorage, qreal **imStorage)
Definition: QuEST_common.c:606
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
#define qreal
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
@ PAULI_X
Definition: QuEST.h:96
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:167
#define qcomp
void statevec_cloneQureg(Qureg targetQureg, Qureg copyQureg)
works for both statevectors and density matrices
Definition: QuEST_cpu.c:1474
int numRanks
Definition: QuEST.h:202
@ PAULI_Y
Definition: QuEST.h:96
qreal ** real
Definition: QuEST.h:139
Represents a system of qubits.
Definition: QuEST.h:160
void validateNumQubitsInMatrix(int numQubits, const char *caller)
qreal ** imag
Definition: QuEST.h:140
void seedQuESTDefault()
Seed the Mersenne Twister used for random number generation in the QuEST environment with an example ...
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:163
int numQubits
Definition: QuEST.h:138
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:165
void validateNumRanks(int numRanks, const char *caller)
void initZeroState(Qureg qureg)
Initialise a set of qubits to the classical zero state .
Definition: QuEST.c:111
void qasm_setup(Qureg *qureg)
Definition: QuEST_qasm.c:60
void statevec_createQureg(Qureg *qureg, int numQubits, QuESTEnv env)
Definition: QuEST_cpu.c:1278