Operators

Non-physical operators which may be non-unitary, non-norm-preserving, even non-Hermitian. More...

Functions

void applyDiagonalOp (Qureg qureg, DiagonalOp op)
 Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg. More...
 
void applyFullQFT (Qureg qureg)
 Applies the quantum Fourier transform (QFT) to the entirety of qureg. More...
 
void applyMatrix2 (Qureg qureg, int targetQubit, ComplexMatrix2 u)
 Apply a general 2-by-2 matrix, which may be non-unitary. More...
 
void applyMatrix4 (Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
 Apply a general 4-by-4 matrix, which may be non-unitary. More...
 
void applyMatrixN (Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits. More...
 
void applyMultiControlledMatrixN (Qureg qureg, int *ctrls, int numCtrls, int *targs, int numTargs, ComplexMatrixN u)
 Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits. More...
 
void applyMultiVarPhaseFunc (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
 Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polynomial "phase function". More...
 
void applyMultiVarPhaseFuncOverrides (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
 Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices. More...
 
void applyNamedPhaseFunc (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
 Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-variable) phase function. More...
 
void applyNamedPhaseFuncOverrides (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
 Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-variable) phase function, and an explicit set of 'overriding' values at specific state indices. More...
 
void applyParamNamedPhaseFunc (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
 Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potentially multi-variable) phase function. More...
 
void applyParamNamedPhaseFuncOverrides (Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
 Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potentially multi-variable) phase function, and an explicit set of 'overriding' values at specific state indices. More...
 
void applyPauliHamil (Qureg inQureg, PauliHamil hamil, Qureg outQureg)
 Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyPauliSum (Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
 Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg. More...
 
void applyPhaseFunc (Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
 Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function". More...
 
void applyPhaseFuncOverrides (Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
 Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices. More...
 
void applyProjector (Qureg qureg, int qubit, int outcome)
 Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection. More...
 
void applyQFT (Qureg qureg, int *qubits, int numQubits)
 Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg. More...
 
void applyTrotterCircuit (Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
 Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg. More...
 

Detailed Description

Non-physical operators which may be non-unitary, non-norm-preserving, even non-Hermitian.

Function Documentation

◆ applyDiagonalOp()

void applyDiagonalOp ( Qureg  qureg,
DiagonalOp  op 
)

Apply a diagonal operator, which is possibly non-unitary and non-Hermitian, to the entire qureg.

Let $d_j = \text{op.real}[j] + (\text{op.imag}[j])\,\text{i} $, and

\[ \hat{D} = \begin{pmatrix} d_0 \\ & d_1 \\ & & \ddots \\ & & & d_{2^{\text{op.numQubits}}-1} \end{pmatrix}. \]

If qureg is a state-vector $|\psi\rangle$, this function performs $|\psi\rangle \rightarrow \hat{D} \, |\psi\rangle$.
If qureg is a density-matrix $\rho$, this function performs $\rho \rightarrow \hat{D}\, \rho$. Notice this has not applied $\hat{D}$ in the fashion of a unitary.

If your operator is unitary with unit amplitudes, the phases of which can be described by an analytic expression, you should instead use applyPhaseFunc() or applyNamedPhaseFunc() for significant memory and runtime savings.

See also
Parameters
[in,out]quregthe state to operate the diagonal operator upon
[in]opthe diagonal operator to apply
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 1127 of file QuEST.c.

1127  {
1128  validateDiagonalOp(qureg, op, __func__);
1129 
1130  if (qureg.isDensityMatrix)
1131  densmatr_applyDiagonalOp(qureg, op);
1132  else
1133  statevec_applyDiagonalOp(qureg, op);
1134 
1135  qasm_recordComment(qureg, "Here, the register was modified to an undisclosed and possibly unphysical state (via applyDiagonalOp).");
1136 }

References densmatr_applyDiagonalOp(), Qureg::isDensityMatrix, qasm_recordComment(), statevec_applyDiagonalOp(), and validateDiagonalOp().

Referenced by TEST_CASE().

◆ applyFullQFT()

void applyFullQFT ( Qureg  qureg)

Applies the quantum Fourier transform (QFT) to the entirety of qureg.

The effected unitary circuit (shown here for 4 qubits, bottom qubit is 0) resembles

\[ \begin{tikzpicture}[scale=.5] \draw (-2, 5) -- (23, 5); \draw (-2, 3) -- (23, 3); \draw (-2, 1) -- (23, 1); \draw (-2, -1) -- (23, -1); \draw[fill=white] (-1, 4) -- (-1, 6) -- (1, 6) -- (1,4) -- cycle; \node[draw=none] at (0, 5) {H}; \draw(2, 5) -- (2, 3); \draw[fill=black] (2, 5) circle (.2); \draw[fill=black] (2, 3) circle (.2); \draw(4, 5) -- (4, 1); \draw[fill=black] (4, 5) circle (.2); \draw[fill=black] (4, 1) circle (.2); \draw(6, 5) -- (6, -1); \draw[fill=black] (6, 5) circle (.2); \draw[fill=black] (6, -1) circle (.2); \draw[fill=white] (-1+8, 4-2) -- (-1+8, 6-2) -- (1+8, 6-2) -- (1+8,4-2) -- cycle; \node[draw=none] at (8, 5-2) {H}; \draw(10, 5-2) -- (10, 3-2); \draw[fill=black] (10, 5-2) circle (.2); \draw[fill=black] (10, 3-2) circle (.2); \draw(12, 5-2) -- (12, 3-4); \draw[fill=black] (12, 5-2) circle (.2); \draw[fill=black] (12, 3-4) circle (.2); \draw[fill=white] (-1+8+6, 4-4) -- (-1+8+6, 6-4) -- (1+8+6, 6-4) -- (1+8+6,4-4) -- cycle; \node[draw=none] at (8+6, 5-4) {H}; \draw(16, 5-2-2) -- (16, 3-4); \draw[fill=black] (16, 5-2-2) circle (.2); \draw[fill=black] (16, 3-4) circle (.2); \draw[fill=white] (-1+8+6+4, 4-4-2) -- (-1+8+6+4, 6-4-2) -- (1+8+6+4, 6-4-2) -- (1+8+6+4,4-4-2) -- cycle; \node[draw=none] at (8+6+4, 5-4-2) {H}; \draw (20, 5) -- (20, -1); \draw (20 - .35, 5 + .35) -- (20 + .35, 5 - .35); \draw (20 - .35, 5 - .35) -- (20 + .35, 5 + .35); \draw (20 - .35, -1 + .35) -- (20 + .35, -1 - .35); \draw (20 - .35, -1 - .35) -- (20 + .35, -1 + .35); \draw (22, 3) -- (22, 1); \draw (22 - .35, 3 + .35) -- (22 + .35, 3 - .35); \draw (22 - .35, 3 - .35) -- (22 + .35, 3 + .35); \draw (22 - .35, 1 + .35) -- (22 + .35, 1 - .35); \draw (22 - .35, 1 - .35) -- (22 + .35, 1 + .35); \end{tikzpicture} \]

though is performed more efficiently.

  • If qureg is a state-vector, the output amplitudes are the discrete Fourier transform (DFT) of the input amplitudes, in the exact ordering. This is true even if qureg is unnormalised.
    Precisely,

    \[ \text{QFT} \, \left( \sum\limits_{x=0}^{2^N-1} \alpha_x |x\rangle \right) = \frac{1}{\sqrt{2^N}} \sum\limits_{x=0}^{2^N-1} \left( \sum\limits_{y=0}^{2^N-1} e^{2 \pi \, i \, x \, y / 2^N} \; \alpha_y \right) |x\rangle \]

  • If qureg is a density matrix $\rho$, it will be changed under the unitary action of the QFT. This can be imagined as each mixed state-vector undergoing the DFT on its amplitudes. This is true even if qureg is unnormalised.

    \[ \rho \; \rightarrow \; \text{QFT} \; \rho \; \text{QFT}^{\dagger} \]

This function merges contiguous controlled-phase gates into single invocations of applyNamedPhaseFunc(), and hence is significantly faster than performing the QFT circuit directly.

Furthermore, in distributed mode, this function requires only $\log_2(\text{\#nodes})$ rounds of pair-wise communication, and hence is exponentially faster than directly performing the DFT on the amplitudes of qureg.

See also
  • applyQFT() to apply the QFT to a sub-register of qureg.
Parameters
[in,out]qurega state-vector or density matrix to modify
Author
Tyson Jones

Definition at line 876 of file QuEST.c.

876  {
877 
878  qasm_recordComment(qureg, "Beginning of QFT circuit");
879 
880  int qubits[100];
881  for (int i=0; i<qureg.numQubitsRepresented; i++)
882  qubits[i] = i;
883  agnostic_applyQFT(qureg, qubits, qureg.numQubitsRepresented);
884 
885  qasm_recordComment(qureg, "End of QFT circuit");
886 }

References agnostic_applyQFT(), Qureg::numQubitsRepresented, and qasm_recordComment().

Referenced by TEST_CASE().

◆ applyMatrix2()

void applyMatrix2 ( Qureg  qureg,
int  targetQubit,
ComplexMatrix2  u 
)

Apply a general 2-by-2 matrix, which may be non-unitary.

The matrix is left-multiplied onto the state, for both state-vectors and density matrices.

Note this differs from the action of unitary() on a density matrix.

This function may leave qureg is an unnormalised state.

See also


Parameters
[in,out]quregobject representing the set of all qubits
[in]targetQubitqubit to operate u upon
[in]umatrix to apply
Exceptions
invalidQuESTInputError()
  • if targetQubit is outside [0, qureg.numQubitsRepresented)
Author
Tyson Jones

Definition at line 1084 of file QuEST.c.

1084  {
1085  validateTarget(qureg, targetQubit, __func__);
1086 
1087  // actually just left-multiplies any complex matrix
1088  statevec_unitary(qureg, targetQubit, u);
1089 
1090  qasm_recordComment(qureg, "Here, an undisclosed 2-by-2 matrix (possibly non-unitary) was multiplied onto qubit %d", targetQubit);
1091 }

References qasm_recordComment(), statevec_unitary(), and validateTarget().

Referenced by TEST_CASE().

◆ applyMatrix4()

void applyMatrix4 ( Qureg  qureg,
int  targetQubit1,
int  targetQubit2,
ComplexMatrix4  u 
)

Apply a general 4-by-4 matrix, which may be non-unitary.

The matrix is left-multiplied onto the state, for both state-vectors and density matrices.

Note this differs from the action of twoQubitUnitary() on a density matrix.

targetQubit1 is treated as the least significant qubit in u, such that a row in u is dotted with the vector $ |\text{targetQubit2} \;\; \text{targetQubit1}\rangle : \{ |00\rangle, |01\rangle, |10\rangle, |11\rangle \} $

For example,

applyMatrix4(qureg, a, b, u);

will invoke multiplication

\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} \\ u_{10} & u_{11} & u_{12} & u_{13} \\ u_{20} & u_{21} & u_{22} & u_{23} \\ u_{30} & u_{31} & u_{32} & u_{33} \end{pmatrix} \begin{pmatrix} |ba\rangle = |00\rangle \\ |ba\rangle = |01\rangle \\ |ba\rangle = |10\rangle \\ |ba\rangle = |11\rangle \end{pmatrix} \]

This function may leave qureg is an unnormalised state.

Note that in distributed mode, this routine requires that each node contains at least 4 amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q/4 nodes.

See also


Parameters
[in,out]quregobject representing the set of all qubits
[in]targetQubit1first qubit to operate on, treated as least significant in u
[in]targetQubit2second qubit to operate on, treated as most significant in u
[in]umatrix to apply
Exceptions
invalidQuESTInputError()
  • if targetQubit1 or targetQubit2 are outside [0, qureg.numQubitsRepresented)
  • if targetQubit1 equals targetQubit2
  • if each node cannot fit 4 amplitudes in distributed mode
Author
Tyson Jones

Definition at line 1093 of file QuEST.c.

1093  {
1094  validateMultiTargets(qureg, (int []) {targetQubit1, targetQubit2}, 2, __func__);
1095  validateMultiQubitMatrixFitsInNode(qureg, 2, __func__);
1096 
1097  // actually just left-multiplies any complex matrix
1098  statevec_twoQubitUnitary(qureg, targetQubit1, targetQubit2, u);
1099 
1100  qasm_recordComment(qureg, "Here, an undisclosed 4-by-4 matrix (possibly non-unitary) was multiplied onto qubits %d and %d", targetQubit1, targetQubit2);
1101 }

References qasm_recordComment(), statevec_twoQubitUnitary(), validateMultiQubitMatrixFitsInNode(), and validateMultiTargets().

Referenced by TEST_CASE().

◆ applyMatrixN()

void applyMatrixN ( Qureg  qureg,
int *  targs,
int  numTargs,
ComplexMatrixN  u 
)

Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.

The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Note this differs from the action of multiQubitUnitary() on a density matrix.

The first target qubit in targs is treated as least significant in u. For example,

applyMatrixN(qureg, (int []) {a, b, c}, 3, u);

will invoke multiplication

\[ \begin{pmatrix} u_{00} & u_{01} & u_{02} & u_{03} & u_{04} & u_{05} & u_{06} & u_{07} \\ u_{10} & u_{11} & u_{12} & u_{13} & u_{14} & u_{15} & u_{16} & u_{17} \\ u_{20} & u_{21} & u_{22} & u_{23} & u_{24} & u_{25} & u_{26} & u_{27} \\ u_{30} & u_{31} & u_{32} & u_{33} & u_{34} & u_{35} & u_{36} & u_{37} \\ u_{40} & u_{41} & u_{42} & u_{43} & u_{44} & u_{45} & u_{46} & u_{47} \\ u_{50} & u_{51} & u_{52} & u_{53} & u_{54} & u_{55} & u_{56} & u_{57} \\ u_{60} & u_{61} & u_{62} & u_{63} & u_{64} & u_{65} & u_{66} & u_{67} \\ u_{70} & u_{71} & u_{72} & u_{73} & u_{74} & u_{75} & u_{76} & u_{77} \\ \end{pmatrix} \begin{pmatrix} |cba\rangle = |000\rangle \\ |cba\rangle = |001\rangle \\ |cba\rangle = |010\rangle \\ |cba\rangle = |011\rangle \\ |cba\rangle = |100\rangle \\ |cba\rangle = |101\rangle \\ |cba\rangle = |110\rangle \\ |cba\rangle = |111\rangle \end{pmatrix} \]

This function may leave qureg is an unnormalised state.

The passed ComplexMatrix must be a compatible size with the specified number of target qubits, otherwise an error is thrown.

Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

Note too that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes in the register. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

See also
Parameters
[in,out]quregobject representing the set of all qubits
[in]targsa list of the target qubits, ordered least significant to most in u
[in]numTargsthe number of target qubits
[in]umatrix to apply
Exceptions
invalidQuESTInputError()
  • if any index in targs is outside of [0, qureg.numQubitsRepresented)
  • if targs are not unique
  • if u is not of a compatible size with numTargs
  • if a node cannot fit the required number of target amplitudes in distributed mode
Author
Tyson Jones

Definition at line 1103 of file QuEST.c.

1103  {
1104  validateMultiTargets(qureg, targs, numTargs, __func__);
1105  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
1106 
1107  // actually just left-multiplies any complex matrix
1108  statevec_multiQubitUnitary(qureg, targs, numTargs, u);
1109 
1110  int dim = (1 << numTargs);
1111  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary) was multiplied onto %d undisclosed qubits", dim, dim, numTargs);
1112 }

References qasm_recordComment(), statevec_multiQubitUnitary(), validateMultiQubitMatrix(), and validateMultiTargets().

Referenced by TEST_CASE().

◆ applyMultiControlledMatrixN()

void applyMultiControlledMatrixN ( Qureg  qureg,
int *  ctrls,
int  numCtrls,
int *  targs,
int  numTargs,
ComplexMatrixN  u 
)

Apply a general N-by-N matrix, which may be non-unitary, with additional controlled qubits.

The matrix is left-multiplied onto the state, for both state-vectors and density matrices. Hence, this function differs from multiControlledMultiQubitUnitary() by more than just permitting a non-unitary matrix.

This function may leave qureg is an unnormalised state.

Any number of control and target qubits can be specified. This effects the many-qubit matrix

\[ \begin{pmatrix} 1 \\ & 1 \\\ & & \ddots \\ & & & u_{00} & u_{01} & \dots \\ & & & u_{10} & u_{11} & \dots \\ & & & \vdots & \vdots & \ddots \end{pmatrix} \]

on the control and target qubits.

The target qubits in targs are treated as ordered least significant to most significant in u.

The passed ComplexMatrix must be a compatible size with the specified number of target qubits, otherwise an error is thrown.

Note that in multithreaded mode, each thread will clone 2^numTargs amplitudes, and store these in the runtime stack. Using t threads, the total memory overhead of this function is t*2^numTargs. For many targets (e.g. 16 qubits), this may cause a stack-overflow / seg-fault (e.g. on a 1 MiB stack).

Note that in distributed mode, this routine requires that each node contains at least 2^numTargs amplitudes. This means an q-qubit register (state vector or density matrix) can be distributed by at most 2^q / 2^numTargs nodes.

Parameters
[in,out]quregobject representing the set of all qubits
[in]ctrlsa list of the control qubits
[in]numCtrlsthe number of control qubits
[in]targsa list of the target qubits, ordered least to most significant
[in]numTargsthe number of target qubits
[in]umatrix to apply
Exceptions
invalidQuESTInputError()
  • if any index in ctrls and targs is outside of [0, qureg.numQubitsRepresented)
  • if ctrls and targs are not unique
  • if matrix u is not a compatible size with numTargs
  • if a node cannot fit the required number of target amplitudes in distributed mode
Author
Tyson Jones

Definition at line 1114 of file QuEST.c.

1114  {
1115  validateMultiControlsMultiTargets(qureg, ctrls, numCtrls, targs, numTargs, __func__);
1116  validateMultiQubitMatrix(qureg, u, numTargs, __func__);
1117 
1118  // actually just left-multiplies any complex matrix
1119  long long int ctrlMask = getQubitBitMask(ctrls, numCtrls);
1120  statevec_multiControlledMultiQubitUnitary(qureg, ctrlMask, targs, numTargs, u);
1121 
1122  int numTot = numTargs + numCtrls;
1123  int dim = (1 << numTot );
1124  qasm_recordComment(qureg, "Here, an undisclosed %d-by-%d matrix (possibly non-unitary, and including %d controlled qubits) was multiplied onto %d undisclosed qubits", dim, dim, numCtrls, numTot);
1125 }

References getQubitBitMask(), qasm_recordComment(), statevec_multiControlledMultiQubitUnitary(), validateMultiControlsMultiTargets(), and validateMultiQubitMatrix().

Referenced by TEST_CASE().

◆ applyMultiVarPhaseFunc()

void applyMultiVarPhaseFunc ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
qreal coeffs,
qreal exponents,
int *  numTermsPerReg 
)

Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polynomial "phase function".

This is a multi-variable extension of applyPhaseFunc(), whereby multiple sub-registers inform separate variables in the exponential polynomial function, and effects a diagonal unitary operator.

  • Arguments coeffs, exponents and numTermsPerReg together specify a real exponential polynomial $f(\vec{r})$ of the form

    \[ f(r_1, \; \dots, \; r_{\text{numRegs}}) = \sum\limits_j^{\text{numRegs}} \; \sum\limits_{i}^{\text{numTermsPerReg}[j]} \; c_{i,j} \; {r_j}^{\; p_{i,j}}\,, \]

    where both coefficients $c_{i,j}$ and exponents $p_{i,j}$ can be any real number, subject to constraints described below.

    While coeffs and exponents are flat lists, they should be considered grouped into #numRegs sublists with lengths given by numTermsPerReg (which itself has length numRegs).

    For example,

    int numRegs = 3;
    qreal coeffs[] = {1, 2, 4, -3.14};
    qreal exponents[] = {2, 1, 5, 0.5 };
    int numTermsPerReg[] = {1, 2, 1 };

    constitutes the function

    \[ f(\vec{r}) = 1 \, {r_1}^2 + 2 \, {r_2} + 4 \, {r_2}^{5} - 3.14 \, {r_3}^{0.5}. \]


    This means lists coeffs and exponents should both be of length equal to the sum of numTermsPerReg.

    Unlike applyPhaseFunc(), applyMultiVarPhaseFunc() places additional constraints on the exponents in $f(\vec{r})$, due to the exponentially growing costs of overriding diverging indices. Namely:

    1. exponents must not contain a negative number, since this would result in a divergence when that register is zero, which would need to be overriden for every other register basis state. If $f(\vec{r})$ must contain a negative exponent, you should instead call applyPhaseFuncOverrides() once for each register/variable, and override the zero index for the relevant variable. This works, because

      \[ \exp( i \sum_j f_j(r_j) ) = \prod_j \exp(i f_j(r_j) ). \]

    2. exponents must not contain a fractional number if endoding = TWOS_COMPLEMENT, because such a term would produce illegal complex values at negative register indices. Similar to the problem above, each negative register index would require overriding at every index of the other registers, and hence require an exponential number of overrides. Therefore, if $f(\vec{r})$ must contain a negative exponent, you should instead call applyPhaseFuncOverrides() once for each register/variable, and override every negative index of each register in turn.

  • Lists qubits and numQubitsPerReg together describe #numRegs sub-registers of qureg, which can each contain a different number of qubits.
    Although qubits is a flat list of unique qubit indices, it should be imagined grouped into #numRegs sub-lists, of lengths given by numQubitsPerReg.

    For example,

    int qubits[] = {0,1, 3,4,5, 7}
    int numQubitsPerReg[] = {2, 3, 1};
    int numRegs = 3;

    describes three sub-registers, which are bolded below in an eight-qubit zero-state.

    \[ |r_3\rangle \; |0\rangle \; |r_2\rangle \; |0\rangle \; |r_1\rangle = |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{00}\rangle \]

    Note that the qubits need not be ordered increasing, and qubits within each sub-register are assumed ordered least to most significant in that sub-register.

    List qubits should have length equal to the sum of elements in numQubitsPerReg.

  • Each sub-register is associated with a variable $r_j$ in phase function $f(\vec{r})$.
    For a given computational basis state of qureg, the value of each variable is determined by the binary value in the corresponding sub-register, when intepreted with bitEncoding encoding.
    See bitEncoding for more information.

  • The function $f(\vec{r})$ specifies the phase change to induce upon amplitude $\alpha$ of computational basis state with the nominated sub-registers encoding values $r_1, \; \dots$.

    \[ \alpha \, |r_{\text{numRegs}}, \; \dots, \; r_2, \; r_1 \rangle \rightarrow \, \exp(i f(\vec{r}\,)) \; \alpha \, |r_{\text{numRegs}}, \; \dots, \; r_2, \; r_1 \rangle. \]

    For example, using the sub-registers in the previous example and encoding = UNSIGNED, the following states receive amplitude factors:

    \[ \begin{aligned} |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{00}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=0)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{01}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=1)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{10}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=2)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{11}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=3)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |1\rangle \; |\mathbf{00}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=0)} \\ & \;\;\;\vdots \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{111}\rangle \; |0\rangle \; |\mathbf{01}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=7,r_1=1)} \\ & \;\;\;\vdots \\ |\mathbf{1}\rangle \; |0\rangle \; |\mathbf{111}\rangle \; |0\rangle \; |\mathbf{11}\rangle & \rightarrow \, e^{i f(r_3=1,r_2=7,r_1=3)} \end{aligned} \]

  • If qureg is a density matrix $\rho$, then its elements are modified as

    \[ \alpha \, |j\rangle\langle k| \; \rightarrow \; \exp(i \, (f(\vec{r}_j) - f(\vec{r}_k)) \, ) \; \alpha \, |j\rangle\langle k|, \]

    where $f(\vec{r}_j)$ and $f(\vec{r}_k)$ are determined as above.

  • The interpreted phase function can be previewed in the QASM log, as a comment.
    For example:

    would show, for the above example,

    // Here, applyMultiVarPhaseFunc() multiplied a complex scalar of the form
    // exp(i (
    // + 1 x^2
    // + 2 y + 4 y^(-1)
    // - 3.14 z^0.5 ))
    // upon substates informed by qubits (under an unsigned binary encoding)
    // |x> = {0, 1}
    // |y> = {3, 4, 5}
    // |z> = {7}


