Calculations

Calculations and property-getters which do not modify the studied quantum state. More...

Functions

qreal calcDensityInnerProduct (Qureg rho1, Qureg rho2)
 Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size. More...
 
Complex calcExpecDiagonalOp (Qureg qureg, DiagonalOp op)
 Computes the expected value of the diagonal operator op for state qureg. More...
 
qreal calcExpecPauliHamil (Qureg qureg, PauliHamil hamil, Qureg workspace)
 Computes the expected value of qureg under Hermitian operator hamil. More...
 
qreal calcExpecPauliProd (Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
 Computes the expected value of a product of Pauli operators. More...
 
qreal calcExpecPauliSum (Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
 Computes the expected value of a sum of products of Pauli operators. More...
 
qreal calcFidelity (Qureg qureg, Qureg pureState)
 Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (necessarily a state-vector). More...
 
qreal calcHilbertSchmidtDistance (Qureg a, Qureg b)
 Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them. More...
 
Complex calcInnerProduct (Qureg bra, Qureg ket)
 Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by. More...
 
void calcProbOfAllOutcomes (qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
 Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubits. More...
 
qreal calcProbOfOutcome (Qureg qureg, int measureQubit, int outcome)
 Gives the probability of a specified qubit being measured in the given outcome (0 or 1). More...
 
qreal calcPurity (Qureg qureg)
 Calculates the purity of a density matrix, by the trace of the density matrix squared. More...
 
qreal calcTotalProb (Qureg qureg)
 A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number). More...
 
Complex getAmp (Qureg qureg, long long int index)
 Get the complex amplitude at a given index in the state vector. More...
 
Complex getDensityAmp (Qureg qureg, long long int row, long long int col)
 Get an amplitude from a density matrix at a given row and column. More...
 
qreal getImagAmp (Qureg qureg, long long int index)
 Get the imaginary component of the complex probability amplitude at an index in the state vector. More...
 
long long int getNumAmps (Qureg qureg)
 Returns the number of complex amplitudes in a state-vector qureg. More...
 
int getNumQubits (Qureg qureg)
 Returns the number of qubits represented by qureg. More...
 
qreal getProbAmp (Qureg qureg, long long int index)
 Get the probability of a state-vector at an index in the full state vector. More...
 
qreal getRealAmp (Qureg qureg, long long int index)
 Get the real component of the complex probability amplitude at an index in the state vector. More...
 

Detailed Description

Calculations and property-getters which do not modify the studied quantum state.

Function Documentation

◆ calcDensityInnerProduct()

qreal calcDensityInnerProduct ( Qureg  rho1,
Qureg  rho2 
)

Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of matrices) of two density matrices rho1 and rho2 of equivalent size.

That is, we define the Hilbert-Schmidt scalar product

\[ ((\rho_1, \rho_2))_{HS} := \text{Tr}[ \rho_1^\dagger \rho_2 ], \]

which is equivalent to the sum of products of matrix elemets, i.e.,

\[ ((\rho_1, \rho_2))_{HS} = \sum\limits_i \sum\limits_j (\rho_1)_{ij}^* (\rho_2)_{ij} \]

Assuming that both density matrices are Hermitian, the resulting scalar product is real and invariant under reordering its arguments as

\[ ((\rho_1, \rho_2))_{HS} = ((\rho_2, \rho_1))_{HS} = \text{Tr}[\rho_1 \rho_2] \]

If both rho1 and rho2 are density matrices of pure states bra and ket, then the equality holds

\[ ((\rho_1, \rho_2))_{HS} = |\langle \text{bra} | \text{ket} \rangle|^2. \]

If either or both of rho1 and rho2 are non Hermitian (i.e. invalid density matrices), then this function returns the real component of the scalar product, and discards the imaginary component. That is, it returns

\[ \text{Re}\{ \text{Tr}[ \rho_1^\dagger \rho_2 ] \} = \text{Re}\{ \text{Tr}[ \rho_2^\dagger \rho_1 ] \}. \]

This is still sometimes useful, e.g. in calculating the inner product with an anti-commutator, e.g. (for Hermitian $ \sigma $, $ \rho $, $ H $)

\[ ((\sigma, H \rho + \rho H))_{HS} = 2 \; \text{Re} \{ ((\sigma, H \rho))_{HS} \} \]

where $ H \rho $ could be a weighted sum of Pauli products applied to $ \rho $ through applyPauliSum().

See also
Parameters
[in]rho1qureg as a density matrix (to have its values conjugate transposed)
[in]rho2qureg as a density matrix
Returns
the real Hilbert-Schmidt scalar product of density matrices rho1 and rho2 (assuming Hermiticity)
Exceptions
invalidQuESTInputError()
  • if rho1 and rho2 are not both density matrices
  • if rho1 and rho2 have mismatching dimensions
Author
Balint Koczor (CPU)
Tyson Jones (GPU)

Definition at line 1158 of file QuEST.c.

1158  {
1159  validateDensityMatrQureg(rho1, __func__);
1160  validateDensityMatrQureg(rho2, __func__);
1161  validateMatchingQuregDims(rho1, rho2, __func__);
1162 
1163  return densmatr_calcInnerProduct(rho1, rho2);
1164 }

References densmatr_calcInnerProduct(), validateDensityMatrQureg(), and validateMatchingQuregDims().

Referenced by TEST_CASE().

◆ calcExpecDiagonalOp()

Complex calcExpecDiagonalOp ( Qureg  qureg,
DiagonalOp  op 
)

Computes the expected value of the diagonal operator op for state qureg.

Since op is not necessarily Hermitian, the expected value may be a complex number.

Let $ D $ be the diagonal operator op, with diagonal elements $ d_i $. Then if qureg is a state-vector $|\psi\rangle $, this function computes

\[ \langle \psi | D | \psi \rangle = \sum_i |\psi_i|^2 \, d_i \]

If qureg is a density matrix $ \rho $, this function computes

\[ \text{Trace}( D \rho ) = \sum_i \rho_{ii} \, d_i \]

See also
Parameters
[in]qurega state-vector or density matrix
[in]opthe diagonal operator to compute the expected value of
Returns
the expected vaulue of the operator
Exceptions
invalidQuESTInputError()
  • if op was not created
  • if op acts on a different number of qubits than qureg represents
Author
Tyson Jones

Definition at line 1228 of file QuEST.c.

1228  {
1229  validateDiagonalOp(qureg, op, __func__);
1230 
1231  if (qureg.isDensityMatrix)
1232  return densmatr_calcExpecDiagonalOp(qureg, op);
1233  else
1234  return statevec_calcExpecDiagonalOp(qureg, op);
1235 }

References densmatr_calcExpecDiagonalOp(), Qureg::isDensityMatrix, statevec_calcExpecDiagonalOp(), and validateDiagonalOp().

Referenced by TEST_CASE().

◆ calcExpecPauliHamil()

qreal calcExpecPauliHamil ( Qureg  qureg,
PauliHamil  hamil,
Qureg  workspace 
)

Computes the expected value of qureg under Hermitian operator hamil.

Represent hamil as $ H = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ (where $ c_i \in $ hamil.termCoeffs and $ N = $ hamil.numQubits). This function computes $ \langle \psi | H | \psi \rangle $ if qureg = $ \psi $ is a state-vector, and computes $ \text{Trace}(H \rho) =\text{Trace}(\rho H) $ if qureg = $ \rho $ is a density matrix.

This function is merely an encapsulation of calcExpecPauliSum() - refer to the doc there for an elaboration.

workspace must be a register with the same type (state-vector vs density matrix) and dimensions (number of represented qubits) as qureg and hamil, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to qureg pre-multiplied with the final Pauli product in hamil. NOTE that if qureg is a density matrix, workspace will become $ \hat{\sigma} \rho $ which is itself not a density matrix (it is distinct from $ \hat{\sigma} \rho \hat{\sigma}^\dagger $).

This function works by cloning the qureg state into workspace, applying each of the specified Pauli products in hamil to workspace (one Pauli operation at a time), then computing its inner product with qureg (for state-vectors) or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions. It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.

See also
Parameters
[in]quregthe register of which to find the expected value, which is unchanged by this function
[in]hamila PauliHamil created with createPauliHamil() or createPauliHamilFromFile()
[in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the final specified Pauli product
Exceptions
invalidQuESTInputError()
  • if any code in hamil.pauliCodes is not a valid Pauli code
  • if hamil.numSumTerms <= 0
  • if workspace is not of the same type and dimensions as qureg and hamil
Author
Tyson Jones

Definition at line 1219 of file QuEST.c.

1219  {
1220  validateMatchingQuregTypes(qureg, workspace, __func__);
1221  validateMatchingQuregDims(qureg, workspace, __func__);
1222  validatePauliHamil(hamil, __func__);
1223  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
1224 
1225  return statevec_calcExpecPauliSum(qureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, workspace);
1226 }

References PauliHamil::numSumTerms, PauliHamil::pauliCodes, statevec_calcExpecPauliSum(), PauliHamil::termCoeffs, validateMatchingQuregDims(), validateMatchingQuregPauliHamilDims(), validateMatchingQuregTypes(), and validatePauliHamil().

Referenced by TEST_CASE().

◆ calcExpecPauliProd()

qreal calcExpecPauliProd ( Qureg  qureg,
int *  targetQubits,
enum pauliOpType pauliCodes,
int  numTargets,
Qureg  workspace 
)

Computes the expected value of a product of Pauli operators.

Letting $ \sigma = \otimes_j \hat{\sigma}_j $ be the operators indicated by pauliCodes and acting on qubits targetQubits, this function computes $ \langle \psi | \sigma | \psi \rangle $ if qureg = $ \psi $ is a state-vector, and computes $ \text{Trace}(\sigma \rho) $ if qureg = $ \rho $ is a density matrix.

pauliCodes is an array of length numTargets which specifies which Pauli operators to enact on the corresponding qubits in targetQubits, where 0 = PAULI_I, 1 = PAULI_X, 2 = PAULI_Y, 3 = PAULI_Z. The target qubits must be unique, and at most qureg.numQubitsRepresented may be specified. For example, on a 7-qubit state-vector,

calcExpecPauliProd(qureg, {4,5,6}, {PAULI_X, PAULI_I, PAULI_Z}, 3, workspace);

will compute $ \langle \psi | I I I I X I Z | \psi \rangle $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

workspace must be a register with the same type (state-vector vs density matrix) and dimensions (number of represented qubits) as qureg, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to $ \sigma | \psi \rangle $ (if qureg is a state-vector) or $ \sigma \rho $ (if qureg is a density matrix). NOTE that this last quantity is NOT the result of applying the paulis as unitaries, $ \sigma^\dagger \rho \sigma $, but is instead the result of their direct multiplication with the density matrix. It is therefore itself not a valid density matrix.

This function works by cloning the qureg state into workspace, applying the specified Pauli operators to workspace then computing its inner product with qureg (for state-vectors) or its trace (for density matrices). It therefore should scale linearly in time with the number of specified non-identity Pauli operators, which is bounded by the number of represented qubits.

See also
Parameters
[in]quregthe register of which to find the expected value, which is unchanged by this function
[in]targetQubitsa list of the indices of the target qubits
[in]pauliCodesa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) to apply to the corresponding qubits in targetQubits
[in]numTargetsnumber of target qubits, i.e. the length of targetQubits and pauliCodes
[in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the pauli operators
Exceptions
invalidQuESTInputError()
  • if numTargets is outside [1, qureg.numQubitsRepresented])
  • if any qubit in targetQubits is outside [0, qureg.numQubitsRepresented))
  • if any qubit in targetQubits is repeated
  • if any code in pauliCodes is not in {0,1,2,3}
  • if workspace is not of the same type and dimensions as qureg