See also
Parameters
[in,out]quregthe state-vector or density matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]coeffsthe coefficients of all terms of the exponential polynomial phase function $f(\vec{r})$
[in]exponentsthe exponents of all terms of the exponential polynomial phase function $f(\vec{r})$
[in]numTermsPerRega list of the number of coeff and exponent terms supplied for each variable/sub-register
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if any element of numTermsPerReg is < 1
  • if exponents contains a negative number
  • if exponents contains a fractional number despite encoding = TWOS_COMPLEMENT
Author
Tyson Jones

Definition at line 761 of file QuEST.c.

761  {
762  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
763  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
764  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
765 
766  int conj = 0;
767  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
768  if (qureg.isDensityMatrix) {
769  conj = 1;
770  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
771  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0, conj);
772  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
773  }
774 
775  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, NULL, NULL, 0);
776 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyMultiVarPhaseFuncOverrides()

void applyMultiVarPhaseFuncOverrides ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
qreal coeffs,
qreal exponents,
int *  numTermsPerReg,
long long int *  overrideInds,
qreal overridePhases,
int  numOverrides 
)

Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices.

See applyMultiVarPhaseFunc() first for a full description.

  • As in applyMultiVarPhaseFunc(), the arguments coeffs and exponents specify a multi-variable phase function $f(\vec{r})$, where $\vec{r}$ is determined by the sub-registers in qubits, and bitEncoding encoding for each basis state of qureg.

  • Additionally, overrideInds is a list of length numOverrides which specifies the values of $\vec{r}$ for which to explicitly set the induced phase change.
    While flat, overrideInds should be imagined grouped into sub-lists of length numRegs, which specify the full $\{r_1,\; \dots \;r_{\text{numRegs}} \} $ coordinate to override.
    Each sublist corresponds to a single element of overridePhases.
    For example,

    int numRegs = 3;
    int numOverrides = 2;
    long long int overrideInds[] = { 0,0,0, 1,2,3 };
    qreal overridePhases[] = { M_PI, - M_PI };

    denotes that any basis state of qureg with sub-register values $\{r_3,r_2,r_1\} = \{0, 0, 0\}$ (or $\{r_3,r_2,r_1\} = \{1,2,3\}$) should receive phase change $\pi$ (or $-\pi$) in lieu of $\exp(i f(r_3=0,r_2=0,r_1=0))$.

    Note that you cannot use applyMultiVarPhaseFuncOverrides() to override divergences in $f(\vec{r})$, since each diverging value $r_j$ would need to be overriden as an $\vec{r}$ coordinate for every basis state of the other registers; the number of overrides grows exponentially. Ergo, if exponents contains a negative number (diverging at $r_j=0$), or exponents contains a fractional number despite encoding = TWOS_COMPLEMENT (producing complex phases at negative indices), you must instead call applyPhaseFuncOverrides() for each variable in turn and override the diverging $r_j$ (each independently of the other registers).

  • The interpreted overrides can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyMultiVarPhaseFunc() multiplied ...
    // though with overrides
    // |x=0, y=0, z=0> -> exp(i 3.14159)
    // |x=1, y=2, z=3> -> exp(i (-3.14159))


See also
Parameters
[in,out]quregthe state-vector or density-matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]coeffsthe coefficients of all terms of the exponential polynomial phase function $f(\vec{r})$
[in]exponentsthe exponents of all terms of the exponential polynomial phase function $f(\vec{r})$
[in]numTermsPerRega list of the number of coeff and exponent terms supplied for each variable/sub-register
[in]overrideIndsa flattened list of sub-register coordinates (values of $\vec{r}$) of which to explicit set the phase change
[in]overridePhasesa list of replacement phase changes, for the corresponding $\vec{r}$ values in overrideInds
[in]numOverridesthe lengths of list overridePhases (but not necessarily of overrideInds)
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if any element of numTermsPerReg is < 1
  • if exponents contains a negative number
  • if exponents contains a fractional number despite encoding = TWOS_COMPLEMENT
  • if any value in overrideInds is not producible by its corresponding sub-register under the given encoding (e.g. 2 unsigned qubits cannot represent index 9)
  • if numOverrides < 0
Author
Tyson Jones

Definition at line 778 of file QuEST.c.

778  {
779  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
780  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
781  validateMultiVarPhaseFuncTerms(numQubitsPerReg, numRegs, encoding, exponents, numTermsPerReg, __func__);
782  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
783 
784  int conj = 0;
785  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
786  if (qureg.isDensityMatrix) {
787  conj = 1;
788  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
789  statevec_applyMultiVarPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides, conj);
790  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
791  }
792 
793  qasm_recordMultiVarPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, coeffs, exponents, numTermsPerReg, overrideInds, overridePhases, numOverrides);
794 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordMultiVarPhaseFunc(), shiftSubregIndices(), statevec_applyMultiVarPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validateMultiVarPhaseFuncTerms(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyNamedPhaseFunc()

void applyNamedPhaseFunc ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
enum phaseFunc  functionNameCode 
)

Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-variable) phase function.

This effects a diagonal unitary operator, with a phase function $f(\vec{r})$ which may not be simply expressible as an exponential polynomial in functions applyPhaseFunc() and applyMultiVarPhaseFunc().