Author
Tyson Jones

Definition at line 1201 of file QuEST.c.

1201  {
1202  validateMultiTargets(qureg, targetQubits, numTargets, __func__);
1203  validatePauliCodes(pauliCodes, numTargets, __func__);
1204  validateMatchingQuregTypes(qureg, workspace, __func__);
1205  validateMatchingQuregDims(qureg, workspace, __func__);
1206 
1207  return statevec_calcExpecPauliProd(qureg, targetQubits, pauliCodes, numTargets, workspace);
1208 }

References statevec_calcExpecPauliProd(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateMultiTargets(), and validatePauliCodes().

Referenced by TEST_CASE().

◆ calcExpecPauliSum()

qreal calcExpecPauliSum ( Qureg  qureg,
enum pauliOpType allPauliCodes,
qreal termCoeffs,
int  numSumTerms,
Qureg  workspace 
)

Computes the expected value of a sum of products of Pauli operators.

Let $ H = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ be the operators indicated by allPauliCodes (where $ c_i \in $ termCoeffs and $ N = $ qureg.numQubitsRepresented). This function computes $ \langle \psi | H | \psi \rangle $ if qureg = $ \psi $ is a state-vector, and computes $ \text{Trace}(H \rho) =\text{Trace}(\rho H) $ if qureg = $ \rho $ is a density matrix.

allPauliCodes is an array of length numSumTerms*qureg.numQubitsRepresented which specifies which Pauli operators to apply, where 0 = PAULI_I, 1 = PAULI_X, 2 = PAULI_Y, 3 = PAULI_Z. For each sum term, a Pauli operator must be specified for EVERY qubit in qureg; each set of numSumTerms operators will be grouped into a product. termCoeffs is an arrray of length numSumTerms containing the term coefficients. For example, on a 3-qubit state-vector,

int paulis[6] = {PAULI_X, PAULI_I, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z};
qreal coeffs[2] = {1.5, -3.6};
calcExpecPauliSum(qureg, paulis, coeffs, 2, workspace);

will compute $ \langle \psi | (1.5 X I I - 3.6 X Y Z) | \psi \rangle $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

workspace must be a register with the same type (state-vector vs density matrix) and dimensions (number of represented qubits) as qureg, and is used as working space. When this function returns, qureg will be unchanged and workspace will be set to qureg pre-multiplied with the final Pauli product. NOTE that if qureg is a density matrix, workspace will become $ \hat{\sigma} \rho $ which is itself not a density matrix (it is distinct from $ \hat{\sigma} \rho \hat{\sigma}^\dagger $).

This function works by cloning the qureg state into workspace, applying each of the specified Pauli products to workspace (one Pauli operation at a time), then computing its inner product with qureg (for state-vectors) or its trace (for density matrices) multiplied with the corresponding coefficient, and summing these contributions. It therefore should scale linearly in time with the total number of non-identity specified Pauli operators.

See also
Parameters
[in]quregthe register of which to find the expected value, which is unchanged by this function
[in]allPauliCodesa list of the Pauli codes (0=PAULI_I, 1=PAULI_X, 2=PAULI_Y, 3=PAULI_Z) of all Paulis involved in the products of terms. A Pauli must be specified for each qubit in the register, in every term of the sum.
[in]termCoeffsThe coefficients of each term in the sum of Pauli products
[in]numSumTermsThe total number of Pauli products specified
[in,out]workspacea working-space qureg with the same dimensions as qureg, which is modified to be the result of multiplying the state with the final specified Pauli product
Exceptions
invalidQuESTInputError()
  • if any code in allPauliCodes is not in {0,1,2,3}
  • if numSumTerms <= 0,
  • if workspace is not of the same type and dimensions as qureg
Author
Tyson Jones

Definition at line 1210 of file QuEST.c.

1210  {
1211  validateNumPauliSumTerms(numSumTerms, __func__);
1212  validatePauliCodes(allPauliCodes, numSumTerms*qureg.numQubitsRepresented, __func__);
1213  validateMatchingQuregTypes(qureg, workspace, __func__);
1214  validateMatchingQuregDims(qureg, workspace, __func__);
1215 
1216  return statevec_calcExpecPauliSum(qureg, allPauliCodes, termCoeffs, numSumTerms, workspace);
1217 }

References Qureg::numQubitsRepresented, statevec_calcExpecPauliSum(), validateMatchingQuregDims(), validateMatchingQuregTypes(), validateNumPauliSumTerms(), and validatePauliCodes().

Referenced by TEST_CASE().

◆ calcFidelity()

qreal calcFidelity ( Qureg  qureg,
Qureg  pureState 
)

Calculates the fidelity of qureg (a state-vector or density matrix) against a reference pure state (necessarily a state-vector).

If qureg is a state-vector, this function computes

\[ |\langle \text{qureg} | \text{pureState} \rangle|^2 \]

If qureg is a density matrix, this function computes

\[ \langle \text{pureState} | \text{qureg} | \text{pureState} \rangle \]

In either case, the returned fidelity lies in [0, 1] (assuming both input states have valid normalisation). If any of the input Quregs are not normalised, this function will return the real component of the correct linear algebra calculation.

The number of qubits represented in qureg and pureState must match.

See also
Parameters
[in]qurega density matrix or state vector
[in]pureStatea state vector
Returns
the fidelity between the input registers
Exceptions
invalidQuESTInputError()
  • if the second argument (pureState) is not a state-vector
  • if the number of qubits in qureg and pureState do not match
Author
Tyson Jones

Definition at line 1191 of file QuEST.c.

1191  {
1192  validateSecondQuregStateVec(pureState, __func__);
1193  validateMatchingQuregDims(qureg, pureState, __func__);
1194 
1195  if (qureg.isDensityMatrix)
1196  return densmatr_calcFidelity(qureg, pureState);
1197  else
1198  return statevec_calcFidelity(qureg, pureState);
1199 }

References densmatr_calcFidelity(), Qureg::isDensityMatrix, statevec_calcFidelity(), validateMatchingQuregDims(), and validateSecondQuregStateVec().

Referenced by TEST_CASE().

◆ calcHilbertSchmidtDistance()

qreal calcHilbertSchmidtDistance ( Qureg  a,
Qureg  b 
)

Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius norm of the difference between them.

That is, we define the Hilbert Schmidt distance

\[ D(a, b) = \| a - b \|_F = \sqrt{ \text{Tr}[ (a-b)(a-b)^\dagger ] } \]

This is equivalent to the square-root of the sum of the absolute value squared of the element-differences of the matrices, i.e.

\[ D(a, b) = \sqrt{ \sum\limits_i \sum\limits_j | a_{ij} - b_{ij} |^2 } \]

We caution this may differ by some definitions of the Hilbert Schmidt distance by a square-root.

This function correctly returns the result of the above formulations even when a and b are incorrectly normalised (i.e. are general matrices).

See also
Parameters
[in]aa density matrix
[in]ban equally-sized density matrix
Exceptions
invalidQuESTInputError()
  • if either a or b are not density matrices
  • if a and have mismatching dimensions
Author
Balint Koczor
Tyson Jones (refactored, doc)

Definition at line 1237 of file QuEST.c.

1237  {
1238  validateDensityMatrQureg(a, __func__);
1239  validateDensityMatrQureg(b, __func__);
1240  validateMatchingQuregDims(a, b, __func__);
1241 
1243 }

References densmatr_calcHilbertSchmidtDistance(), validateDensityMatrQureg(), and validateMatchingQuregDims().

Referenced by TEST_CASE().

◆ calcInnerProduct()

Complex calcInnerProduct ( Qureg  bra,
Qureg  ket 
)

Computes the inner product $ \langle \text{bra} | \text{ket} \rangle $ of two equal-size state vectors, given by.

\[ \langle \text{bra} | \text{ket} \rangle = \sum_i {\text{bra}_i}^* \; \times \; \text{ket}_i \]

The same qureg may be passed as both bra and ket, though we recommend users check state-vector normalisation with calcTotalProb which employs Kahan summation for greater accuracy. Neither state-vector is modified.

This function returns the correct inner product even if bra and ket are not correctly normalised states.

See also
Parameters
[in]braqureg to be the 'bra' (i.e. have its values conjugate transposed) in the inner product
[in]ketqureg to be the 'ket' in the inner product
Returns
the complex inner product of bra and ket
Exceptions
invalidQuESTInputError()
  • if either bra and ket are not both state-vectors
  • if bra and ket do not have equal dimensions
Author
Tyson Jones

Definition at line 1150 of file QuEST.c.

1150  {
1151  validateStateVecQureg(bra, __func__);
1152  validateStateVecQureg(ket, __func__);
1153  validateMatchingQuregDims(bra, ket, __func__);
1154 
1155  return statevec_calcInnerProduct(bra, ket);
1156 }

References statevec_calcInnerProduct(), validateMatchingQuregDims(), and validateStateVecQureg().

Referenced by TEST_CASE().

◆ calcProbOfAllOutcomes()

void calcProbOfAllOutcomes ( qreal outcomeProbs,
Qureg  qureg,
int *  qubits,
int  numQubits 
)

Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubits.

This performs no actual measurement and does not modify qureg.

  • For qubits = {a, b, c, ...}, outcomeProbs is populated to

    \[ \text{outcomeProbs} = \{ \; |\alpha_0|^2, \; |\alpha_1|^2, \; |\alpha_2|^2, \; |\alpha_3|^2, \; ... \; \}, \]

    where $|\alpha_j|^2$ are the probabilities of the respective outcome states (interpreting qubits as ordered least to most significant)

    \[ |\dots\textbf{c\,b\,a}\rangle_i \; \; = \;\; |000\rangle, \;\; |001\rangle \;\; |010\rangle \;\; |011\rangle, \;\; \dots \]

    understood in a state-vector qureg $|\psi\rangle$ as

    \[ |\psi\rangle = \sum\limits_i^{\text{numQubits}} \alpha_i \; |\dots\textbf{c\,b\,a}\rangle_i \; \otimes \; |\phi\rangle_i, \]

    or in a density matrix qureg $\rho$ as

    \[ \begin{aligned} \rho &= \sum\limits_{i,j}^{\text{numQubits}} \; \beta_{ij} \; |\dots\textbf{c\,b\,a}\rangle_i\,\langle\dots\textbf{c\,b\,a}|_j \; \otimes \; \mu_{ij} \\ &= \sum\limits_i^{\text{numQubits}} \; |\alpha_i|^2 \; |\dots\textbf{c\,b\,a}\rangle\langle\dots\textbf{c\,b\,a}|_i \;\; + \, \sum\limits_{i \ne j}^{\text{numQubits}} \; \beta_{ij} \; |\dots\textbf{c\,b\,a}\rangle_i\,\langle\dots\textbf{c\,b\,a}|_j \; \otimes \; \mu_{ij}, \end{aligned} \]

    where $|\phi\rangle_i$ and $\mu_{ij}$ are understood to be the separated states of the remaining qubits.

outcomeProbs must be a pre-allocated array of length $2^{\text{numQubits}}$, which is equivalent to 1<<numQubits. In distributed mode, every node receives the full list of outcome probabilities.

  • Note that the indices in qubits need not be adjacent nor ordered. The order of qubits determines the order of outcomeProbs, whereby qubits are treated as increasing significance.

  • For example, given a qureg initialised into state-vector

    \[ |\psi\rangle = \alpha_0 |000\rangle \;+\; \alpha_1 |001\rangle \;+\; \alpha_2 |010\rangle \;+\; \alpha_3 |011\rangle \;+\; \alpha_4 |100\rangle \;+\; \alpha_5 |101\rangle \;+\; \alpha_6 |110\rangle \;+\; \alpha_7 |111\rangle, \]

    then executing

    int qubits[] = {2, 0};
    int numQubits = 2;
    qreal outcomeProbs[1<<numQubits];
    calcProbOfAllOutcomes(outcomeProbs, qureg, qubits, numQubits);

    would populate outcomeProbs with

    \[ \text{outcomeProbs} = \{ \;\; |\alpha_0|^2+|\alpha_2|^2, \;\; |\alpha_4|^2+|\alpha_6|^2, \;\; |\alpha_1|^2+|\alpha_3|^2, \;\; |\alpha_5|^2+|\alpha_7|^2 \;\; \}. \]

Since all probability amplitudes of a state-vector are ultimately involved in the output probabilities, calcProbOfAllOutcomes() works as expected for un-normalised states. This is similarly true for density matrices, where all diagonal elements are involved, although only the real values of the diagonal elements will be consulted.

See also
Parameters
[out]outcomeProbsa pre-allocated array of length 1<<numQubits, which will be modified to contain all outcome probabilities
[in]qurega state-vector or density matrix to study
[in]qubitsa list of qubits to study
[in]numQubitsthe length of list qubits
Exceptions
invalidQuESTInputError()
  • if numQubits <= 0
  • if any index in qubits is invalid, i.e. outside [0, qureg.numQubitsRepresented )
  • if qubits contains any repetitions
segmentation-fault
  • if outcomeProbs is not pre-allocated
  • if outcomeProbs contains space for fewer than 1<<numQubits elements
Author
Tyson Jones

Definition at line 1176 of file QuEST.c.

1176  {
1177  validateMultiTargets(qureg, qubits, numQubits, __func__);
1178 
1179  if (qureg.isDensityMatrix)
1180  densmatr_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
1181  else
1182  statevec_calcProbOfAllOutcomes(retProbs, qureg, qubits, numQubits);
1183 }

References densmatr_calcProbOfAllOutcomes(), Qureg::isDensityMatrix, statevec_calcProbOfAllOutcomes(), and validateMultiTargets().

Referenced by TEST_CASE().

◆ calcProbOfOutcome()

qreal calcProbOfOutcome ( Qureg  qureg,
int  measureQubit,
int  outcome 
)

Gives the probability of a specified qubit being measured in the given outcome (0 or 1).

This performs no actual measurement and does not change the state of the qubits.

For state-vectors, this function works by summing the absolute-value-squared of every amplitude in the state-vector for which measureQubit = 0. If outcome = 1, it returns 1 minus this value. Hence for unnormalised state-vectors, this result will differ from the absolute-value-squared of every amplitude where measureQubit = outcome.

For density matrices, this function sums the diagonal values (should be real) corresponding to measureQubit = 0 (returning 1 minus this if outcome = 1).

See also
Parameters
[in]quregobject representing the set of all qubits
[in]measureQubitqubit to study
[in]outcomefor which to find the probability of the qubit being measured in
Returns
probability of qubit measureQubit being measured in the given outcome
Exceptions
invalidQuESTInputError()
  • if measureQubit is outside [0, qureg.numQubitsRepresented)
  • if outcome is not in {0, 1}
Author
Ania Brown (state-vector)
Tyson Jones (density matrix)

Definition at line 1166 of file QuEST.c.

1166  {
1167  validateTarget(qureg, measureQubit, __func__);
1168  validateOutcome(outcome, __func__);
1169 
1170  if (qureg.isDensityMatrix)
1171  return densmatr_calcProbOfOutcome(qureg, measureQubit, outcome);
1172  else
1173  return statevec_calcProbOfOutcome(qureg, measureQubit, outcome);
1174 }

References densmatr_calcProbOfOutcome(), Qureg::isDensityMatrix, statevec_calcProbOfOutcome(), validateOutcome(), and validateTarget().

Referenced by TEST_CASE().

◆ calcPurity()

qreal calcPurity ( Qureg  qureg)

Calculates the purity of a density matrix, by the trace of the density matrix squared.

Returns $\text{Tr}(\rho^2)$. For a pure state, this =1. For a mixed state, the purity is less than 1 and is lower bounded by 1/2^n, where n is the number of qubits. The minimum purity is achieved for the maximally mixed state identity/2^n.

This function does not accept state-vectors, which clearly have purity 1.

Note this function will give incorrect results for non-Hermitian Quregs (i.e. invalid density matrices), which will disagree with $\text{Tr}(\rho^2)$. Instead, this function returns $\sum_{ij} |\rho_{ij}|^2 $.

See also
Parameters
[in]qurega density matrix of which to measure the purity
Returns
the purity
Exceptions
invalidQuESTInputError()
  • if either combineQureg or otherQureg are not density matrices
  • if the dimensions of combineQureg and otherQureg do not match
  • if prob is not in [0, 1]
Author
Tyson Jones

Definition at line 1185 of file QuEST.c.

1185  {
1186  validateDensityMatrQureg(qureg, __func__);
1187 
1188  return densmatr_calcPurity(qureg);
1189 }

References densmatr_calcPurity(), and validateDensityMatrQureg().

Referenced by TEST_CASE().

◆ calcTotalProb()

qreal calcTotalProb ( Qureg  qureg)

A debugging function which calculates the probability of the qubits in qureg being in any state, which should always be 1 for correctly normalised states (hence returning a real number).

For state-vectors $ \psi $, this is the norm of the entire state-vector (the sum of the absolute-value-squared of every amplitude):

\[ \sum\limits_i |\psi_i|^2 \]

and for density matrices $ \rho $, it is the trace:

\[ \text{Trace}(\rho) = \sum\limits_i \rho_{i,i} \; \]

For un-normalised density matrices (those directly modified or initialised by the user), this function returns the real component of the trace.

Note this calculation utilises Kahan summation for greater accuracy, and hence is not parallelised and so will be slower than other functions.

Parameters
[in]quregobject representing a set of qubits
Returns
the total probability of the qubits in qureg being in any state
Author
Ania Brown (state-vector)
Tyson Jones (density matrix, doc)

Definition at line 1143 of file QuEST.c.

1143  {
1144  if (qureg.isDensityMatrix)
1145  return densmatr_calcTotalProb(qureg);
1146  else
1147  return statevec_calcTotalProb(qureg);
1148 }

References densmatr_calcTotalProb(), Qureg::isDensityMatrix, and statevec_calcTotalProb().

Referenced by TEST_CASE().

◆ getAmp()

Complex getAmp ( Qureg  qureg,
long long int  index 
)

Get the complex amplitude at a given index in the state vector.

See also
Parameters
[in]quregobject representing a set of qubits
[in]indexindex in state vector of probability amplitudes
Returns
amplitude at index, returned as a Complex struct (with .real and .imag attributes)
Exceptions
invalidQuESTInputError()
  • if qureg is a density matrix
  • if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
Author
Tyson Jones

Definition at line 939 of file QuEST.c.

939  {
940  validateStateVecQureg(qureg, __func__);
941  validateAmpIndex(qureg, index, __func__);
942 
943  Complex amp;
944  amp.real = statevec_getRealAmp(qureg, index);
945  amp.imag = statevec_getImagAmp(qureg, index);
946  return amp;
947 }

References Complex::imag, Complex::real, statevec_getImagAmp(), statevec_getRealAmp(), validateAmpIndex(), and validateStateVecQureg().

Referenced by TEST_CASE().

◆ getDensityAmp()

Complex getDensityAmp ( Qureg  qureg,
long long int  row,
long long int  col 
)

Get an amplitude from a density matrix at a given row and column.

See also
Parameters
[in]quregobject representing a density matrix
[in]rowrow of the desired amplitude in the density matrix
[in]colcolumn of the desired amplitude in the density matrix
Returns
a Complex scalar representing the desired amplitude
Exceptions
invalidQuESTInputError()
  • if qureg is a state-vector,
  • if row or col are outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
Author
Tyson Jones

Definition at line 949 of file QuEST.c.

949  {
950  validateDensityMatrQureg(qureg, __func__);
951  validateAmpIndex(qureg, row, __func__);
952  validateAmpIndex(qureg, col, __func__);
953 
954  long long ind = row + col*(1LL << qureg.numQubitsRepresented);
955  Complex amp;
956  amp.real = statevec_getRealAmp(qureg, ind);
957  amp.imag = statevec_getImagAmp(qureg, ind);
958  return amp;
959 }

References Qureg::numQubitsRepresented, Complex::real, statevec_getImagAmp(), statevec_getRealAmp(), validateAmpIndex(), and validateDensityMatrQureg().

Referenced by TEST_CASE().

◆ getImagAmp()

qreal getImagAmp ( Qureg  qureg,
long long int  index 
)

Get the imaginary component of the complex probability amplitude at an index in the state vector.

See also
Parameters
[in]quregobject representing a set of qubits
[in]indexindex in state vector of probability amplitudes
Returns
imaginary component at that index
Exceptions
invalidQuESTInputError()
  • if qureg is a density matrix
  • if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
Author
Ania Brown

Definition at line 925 of file QuEST.c.

925  {
926  validateStateVecQureg(qureg, __func__);
927  validateAmpIndex(qureg, index, __func__);
928 
929  return statevec_getImagAmp(qureg, index);
930 }

References statevec_getImagAmp(), validateAmpIndex(), and validateStateVecQureg().

Referenced by TEST_CASE().

◆ getNumAmps()

long long int getNumAmps ( Qureg  qureg)

Returns the number of complex amplitudes in a state-vector qureg.

In distributed mode, this returns the total number of amplitudes in the full representation of qureg, and so may be larger than the number stored on each node. For the latter, refer to Qureg.numAmpsPerChunk.

See also
Parameters
[in]qurega state-vecotor
Returns
the total number of complex amplitudes representing qureg.
Exceptions
invalidQuESTInputError()
  • if qureg is a density matrix
Author
Tyson Jones

Definition at line 912 of file QuEST.c.

912  {
913  validateStateVecQureg(qureg, __func__);
914 
915  return qureg.numAmpsTotal;
916 }

References Qureg::numAmpsTotal, and validateStateVecQureg().

Referenced by TEST_CASE().

◆ getNumQubits()

int getNumQubits ( Qureg  qureg)

Returns the number of qubits represented by qureg.

See also
Parameters
[in]qurega state-vecor or density matrix
Returns
qureg.numQubitsRepresented
Author
Tyson Jones

Definition at line 908 of file QuEST.c.

908  {
909  return qureg.numQubitsRepresented;
910 }

References Qureg::numQubitsRepresented.

Referenced by TEST_CASE().

◆ getProbAmp()

qreal getProbAmp ( Qureg  qureg,
long long int  index 
)

Get the probability of a state-vector at an index in the full state vector.

See also
Parameters
[in]quregobject representing a set of qubits
[in]indexindex in state vector of probability amplitudes
Returns
realEl*realEl + imagEl*imagEl
Exceptions
invalidQuESTInputError()
  • if qureg is a density matrix
  • if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
Author
Ania Brown

Definition at line 932 of file QuEST.c.

932  {
933  validateStateVecQureg(qureg, __func__);
934  validateAmpIndex(qureg, index, __func__);
935 
936  return statevec_getProbAmp(qureg, index);
937 }

References statevec_getProbAmp(), validateAmpIndex(), and validateStateVecQureg().

Referenced by TEST_CASE().

◆ getRealAmp()

qreal getRealAmp ( Qureg  qureg,
long long int  index 
)

Get the real component of the complex probability amplitude at an index in the state vector.

See also
Parameters
[in]quregobject representing a set of qubits
[in]indexindex in state vector of probability amplitudes
Returns
real component at that index
Exceptions
invalidQuESTInputError()
  • if qureg is a density matrix
  • if index is outside [0, $2^{N}$) where $N = $ qureg.numQubitsRepresented
Author
Ania Brown

Definition at line 918 of file QuEST.c.

918  {
919  validateStateVecQureg(qureg, __func__);
920  validateAmpIndex(qureg, index, __func__);
921 
922  return statevec_getRealAmp(qureg, index);
923 }

References statevec_getRealAmp(), validateAmpIndex(), and validateStateVecQureg().

Referenced by TEST_CASE().

void validateDensityMatrQureg(Qureg qureg, const char *caller)
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
void validateOutcome(int outcome, const char *caller)
@ PAULI_Z
Definition: QuEST.h:96
void calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
Populates outcomeProbs with the probabilities of every outcome of the sub-register contained in qubit...
Definition: QuEST.c:1176
qreal densmatr_calcInnerProduct(Qureg a, Qureg b)
qreal statevec_calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Definition: QuEST_common.c:509
@ PAULI_I
Definition: QuEST.h:96
void validateStateVecQureg(Qureg qureg, const char *caller)
qreal statevec_calcExpecPauliSum(Qureg qureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Definition: QuEST_common.c:524
qreal densmatr_calcPurity(Qureg qureg)
Computes the trace of the density matrix squared.
qreal statevec_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
void validateNumPauliSumTerms(int numTerms, const char *caller)
qreal statevec_calcFidelity(Qureg qureg, Qureg pureState)
Definition: QuEST_common.c:380
#define qreal
@ PAULI_X
Definition: QuEST.h:96
qreal statevec_getProbAmp(Qureg qureg, long long int index)
Definition: QuEST_common.c:248
qreal densmatr_calcTotalProb(Qureg qureg)
Complex statevec_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
void statevec_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
void densmatr_calcProbOfAllOutcomes(qreal *retProbs, Qureg qureg, int *qubits, int numQubits)
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
@ PAULI_Y
Definition: QuEST.h:96
Complex densmatr_calcExpecDiagonalOp(Qureg qureg, DiagonalOp op)
Complex statevec_calcInnerProduct(Qureg bra, Qureg ket)
Terrible code which unnecessarily individually computes and sums the real and imaginary components of...
qreal statevec_getImagAmp(Qureg qureg, long long int index)
void validatePauliHamil(PauliHamil hamil, const char *caller)
qreal densmatr_calcFidelity(Qureg qureg, Qureg pureState)
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:1210
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
qreal real
Definition: QuEST.h:105
qreal imag
Definition: QuEST.h:106
qreal densmatr_calcHilbertSchmidtDistance(Qureg a, Qureg b)
Represents one complex number.
Definition: QuEST.h:103
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
qreal densmatr_calcProbOfOutcome(Qureg qureg, int measureQubit, int outcome)
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:1201
qreal statevec_getRealAmp(Qureg qureg, long long int index)
qreal statevec_calcTotalProb(Qureg qureg)