Arguments qubits and numQubitsPerReg encode sub-registers of qureg in the same manner as in applyMultiVarPhaseFunc():

  • Lists qubits and numQubitsPerReg together describe #numRegs sub-registers of qureg, which can each contain a different number of qubits.
    Although qubits is a flat list of unique qubit indices, it should be imagined grouped into #numRegs sub-lists, of lengths given by numQubitsPerReg.

    For example,

    int qubits[] = {0,1, 3,4,5, 7}
    int numQubitsPerReg[] = {2, 3, 1};
    int numRegs = 3;

    describes three sub-registers, which are bolded below in an eight-qubit zero-state.

    \[ |r_3\rangle \; |0\rangle \; |r_2\rangle \; |0\rangle \; |r_1\rangle = |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{00}\rangle \]

    Note that the qubits need not be ordered increasing, and qubits within each sub-register are assumed ordered least to most significant in that sub-register.

    List qubits should have length equal to the sum of elements in numQubitsPerReg.

  • Each sub-register is associated with a variable $r_j$ in phase function $f(\vec{r})$.
    For a given computational basis state of qureg, the value of each variable is determined by the binary value in the corresponding sub-register, when intepreted with bitEncoding encoding.
    See bitEncoding for more information.

  • Argument functionNameCode determines the phase function $f(\vec{r})$.
    For example,

    int numRegs = 3;
    enum phaseFunc functionNameCode = NORM;

    describes phase function

    \[ f(\vec{r}) = \sqrt{ {r_1}^2 + {r_2}^2 + {r_3} ^2 }. \]

    See phaseFunc for a list and description of all named phase functions.
    Some phase functions, like SCALED_NORM, require passing additional parameters, through the function applyParamNamedPhaseFunc().

    If the phase function $f(\vec{r})$ diverges at one or more $\vec{r}$ values, you should instead use applyNamedPhaseFuncOverrides() and specify explicit phase changes for these coordinates. Otherwise, the corresponding amplitudes of qureg will become indeterminate (like NaN).

  • The function $f(\vec{r})$ specifies the phase change to induce upon amplitude $\alpha$ of computational basis state with the nominated sub-registers encoding values $r_1, \; \dots$.

    \[ \alpha \, |r_{\text{numRegs}}, \; \dots, \; r_2, \; r_1 \rangle \rightarrow \, \exp(i f(\vec{r}\,)) \; \alpha \, |r_{\text{numRegs}}, \; \dots, \; r_2, \; r_1 \rangle. \]

    For example, using the sub-registers in the above example and encoding = UNSIGNED, the following states receive amplitude factors:

    \[ \begin{aligned} |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{00}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=0)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{01}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=1)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{10}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=2)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |0\rangle \; |\mathbf{11}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=3)} \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{000}\rangle \; |1\rangle \; |\mathbf{00}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=0,r_1=0)} \\ & \;\;\;\vdots \\ |\mathbf{0}\rangle \; |0\rangle \; |\mathbf{111}\rangle \; |0\rangle \; |\mathbf{01}\rangle & \rightarrow \, e^{i f(r_3=0,r_2=7,r_1=1)} \\ & \;\;\;\vdots \\ |\mathbf{1}\rangle \; |0\rangle \; |\mathbf{111}\rangle \; |0\rangle \; |\mathbf{11}\rangle & \rightarrow \, e^{i f(r_3=1,r_2=7,r_1=3)} \end{aligned} \]


  • If qureg is a density matrix, its elements are modified to

    \[ \alpha \, |j\rangle\langle k| \; \rightarrow \; \exp(i (f(\vec{r}_j) \, - \, f(\vec{r}_k))) \; \alpha \, |j\rangle\langle k| \]

    where $f(\vec{r}_j)$ and $f(\vec{r}_k)$ are determined as above. This is equivalent to modification

    \[ \rho \; \rightarrow \; \hat{D} \, \rho \, \hat{D}^\dagger \]

    where $\hat{D}$ is the diagonal unitary

    \[ \hat{D} = \text{diag}\, \{ \; e^{i f(\vec{r_0})}, \; e^{i f(\vec{r_1})}, \; \dots \; \}. \]


  • The interpreted phase function can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyNamedPhaseFunc() multiplied a complex scalar of form
    // exp(i 1 / sqrt((x-y)^2 + (z-t)^2))


See also
Parameters
[in,out]quregthe state-vector or density-matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]functionNameCodethe phaseFunc $f(\vec{r})$
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if functionNameCode is not a valid phaseFunc
  • if functionNameCode requires additional parameters, which must instead be passed with applyParamNamedPhaseFunc()
Author
Tyson Jones

Definition at line 796 of file QuEST.c.

796  {
797  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
798  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
799  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
800 
801  int conj = 0;
802  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
803  if (qureg.isDensityMatrix) {
804  conj = 1;
805  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
806  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0, conj);
807  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
808  }
809 
810  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, NULL, NULL, 0);
811 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyNamedPhaseFuncOverrides()

void applyNamedPhaseFuncOverrides ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
enum phaseFunc  functionNameCode,
long long int *  overrideInds,
qreal overridePhases,
int  numOverrides 
)

Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-variable) phase function, and an explicit set of 'overriding' values at specific state indices.

See applyNamedPhaseFunc() first for a full description.

  • As in applyNamedPhaseFunc(), functionNameCode specifies a multi-variable phase function $f(\vec{r})$, where $\vec{r}$ is determined by the sub-registers in qubits, and bitEncoding encoding for each basis state of qureg.

  • Additionally, overrideInds is a list of length numOverrides which specifies the values of $\vec{r}$ for which to explicitly set the induced phase change.
    While flat, overrideInds should be imagined grouped into sub-lists of length numRegs, which specify the full $\{r_1,\; \dots \;r_{\text{numRegs}} \} $ coordinate to override.
    Each sublist corresponds to a single element of overridePhases.
    For example,

    int numRegs = 3;
    int numOverrides = 2;
    long long int overrideInds[] = { 0,0,0, 1,2,3 };
    qreal overridePhases[] = { M_PI, - M_PI };

    denotes that any basis state of qureg with sub-register values $\{r_3,r_2,r_1\} = \{0, 0, 0\}$ (or $\{r_3,r_2,r_1\} = \{1,2,3\}$) should receive phase change $\pi$ (or $-\pi$) in lieu of $\exp(i f(r_3=0,r_2=0,r_1=0))$.

  • The interpreted overrides can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyNamedPhaseFunc() multiplied ...
    // though with overrides
    // |x=0, y=0, z=0> -> exp(i 3.14159)
    // |x=1, y=2, z=3> -> exp(i (-3.14159))


See also
Parameters
[in,out]quregthe state-vector pr density-matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]functionNameCodethe phaseFunc $f(\vec{r})$
[in]overrideIndsa flattened list of sub-register coordinates (values of $\vec{r}$) of which to explicit set the phase change
[in]overridePhasesa list of replacement phase changes, for the corresponding $\vec{r}$ values in overrideInds
[in]numOverridesthe lengths of list overridePhases (but not necessarily of overrideInds)
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if functionNameCode is not a valid phaseFunc
  • if functionNameCode requires additional parameters, which must instead be passed with applyParamNamedPhaseFunc()
  • if any value in overrideInds is not producible by its corresponding sub-register under the given encoding (e.g. 2 unsigned qubits cannot represent index 9)
  • if numOverrides < 0
Author
Tyson Jones

Definition at line 813 of file QuEST.c.

813  {
814  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
815  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
816  validatePhaseFuncName(functionNameCode, numRegs, 0, __func__);
817  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
818 
819  int conj = 0;
820  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
821  if (qureg.isDensityMatrix) {
822  conj = 1;
823  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
824  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides, conj);
825  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
826  }
827 
828  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, NULL, 0, overrideInds, overridePhases, numOverrides);
829 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyParamNamedPhaseFunc()

void applyParamNamedPhaseFunc ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
enum phaseFunc  functionNameCode,
qreal params,
int  numParams 
)

Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potentially multi-variable) phase function.

See applyNamedPhaseFunc() for full documentation.
This function merely accepts additional phaseFunc names which accept one (or more) parameters.

  • Argument functionNameCode, which determines the phase function $f(\vec{r}, \vec{\theta})$, can include parameterised phaseFunc names like SCALED_NORM, which require additional parameters $\vec{\theta}$ passed via list params.
    For example,

    enum phaseFunc functionNameCode = SCALED_PRODUCT;
    qreal params[] = {0.5};
    int numParams = 1;
    applyParamNamedPhaseFunc(..., functionNameCode, params, numParams);

    invokes phase function

    \[ f(\vec{r}, \theta)|_{\theta=0.5} \; = \; 0.5 \prod_j^{\text{numRegs}} \; r_j\,. \]

    See phaseFunc for all named phased functions.

  • Functions with divergences, like INVERSE_NORM and SCALED_INVERSE_DISTANCE, must accompany an extra parameter to specify an overriding phase at the divergence. For example,

    enum phaseFunc functionNameCode = SCALED_INVERSE_NORM;
    qreal params[] = {0.5, M_PI};
    int numParams = 2;
    applyParamNamedPhaseFunc(..., functionNameCode, params, numParams);

    invokes phase function

    \[ f(\vec{r}, \theta)|_{\theta=0.5} \; = \; \begin{cases} \pi & \;\;\; \vec{r}=\vec{0} \\ \displaystyle 0.5 \left[ \sum_j^{\text{numRegs}} {r_j}^2 \right]^{-1/2} & \;\;\;\text{otherwise} \end{cases}. \]

    Notice the order of the parameters matches the order of the words in the phaseFunc.

    Functions SCALED_INVERSE_SHIFTED_NORM and SCALED_INVERSE_SHIFTED_DISTANCE, which can have denominators arbitrarily close to zero, will invoke the divergence parameter whenever the denominator is smaller than (or equal to) machine precision REAL_EPS.

  • Functions allowing the shifting of sub-register values, which are SCALED_INVERSE_SHIFTED_NORM and SCALED_INVERSE_SHIFTED_DISTANCE, need these shift values to be passed in the params argument after the scaling and divergence override parameters listed above. The function SCALED_INVERSE_SHIFTED_NORM needs as many extra parameters, as there are sub-registers; SCALED_INVERSE_SHIFTED_DISTANCE needs one extra parameter for each pair of sub-registers. For example,

    enum phaseFunc functionNameCode = SCALED_INVERSE_SHIFTED_NORM;
    int qubits[] = {0,1,2,3, 4,5,6,7};
    int qubitsPerReg[] = {4, 4};
    qreal params[] = {0.5, M_PI, 0.8, -0.3};
    int numParams = 4;
    applyParamNamedPhaseFunc(..., qubits, qubitsPerReg, 2, ..., functionNameCode, params, numParams);

    invokes phase function

    \[ f(\vec{r}) \; = \; \begin{cases} \pi & \;\;\; \vec{r}=\vec{0} \\ \displaystyle 0.5 \left[(r_1-0.8)^2 + (r_2+0.3)^2\right]^{-1/2} & \;\;\;\text{otherwise} \end{cases}. \]

    and

    int qubits[] = {0,1, 2,3, 4,5, 6,7};
    int qubitsPerReg[] = {2, 2, 2, 2};
    qreal params[] = {0.5, M_PI, 0.8, -0.3};
    int numParams = 4;
    applyParamNamedPhaseFunc(..., qubits, qubitsPerReg, 4, ..., functionNameCode, params, numParams);

    invokes phase function

    \[ f(\vec{r}) \; = \; \begin{cases} \pi & \;\;\; \vec{r}=\vec{0} \\ \displaystyle 0.5 \left[(r_1-r_2-0.8)^2 + (r_3-r_4+0.3)^2\right]^{-1/2} & \;\;\;\text{otherwise} \end{cases}. \]

You can further override $f(\vec{r}, \vec{\theta})$ at one or more $\vec{r}$ values via applyParamNamedPhaseFuncOverrides().


See also
Parameters
[in,out]quregthe state-vector or density-matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]functionNameCodethe phaseFunc $f(\vec{r}, \vec{\theta})$
[in]paramsa list of any additional parameters needed by the phaseFunc functionNameCode
[in]numParamsthe length of list params
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if functionNameCode is not a valid phaseFunc
  • if numParams is incompatible with functionNameCode (for example, no parameters were passed to SCALED_PRODUCT)
Author
Tyson Jones
Richard Meister (shifted functions)

Definition at line 831 of file QuEST.c.

831  {
832  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
833  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
834  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
835 
836  int conj = 0;
837  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
838  if (qureg.isDensityMatrix) {
839  conj = 1;
840  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
841  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0, conj);
842  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
843  }
844 
845  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, NULL, NULL, 0);
846 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyParamNamedPhaseFuncOverrides()

void applyParamNamedPhaseFuncOverrides ( Qureg  qureg,
int *  qubits,
int *  numQubitsPerReg,
int  numRegs,
enum bitEncoding  encoding,
enum phaseFunc  functionNameCode,
qreal params,
int  numParams,
long long int *  overrideInds,
qreal overridePhases,
int  numOverrides 
)

Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potentially multi-variable) phase function, and an explicit set of 'overriding' values at specific state indices.

See applyParamNamedPhaseFunc() and applyNamedPhaseFunc() first for a full description.

  • As in applyParamNamedPhaseFunc(), functionNameCode specifies a parameterised multi-variable phase function $f(\vec{r}, \vec{\theta})$, where $\vec{\theta}$ is passed in list params, and $\vec{r}$ is determined both by the sub-registers in qubits, and bitEncoding encoding for each basis state of qureg.

  • Additionally, overrideInds is a list of length numOverrides which specifies the values of $\vec{r}$ for which to explicitly set the induced phase change.
    While flat, overrideInds should be imagined grouped into sub-lists of length numRegs, which specify the full $\{r_1,\; \dots \;r_{\text{numRegs}} \} $ coordinate to override.
    Each sublist corresponds to a single element of overridePhases.
    For example,

    int numRegs = 3;
    int numOverrides = 2;
    long long int overrideInds[] = { 0,0,0, 1,2,3 };
    qreal overridePhases[] = { M_PI, - M_PI };

    denotes that any basis state of qureg with sub-register values $\{r_3,r_2,r_1\} = \{0, 0, 0\}$ (or $\{r_3,r_2,r_1\} = \{1,2,3\}$) should receive phase change $\pi$ (or $-\pi$) in lieu of $\exp(i f(r_3=0,r_2=0,r_1=0, \vec{\theta}))$.

  • The interpreted overrides can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyParamNamedPhaseFunc() multiplied ...
    // though with overrides
    // |x=0, y=0, z=0> -> exp(i 3.14159)
    // |x=1, y=2, z=3> -> exp(i (-3.14159))


See also
Parameters
[in,out]quregthe state-vector or density-matrix to be modified
[in]qubitsa list of all the qubit indices contained in each sub-register
[in]numQubitsPerRega list of the lengths of each sub-list in qubits
[in]numRegsthe number of sub-registers, which is the length of both numQubitsPerReg and numTermsPerReg
[in]encodingthe bitEncoding under which to infer the binary value $r_j$ from the bits of a sub-register
[in]functionNameCodethe phaseFunc $f(\vec{r}, \vec{\theta})$
[in]paramsa list of any additional parameters $\vec{\theta}$ needed by the phaseFunc functionNameCode
[in]numParamsthe length of list params
[in]overrideIndsa flattened list of sub-register coordinates (values of $\vec{r}$) of which to explicit set the phase change
[in]overridePhasesa list of replacement phase changes, for the corresponding $\vec{r}$ values in overrideInds
[in]numOverridesthe lengths of list overridePhases (but not necessarily of overrideInds)
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique (including if sub-registers overlap)
  • if numRegs <= 0 or numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if encoding is not a valid bitEncoding
  • if the size of any sub-register is incompatible with encoding (e.g. contains fewer than two qubits in encoding = TWOS_COMPLEMENT)
  • if functionNameCode is not a valid phaseFunc
  • if numParams is incompatible with functionNameCode (for example, no parameters were passed to SCALED_PRODUCT)
  • if any value in overrideInds is not producible by its corresponding sub-register under the given encoding (e.g. 2 unsigned qubits cannot represent index 9)
  • if numOverrides < 0
Author
Tyson Jones

Definition at line 848 of file QuEST.c.

848  {
849  validateQubitSubregs(qureg, qubits, numQubitsPerReg, numRegs, __func__);
850  validateMultiRegBitEncoding(numQubitsPerReg, numRegs, encoding, __func__);
851  validatePhaseFuncName(functionNameCode, numRegs, numParams, __func__);
852  validateMultiVarPhaseFuncOverrides(numQubitsPerReg, numRegs, encoding, overrideInds, numOverrides, __func__);
853 
854  int conj = 0;
855  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
856  if (qureg.isDensityMatrix) {
857  conj = 1;
858  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, qureg.numQubitsRepresented);
859  statevec_applyParamNamedPhaseFuncOverrides(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides, conj);
860  shiftSubregIndices(qubits, numQubitsPerReg, numRegs, - qureg.numQubitsRepresented);
861  }
862 
863  qasm_recordNamedPhaseFunc(qureg, qubits, numQubitsPerReg, numRegs, encoding, functionNameCode, params, numParams, overrideInds, overridePhases, numOverrides);
864 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordNamedPhaseFunc(), shiftSubregIndices(), statevec_applyParamNamedPhaseFuncOverrides(), validateMultiRegBitEncoding(), validateMultiVarPhaseFuncOverrides(), validatePhaseFuncName(), and validateQubitSubregs().

Referenced by TEST_CASE().

◆ applyPauliHamil()

void applyPauliHamil ( Qureg  inQureg,
PauliHamil  hamil,
Qureg  outQureg 
)

Modifies outQureg to be the result of applying PauliHamil (a Hermitian but not necessarily unitary operator) to inQureg.

Note that afterward, outQureg may no longer be normalised and ergo not a state-vector or density matrix. Users must therefore be careful passing outQureg to other QuEST functions which assume normalisation in order to function correctly.

This is merely an encapsulation of applyPauliSum(), which can refer to for elaborated doc.

Letting hamil be expressed as $ \alpha = \sum_i c_i \otimes_j^{N} \hat{\sigma}_{i,j} $ (where $ c_i \in $ hamil.termCoeffs and $ N = $ hamil.numQubits), this function effects $ \alpha | \psi \rangle $ on state-vector $ |\psi\rangle $ and $\alpha \rho$ (left matrix multiplication) on density matrix $ \rho $.

In theory, inQureg is unchanged though its state is temporarily modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors. The initial state in outQureg is not used.

inQureg and outQureg must both be state-vectors, or both density matrices, of equal dimensions to hamil. inQureg cannot be outQureg.

This function works by applying each Pauli product in hamil to inQureg in turn, and adding the resulting state (weighted by a coefficient in termCoeffs) to the initially-blanked outQureg. Ergo it should scale with the total number of Pauli operators specified (excluding identities), and the qureg dimension.

See also
Parameters
[in]inQuregthe register containing the state which outQureg will be set to, under the action of hamil. inQureg should be unchanged, though may vary slightly due to numerical error.
[in]hamila weighted sum of products of pauli operators
[out]outQuregthe qureg to modify to be the result of applyling hamil to the state in inQureg
Exceptions
invalidQuESTInputError()
  • if any code in hamil.pauliCodes is not a valid Pauli code
  • if numSumTerms <= 0
  • if inQureg is not of the same type and dimensions as outQureg and hamil
Author
Tyson Jones

Definition at line 1059 of file QuEST.c.

1059  {
1060  validateMatchingQuregTypes(inQureg, outQureg, __func__);
1061  validateMatchingQuregDims(inQureg, outQureg, __func__);
1062  validatePauliHamil(hamil, __func__);
1063  validateMatchingQuregPauliHamilDims(inQureg, hamil, __func__);
1064 
1065  statevec_applyPauliSum(inQureg, hamil.pauliCodes, hamil.termCoeffs, hamil.numSumTerms, outQureg);
1066 
1067  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliHamil).");
1068 }

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

Referenced by TEST_CASE().

◆ applyPauliSum()

void applyPauliSum ( Qureg  inQureg,
enum pauliOpType allPauliCodes,
qreal termCoeffs,
int  numSumTerms,
Qureg  outQureg 
)

Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but not necessarily unitary operator) to inQureg.

Note that afterward, outQureg may no longer be normalised and ergo not a state-vector or density matrix. Users must therefore be careful passing outQureg to other QuEST functions which assume normalisation in order to function correctly.

Letting $ \alpha = \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 effects $ \alpha | \psi \rangle $ on state-vector $ |\psi\rangle $ and $\alpha \rho$ (left matrix multiplication) on density matrix $ \rho $.

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};
applyPauliSum(inQureg, paulis, coeffs, 2, outQureg);

will apply Hermitian operation $ (1.5 X I I - 3.6 X Y Z) $ (where in this notation, the left-most operator applies to the least-significant qubit, i.e. that with index 0).

In theory, inQureg is unchanged though its state is temporarily modified and is reverted by re-applying Paulis (XX=YY=ZZ=I), so may see a change by small numerical errors. The initial state in outQureg is not used.

inQureg and outQureg must both be state-vectors, or both density matrices, of equal dimensions. inQureg cannot be outQureg.

This function works by applying each Pauli product to inQureg in turn, and adding the resulting state (weighted by a coefficient in termCoeffs) to the initially-blanked outQureg. Ergo it should scale with the total number of Pauli operators specified (excluding identities), and the qureg dimension.

See also
Parameters
[in]inQuregthe register containing the state which outQureg will be set to, under the action of the Hermitiain operator specified by the Pauli codes. inQureg should be unchanged, though may vary slightly due to numerical error.
[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
[out]outQuregthe qureg to modify to be the result of applyling the weighted Pauli sum operator to the state in inQureg
Exceptions
invalidQuESTInputError()
  • if any code in allPauliCodes is not in {0,1,2,3}
  • if numSumTerms <= 0
  • if inQureg is not of the same type and dimensions as outQureg
Author
Tyson Jones

Definition at line 1048 of file QuEST.c.

1048  {
1049  validateMatchingQuregTypes(inQureg, outQureg, __func__);
1050  validateMatchingQuregDims(inQureg, outQureg, __func__);
1051  validateNumPauliSumTerms(numSumTerms, __func__);
1052  validatePauliCodes(allPauliCodes, numSumTerms*inQureg.numQubitsRepresented, __func__);
1053 
1054  statevec_applyPauliSum(inQureg, allPauliCodes, termCoeffs, numSumTerms, outQureg);
1055 
1056  qasm_recordComment(outQureg, "Here, the register was modified to an undisclosed and possibly unphysical state (applyPauliSum).");
1057 }

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

Referenced by TEST_CASE().

◆ applyPhaseFunc()

void applyPhaseFunc ( Qureg  qureg,
int *  qubits,
int  numQubits,
enum bitEncoding  encoding,
qreal coeffs,
qreal exponents,
int  numTerms 
)

Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function".

This effects a diagonal unitary of unit complex scalars, targeting the nominated qubits.

  • Arguments coeffs and exponents together specify a real exponential polynomial $f(r)$ with numTerms terms, of the form

    \[ f(r) = \sum\limits_{i}^{\text{numTerms}} \text{coeffs}[i] \; r^{\, \text{exponents}[i]}\,, \]

    where both coeffs and exponents can be negative, positive and fractional. For example,

    qreal coeffs[] = {1, -3.14};
    qreal exponents[] = {2, -5.5};
    int numTerms = 2;

    constitutes the function

    \[ f(r) = 1 \, r^2 - 3.14 \, r^{-5.5}. \]

    Note you cannot use fractional exponents with encoding = TWOS_COMPLEMENT, since the negative indices would generate (illegal) complex phases, and must be overriden with applyPhaseFuncOverrides().

    If your function $f(r)$ diverges at one or more $r$ values, you must instead use applyPhaseFuncOverrides() and specify explicit phase changes for these values. Otherwise, the corresponding amplitudes of the state-vector will become indeterminate (like NaN). Note that use of any negative exponent will result in divergences at $r=0$.

  • The function $f(r)$ specifies the phase change to induce upon amplitude $\alpha$ of computational basis state with index $r$, such that

    \[ \alpha \, |r\rangle \rightarrow \, \exp(i f(r)) \; \alpha \, |r\rangle. \]

    The index $r$ associated with each computational basis state is determined by the binary value of the specified qubits (ordered least to most significant), interpreted under the given bitEncoding encoding.

    For example, under encoding = UNSIGNED and qubits = {0,1},

    \[ \begin{aligned} |0\mathbf{00}\rangle & \rightarrow \, e^{i f(0)}\,|0\mathbf{00}\rangle \\ |0\mathbf{01}\rangle & \rightarrow \, e^{i f(1)}\,|0\mathbf{01}\rangle \\ |0\mathbf{10}\rangle & \rightarrow \, e^{i f(2)}\,|0\mathbf{10}\rangle \\ |0\mathbf{11}\rangle & \rightarrow \, e^{i f(3)}\,|0\mathbf{11}\rangle \\ |1\mathbf{00}\rangle & \rightarrow \, e^{i f(0)}\,|1\mathbf{00}\rangle \\ |1\mathbf{01}\rangle & \rightarrow \, e^{i f(1)}\,|1\mathbf{01}\rangle \\ |1\mathbf{10}\rangle & \rightarrow \, e^{i f(2)}\,|1\mathbf{10}\rangle \\ |1\mathbf{11}\rangle & \rightarrow \, e^{i f(3)}\,|1\mathbf{11}\rangle \end{aligned} \]

  • If qureg is a density matrix $\rho$, this function modifies qureg to

    \[ \rho \rightarrow \hat{D} \, \rho \, \hat{D}^\dagger \]

    where $\hat{D}$ is the diagonal unitary operator

    \[ \hat{D} = \text{diag} \, \{ \; e^{i f(r_0)}, \; e^{i f(r_1)}, \; \dots \; \}. \]

    This means element $\rho_{jk}$ is modified to

    \[ \alpha \, |j\rangle\langle k| \; \rightarrow \; e^{i (f(r_j) - f(r_k))} \; \alpha \, |j\rangle\langle k| \]


  • The interpreted phase function can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyPhaseFunc() multiplied a complex scalar of the form
    // exp(i (1 x^3))
    // upon every substate |x>, informed by qubits (under an unsigned binary encoding)
    // {4, 1, 2, 0}

This function may become numerically imprecise for quickly growing phase functions which admit very large phases, for example of 10^10.

See also
Parameters
[in,out]quregthe state-vector or density matrix to be modified
[in]qubitsa list of the indices of the qubits which will inform $r$ for each amplitude in qureg
[in]numQubitsthe length of list qubits
[in]encodingthe bitEncoding under which to infer the binary value $r$ from the bits of qubits in each basis state of qureg
[in]coeffsthe coefficients of the exponential polynomial phase function $f(r)$
[in]exponentsthe exponents of the exponential polynomial phase function $f(r)$
[in]numTermsthe length of list coeffs, which must be the same as that of exponents
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique
  • if numQubits < 0 or numQubits >= qureg.numQubitsRepresented
  • if encoding is not a valid bitEncoding
  • if encoding is not compatible with numQubits (e.g. TWOS_COMPLEMENT with only 1 qubit)
  • if exponents contains a fractional number despite encoding = TWOS_COMPLEMENT (you must instead use applyPhaseFuncOverrides() and override all negative indices)
  • if exponents contains a negative power (you must instead use applyPhaseFuncOverrides() and override the zero index)
  • if numTerms <= 0
Author
Tyson Jones

Definition at line 726 of file QuEST.c.

726  {
727  validateMultiQubits(qureg, qubits, numQubits, __func__);
728  validateBitEncoding(numQubits, encoding, __func__);
729  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, NULL, 0, __func__);
730 
731  int conj = 0;
732  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
733  if (qureg.isDensityMatrix) {
734  conj = 1;
735  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
736  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0, conj);
737  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
738  }
739 
740  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, NULL, NULL, 0);
741 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), and validatePhaseFuncTerms().

Referenced by TEST_CASE().

◆ applyPhaseFuncOverrides()

void applyPhaseFuncOverrides ( Qureg  qureg,
int *  qubits,
int  numQubits,
enum bitEncoding  encoding,
qreal coeffs,
qreal exponents,
int  numTerms,
long long int *  overrideInds,
qreal overridePhases,
int  numOverrides 
)

Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial "phase function", and an explicit set of 'overriding' values at specific state indices.

See applyPhaseFunc() first for a full description.

  • As in applyPhaseFunc(), the arguments coeffs and exponents specify a phase function $f(r)$, where $r$ is determined by qubits and encoding for each basis state of qureg.

  • Additionally, overrideInds is a list of length numOverrides which specifies the values of $r$ for which to explicitly set the induced phase change.
    The overriding phase changes are specified in the corresponding elements of overridePhases.

    For example,

    int qubits[] = {0,1};
    enum bitEncoding encoding = UNSIGNED;
    long long int overrideInds[] = {2};
    qreal overridePhases[] = {M_PI};

    would effect the same diagonal unitary of applyPhaseFunc(), except that all instance of $f(r=2)$ are overriden with phase $\pi$.
    I.e.

    \[ \begin{aligned} |0\mathbf{00}\rangle & \rightarrow \, e^{i f(0)}\,|0\mathbf{00}\rangle \\ |0\mathbf{01}\rangle & \rightarrow \, e^{i f(1)}\,|0\mathbf{01}\rangle \\ |0\mathbf{10}\rangle & \rightarrow \, e^{i \pi} \hspace{12pt} |0\mathbf{10}\rangle \\ |0\mathbf{11}\rangle & \rightarrow \, e^{i f(3)}\,|0\mathbf{11}\rangle \\ |1\mathbf{00}\rangle & \rightarrow \, e^{i f(0)}\,|1\mathbf{00}\rangle \\ |1\mathbf{01}\rangle & \rightarrow \, e^{i f(1)}\,|1\mathbf{01}\rangle \\ |1\mathbf{10}\rangle & \rightarrow \, e^{i \pi} \hspace{12pt} |1\mathbf{10}\rangle \\ |1\mathbf{11}\rangle & \rightarrow \, e^{i f(3)}\,|1\mathbf{11}\rangle \end{aligned} \]

    Note that if encoding = TWOS_COMPLEMENT, and $f(r)$ features a fractional exponent, then every negative phase index must be overriden. This is checked and enforced by QuEST's validation, unless there are more than 16 targeted qubits, in which case valid input is assumed (due to an otherwise prohibitive performance overhead).

    Overriding phases are checked at each computational basis state of qureg before evaluating the phase function $f(r)$, and hence are useful for avoiding singularities or errors at diverging values of $r$.

  • If qureg is a density matrix $\rho$, the overrides determine the diagonal unitary matrix $\hat{D}$, which is then applied to qureg as

    \[ \rho \; \rightarrow \; \hat{D} \, \rho \hat{D}^\dagger. \]

    This means that with overrides $f(r_j) \rightarrow \theta$ and $f(r_k) \rightarrow \phi$, element $\rho_{jk}$ is modified to

    \[ \alpha \, |j\rangle\langle k| \; \rightarrow \; \exp(\, i \, (\theta - \phi) \, ) \; \alpha \, |j\rangle\langle k|. \]


  • The interpreted phase function and list of overrides can be previewed in the QASM log, as a comment.
    For example:

    may show

    // Here, applyPhaseFunc() multiplied a complex scalar of the form
    // exp(i (0.3 x^(-5) + 4 x^1 + 1 x^3))
    // upon every substate |x>, informed by qubits (under a two's complement binary encoding)
    // {4, 1, 2, 0}
    // though with overrides
    // |0> -> exp(i 3.14159)
    // |1> -> exp(i (-3.14159))
    // |2> -> exp(i 0)


See also
Parameters
[in,out]quregthe state-vector or density matrix to be modified
[in]qubitsa list of the indices of the qubits which will inform $r$ for each amplitude in qureg
[in]numQubitsthe length of list qubits
[in]encodingthe bitEncoding under which to infer the binary value $r$ from the bits of qubits in each basis state of qureg
[in]coeffsthe coefficients of the exponential polynomial phase function $f(r)$
[in]exponentsthe exponents of the exponential polynomial phase function $f(r)$
[in]numTermsthe length of list coeffs, which must be the same as that of exponents
[in]overrideIndsa list of sub-state indices (values of $r$) of which to explicit set the phase change
[in]overridePhasesa list of replacement phase changes, for the corresponding $r$ values in overrideInds (one to one)
[in]numOverridesthe lengths of lists overrideInds and overridePhases
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of qubits are not unique
  • if numQubits < 0 or numQubits >= qureg.numQubitsRepresented
  • if encoding is not a valid bitEncoding
  • if encoding is not compatible with numQubits (i.e. TWOS_COMPLEMENT with 1 qubit)
  • if numTerms <= 0
  • if any value in overrideInds is not producible by qubits under the given encoding (e.g. 2 unsigned qubits cannot represent index 9)
  • if numOverrides < 0
  • if exponents contains a negative power and the (consequently diverging) zero index is not contained in overrideInds
  • if encoding is TWOS_COMPLEMENT, and exponents contains a fractional number, but overrideInds does not contain every possible negative index (checked only up to 16 targeted qubits)
Author
Tyson Jones

Definition at line 743 of file QuEST.c.

743  {
744  validateMultiQubits(qureg, qubits, numQubits, __func__);
745  validateBitEncoding(numQubits, encoding, __func__);
746  validatePhaseFuncOverrides(numQubits, encoding, overrideInds, numOverrides, __func__);
747  validatePhaseFuncTerms(numQubits, encoding, coeffs, exponents, numTerms, overrideInds, numOverrides, __func__);
748 
749  int conj = 0;
750  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
751  if (qureg.isDensityMatrix) {
752  conj = 1;
753  shiftIndices(qubits, numQubits, qureg.numQubitsRepresented);
754  statevec_applyPhaseFuncOverrides(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides, conj);
755  shiftIndices(qubits, numQubits, - qureg.numQubitsRepresented);
756  }
757 
758  qasm_recordPhaseFunc(qureg, qubits, numQubits, encoding, coeffs, exponents, numTerms, overrideInds, overridePhases, numOverrides);
759 }

References Qureg::isDensityMatrix, Qureg::numQubitsRepresented, qasm_recordPhaseFunc(), shiftIndices(), statevec_applyPhaseFuncOverrides(), validateBitEncoding(), validateMultiQubits(), validatePhaseFuncOverrides(), and validatePhaseFuncTerms().

Referenced by TEST_CASE().

◆ applyProjector()

void applyProjector ( Qureg  qureg,
int  qubit,
int  outcome 
)

Force the target qubit of qureg into the given classical outcome, via a non-renormalising projection.

This function zeroes all amplitudes in the state-vector or density-matrix which correspond to the opposite outcome given. Unlike collapseToOutcome(), it does not thereafter normalise qureg, and hence may leave it in a non-physical state.

Note there is no requirement that the outcome state has a non-zero proability, and hence this function may leave qureg in a blank state, like that produced by initBlankState().

See also
Parameters
[in,out]qurega state-vector or density matrix to modify
[in]qubitthe qubit to which to apply the projector
[in]thesingle-qubit outcome (0 or 1) to project qubit into
Exceptions
invalidQuESTInputError()
  • if qubit is outside [0, qureg.numQubitsRepresented)
  • if outcome is not in {0,1}
Author
Tyson Jones

Definition at line 888 of file QuEST.c.

888  {
889  validateTarget(qureg, qubit, __func__);
890  validateOutcome(outcome, __func__);
891 
892  qreal renorm = 1;
893 
894  if (qureg.isDensityMatrix)
895  densmatr_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
896  else
897  statevec_collapseToKnownProbOutcome(qureg, qubit, outcome, renorm);
898 
899  qasm_recordComment(qureg, "Here, qubit %d was un-physically projected into outcome %d", qubit, outcome);
900 }

References densmatr_collapseToKnownProbOutcome(), Qureg::isDensityMatrix, qasm_recordComment(), qreal, statevec_collapseToKnownProbOutcome(), validateOutcome(), and validateTarget().

Referenced by TEST_CASE().

◆ applyQFT()

void applyQFT ( Qureg  qureg,
int *  qubits,
int  numQubits 
)

Applies the quantum Fourier transform (QFT) to a specific subset of qubits of the register qureg.

The order of qubits affects the ultimate unitary. The canonical full-state QFT (applyFullQFT()) is achieved by targeting every qubit in increasing order.

The effected unitary circuit (shown here for numQubits = 4) resembles

\[ \begin{tikzpicture}[scale=.5] \draw (-2, 5) -- (23, 5); \node[draw=none] at (-4,5) {qubits[3]}; \draw (-2, 3) -- (23, 3); \node[draw=none] at (-4,3) {qubits[2]}; \draw (-2, 1) -- (23, 1); \node[draw=none] at (-4,1) {qubits[1]}; \draw (-2, -1) -- (23, -1); \node[draw=none] at (-4,-1) {qubits[0]}; \draw[fill=white] (-1, 4) -- (-1, 6) -- (1, 6) -- (1,4) -- cycle; \node[draw=none] at (0, 5) {H}; \draw(2, 5) -- (2, 3); \draw[fill=black] (2, 5) circle (.2); \draw[fill=black] (2, 3) circle (.2); \draw(4, 5) -- (4, 1); \draw[fill=black] (4, 5) circle (.2); \draw[fill=black] (4, 1) circle (.2); \draw(6, 5) -- (6, -1); \draw[fill=black] (6, 5) circle (.2); \draw[fill=black] (6, -1) circle (.2); \draw[fill=white] (-1+8, 4-2) -- (-1+8, 6-2) -- (1+8, 6-2) -- (1+8,4-2) -- cycle; \node[draw=none] at (8, 5-2) {H}; \draw(10, 5-2) -- (10, 3-2); \draw[fill=black] (10, 5-2) circle (.2); \draw[fill=black] (10, 3-2) circle (.2); \draw(12, 5-2) -- (12, 3-4); \draw[fill=black] (12, 5-2) circle (.2); \draw[fill=black] (12, 3-4) circle (.2); \draw[fill=white] (-1+8+6, 4-4) -- (-1+8+6, 6-4) -- (1+8+6, 6-4) -- (1+8+6,4-4) -- cycle; \node[draw=none] at (8+6, 5-4) {H}; \draw(16, 5-2-2) -- (16, 3-4); \draw[fill=black] (16, 5-2-2) circle (.2); \draw[fill=black] (16, 3-4) circle (.2); \draw[fill=white] (-1+8+6+4, 4-4-2) -- (-1+8+6+4, 6-4-2) -- (1+8+6+4, 6-4-2) -- (1+8+6+4,4-4-2) -- cycle; \node[draw=none] at (8+6+4, 5-4-2) {H}; \draw (20, 5) -- (20, -1); \draw (20 - .35, 5 + .35) -- (20 + .35, 5 - .35); \draw (20 - .35, 5 - .35) -- (20 + .35, 5 + .35); \draw (20 - .35, -1 + .35) -- (20 + .35, -1 - .35); \draw (20 - .35, -1 - .35) -- (20 + .35, -1 + .35); \draw (22, 3) -- (22, 1); \draw (22 - .35, 3 + .35) -- (22 + .35, 3 - .35); \draw (22 - .35, 3 - .35) -- (22 + .35, 3 + .35); \draw (22 - .35, 1 + .35) -- (22 + .35, 1 - .35); \draw (22 - .35, 1 - .35) -- (22 + .35, 1 + .35); \end{tikzpicture} \]

though is performed more efficiently.

  • If qureg is a state-vector, the output amplitudes are a kronecker product of the discrete Fourier transform (DFT) acting upon the targeted amplitudes, and the remaining.
    Precisely,
    • let $|x,r\rangle$ represent a computational basis state where $x$ is the binary value of the targeted qubits, and $r$ is the binary value of the remaining qubits.
    • let $|x_j,r_j\rangle$ be the $j\text{th}$ such state.
    • let $n =$ numQubits, and $N =$ qureg.numQubitsRepresented.
      Then, this function effects

      \[ (\text{QFT}\otimes 1) \, \left( \sum\limits_{j=0}^{2^N-1} \alpha_j \, |x_j,r_j\rangle \right) = \frac{1}{\sqrt{2^n}} \sum\limits_{j=0}^{2^N-1} \alpha_j \left( \sum\limits_{y=0}^{2^n-1} e^{2 \pi \, i \, x_j \, y / 2^n} \; |y,r_j \rangle \right) \]

  • If qureg is a density matrix $\rho$, it will be changed under the unitary action of the QFT. This can be imagined as each mixed state-vector undergoing the DFT on its amplitudes. This is true even if qureg is unnormalised.

    \[ \rho \; \rightarrow \; \text{QFT} \; \rho \; \text{QFT}^{\dagger} \]

This function merges contiguous controlled-phase gates into single invocations of applyNamedPhaseFunc(), and hence is significantly faster than performing the QFT circuit directly.

Furthermore, in distributed mode, this function requires only $\log_2(\text{\#nodes})$ rounds of pair-wise communication, and hence is exponentially faster than directly performing the DFT on the amplitudes of qureg.

See also
Parameters
[in,out]qurega state-vector or density matrix to modify
[in]qubitsa list of the qubits to operate the QFT upon
[in]numQubitsthe length of list qubits
Exceptions
invalidQuESTInputError()
  • if any qubit in qubits is invalid, i.e. outside [0, qureg.numQubitsRepresented)
  • if qubits contain any repetitions
  • if numQubits < 1
  • if numQubits >qureg.numQubitsRepresented
segmentation-fault
  • if qubits contains fewer elements than numQubits
Author
Tyson Jones

Definition at line 866 of file QuEST.c.

866  {
867  validateMultiTargets(qureg, qubits, numQubits, __func__);
868 
869  qasm_recordComment(qureg, "Beginning of QFT circuit");
870 
871  agnostic_applyQFT(qureg, qubits, numQubits);
872 
873  qasm_recordComment(qureg, "End of QFT circuit");
874 }

References agnostic_applyQFT(), qasm_recordComment(), and validateMultiTargets().

Referenced by TEST_CASE().

◆ applyTrotterCircuit()

void applyTrotterCircuit ( Qureg  qureg,
PauliHamil  hamil,
qreal  time,
int  order,
int  reps 
)

Applies a trotterisation of unitary evolution $ \exp(-i \, \text{hamil} \, \text{time}) $ to qureg.

This is a sequence of unitary operators, effected by multiRotatePauli(), which together approximate the action of full unitary-time evolution under the given Hamiltonian.

Notate $ \text{hamil} = \sum_j^N c_j \, \hat \sigma_j $ where $c_j$ is a real coefficient in hamil, $\hat \sigma_j$ is the corresponding product of Pauli operators, of which there are a total $N$. Then, order=1 performs first-order Trotterisation, whereby

\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / \text{reps}) \]

order=2 performs the lowest order "symmetrized" Suzuki decomposition, whereby

\[ \exp(-i \, \text{hamil} \, \text{time}) \approx \prod\limits^{\text{reps}} \left[ \prod\limits_{j=1}^{N} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \prod\limits_{j=N}^{1} \exp(-i \, c_j \, \text{time} \, \hat\sigma_j / (2 \, \text{reps})) \right] \]

Greater even values of order specify higher-order symmetrized decompositions $ S[\text{time}, \text{order}, \text{reps}] $ which satisfy

\[ S[\text{time}, \text{order}, 1] = \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) S[ (1-4p)\,\text{time}, \text{order}-2, 1] \left( \prod\limits^2 S[p \, \text{time}, \text{order}-2, 1] \right) \]

and

\[ S[\text{time}, \text{order}, \text{reps}] = \prod\limits^{\text{reps}} S[\text{time}/\text{reps}, \text{order}, 1] \]

where $ p = \left( 4 - 4^{1/(\text{order}-1)} \right)^{-1} $.

These formulations are taken from 'Finding Exponential Product Formulas of Higher Orders', Naomichi Hatano and Masuo Suzuki (2005) (arXiv).

Note that the applied Trotter circuit is captured by QASM, if QASM logging is enabled on qureg.
For example:

applyTrotterCircuit(qureg, hamil, 1, 2, 1);

may show

// Beginning of Trotter circuit (time 1, order 2, 1 repetitions).
// Here, a multiRotatePauli with angle 0.5 and paulis X Y I was applied.
// Here, a multiRotatePauli with angle -0.5 and paulis I Z X was applied.
// Here, a multiRotatePauli with angle -0.5 and paulis I Z X was applied.
// Here, a multiRotatePauli with angle 0.5 and paulis X Y I was applied.
// End of Trotter circuit


See also
Parameters
[in,out]quregthe register to modify under the approximate unitary-time evolution
[in]hamilthe hamiltonian under which to approxiamte unitary-time evolution
[in]timethe target evolution time, which is permitted to be both positive and negative.
[in]orderthe order of Trotter-Suzuki decomposition to use. Higher orders (necessarily even) are more accurate but prescribe an exponentially increasing number of gates.
[in]repsthe number of repetitions of the decomposition of the given order. This improves the accuracy but prescribes a linearly increasing number of gates.
Exceptions
invalidQuESTInputError()
  • if qureg.numQubitsRepresented != hamil.numQubits
  • if hamil contains invalid parameters or Pauli codes,
  • if order is not in {1, 2, 4, 6, ...}
  • or if reps <= 0
Author
Tyson Jones

Definition at line 1070 of file QuEST.c.

1070  {
1071  validateTrotterParams(order, reps, __func__);
1072  validatePauliHamil(hamil, __func__);
1073  validateMatchingQuregPauliHamilDims(qureg, hamil, __func__);
1074 
1075  qasm_recordComment(qureg,
1076  "Beginning of Trotter circuit (time %g, order %d, %d repetitions).",
1077  time, order, reps);
1078 
1079  agnostic_applyTrotterCircuit(qureg, hamil, time, order, reps);
1080 
1081  qasm_recordComment(qureg, "End of Trotter circuit");
1082 }

References agnostic_applyTrotterCircuit(), qasm_recordComment(), validateMatchingQuregPauliHamilDims(), validatePauliHamil(), and validateTrotterParams().

Referenced by TEST_CASE().

void applyPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:726
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
void applyNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:813
void agnostic_applyQFT(Qureg qureg, int *qubits, int numQubits)
Definition: QuEST_common.c:849
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
void validateOutcome(int outcome, const char *caller)
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
@ PAULI_Z
Definition: QuEST.h:96
void shiftIndices(int *indices, int numIndices, int shift)
Definition: QuEST_common.c:156
void applyNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode)
Induces a phase change upon each amplitude of qureg, determined by a named (and potentially multi-var...
Definition: QuEST.c:796
@ PAULI_I
Definition: QuEST.h:96
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
void statevec_twoQubitUnitary(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Definition: QuEST_common.c:561
void statevec_unitary(Qureg qureg, int targetQubit, ComplexMatrix2 u)
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 ...
@ NORM
Definition: QuEST.h:232
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
@ UNSIGNED
Definition: QuEST.h:269
void applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by the passed exponential polynomial ...
Definition: QuEST.c:743
@ INVERSE_DISTANCE
Definition: QuEST.h:234
void validateNumPauliSumTerms(int numTerms, const char *caller)
#define qreal
@ PAULI_X
Definition: QuEST.h:96
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
void densmatr_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
Renorms (/prob) every | * outcome * >< * outcome * | state, setting all others to zero.
Definition: QuEST_cpu.c:791
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
void statevec_applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4446
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
qreal * termCoeffs
The real coefficient of each Pauli product. This is an array of length PauliHamil....
Definition: QuEST.h:283
void applyMatrix4(Qureg qureg, int targetQubit1, int targetQubit2, ComplexMatrix4 u)
Apply a general 4-by-4 matrix, which may be non-unitary.
Definition: QuEST.c:1093
void agnostic_applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Definition: QuEST_common.c:840
void statevec_applyPhaseFuncOverrides(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4268
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
void statevec_applyDiagonalOp(Qureg qureg, DiagonalOp op)
Definition: QuEST_cpu.c:4047
@ SCALED_PRODUCT
Definition: QuEST.h:233
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
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
@ PAULI_Y
Definition: QuEST.h:96
void applyParamNamedPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a named, parameterised (and potent...
Definition: QuEST.c:848
void qasm_recordComment(Qureg qureg, char *comment,...)
Definition: QuEST_qasm.c:121
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
void statevec_multiQubitUnitary(Qureg qureg, int *targets, int numTargets, ComplexMatrixN u)
Definition: QuEST_common.c:573
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
void startRecordingQASM(Qureg qureg)
Enable QASM recording.
Definition: QuEST.c:87
void statevec_applyPauliSum(Qureg inQureg, enum pauliOpType *allCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Definition: QuEST_common.c:538
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:1048
void applyMatrixN(Qureg qureg, int *targs, int numTargs, ComplexMatrixN u)
Apply a general N-by-N matrix, which may be non-unitary, on any number of target qubits.
Definition: QuEST.c:1103
void applyMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:761
void statevec_collapseToKnownProbOutcome(Qureg qureg, int measureQubit, int outcome, qreal outcomeProb)
void shiftSubregIndices(int *allInds, int *numIndsPerReg, int numRegs, int shift)
Definition: QuEST_common.c:161
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
void validatePauliHamil(PauliHamil hamil, const char *caller)
void applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Induces a phase change upon each amplitude of qureg, determined by a multi-variable exponential polyn...
Definition: QuEST.c:778
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)
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
void qasm_recordMultiVarPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:666
void applyParamNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc functionNameCode, qreal *params, int numParams)
Induces a phase change upon each amplitude of qureg, determined by a named, paramaterized (and potent...
Definition: QuEST.c:831
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
void validateTrotterParams(int order, int reps, const char *caller)
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
#define M_PI
Definition: QuEST_common.c:41
void applyTrotterCircuit(Qureg qureg, PauliHamil hamil, qreal time, int order, int reps)
Applies a trotterisation of unitary evolution to qureg.
Definition: QuEST.c:1070
void qasm_recordNamedPhaseFunc(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, enum phaseFunc funcName, qreal *params, int numParams, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:726
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
void printRecordedQASM(Qureg qureg)
Print recorded QASM to stdout.
Definition: QuEST.c:99
void qasm_recordPhaseFunc(Qureg qureg, int *qubits, int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, qreal *overridePhases, int numOverrides)
Definition: QuEST_qasm.c:490
void statevec_applyMultiVarPhaseFuncOverrides(Qureg qureg, int *qubits, int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int *numTermsPerReg, long long int *overrideInds, qreal *overridePhases, int numOverrides, int conj)
Definition: QuEST_cpu.c:4345
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232
void densmatr_applyDiagonalOp(Qureg qureg, DiagonalOp op)