Function applyMultiVarPhaseFunc

Source
pub unsafe extern "C" fn applyMultiVarPhaseFunc(
    qureg: Qureg,
    qubits: *mut c_int,
    numQubitsPerReg: *mut c_int,
    numRegs: c_int,
    encoding: bitEncoding,
    coeffs: *mut f64,
    exponents: *mut f64,
    numTermsPerReg: *mut c_int,
)
Expand description

Induces a phase change upon each amplitude of \p 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 \p coeffs, \p exponents and \p numTermsPerReg together specify a real exponential polynomial \f$f(\vec{r})\f$ of the form \f[ 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}},, \f] where both coefficients \f$c_{i,j}\f$ and exponents \f$p_{i,j}\f$ can be any real number, subject to constraints described below. \n\n While \p coeffs and \p exponents are flat lists, they should be considered grouped into #numRegs sublists with lengths given by \p numTermsPerReg (which itself has length \p numRegs). \n\n 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[ f(\vec{r}) = 1 , {r_1}^2 + 2 , {r_2} + 4 , {r_2}^{5} - 3.14 , {r_3}^{0.5}. \f] \n

    This means lists \p coeffs and \p exponents should both be of length equal to the sum of \p numTermsPerReg. Unlike applyPhaseFunc(), applyMultiVarPhaseFunc() places additional constraints on the exponents in \f$f(\vec{r})\f$, due to the exponentially growing costs of overriding diverging indices. Namely:\n -# \p 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$f(\vec{r})\f$ 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 \f[ \exp( i \sum_j f_j(r_j) ) = \prod_j \exp(i f_j(r_j) ). \f] -# \p exponents must not contain a fractional number if \p 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$f(\vec{r})\f$ 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. \n\n

  • Lists \p qubits and \p numQubitsPerReg together describe #numRegs sub-registers of \p qureg, which can each contain a different number of qubits. \n Although \p qubits is a flat list of unique qubit indices, it should be imagined grouped into #numRegs sub-lists, of lengths given by \p numQubitsPerReg. \n\n 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. \f[ |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 \f] 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.\n\n

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

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

  • The function \f$f(\vec{r})\f$ specifies the phase change to induce upon amplitude \f$\alpha\f$ of computational basis state with the nominated sub-registers encoding values \f$r_1, ; \dots\f$. \f[ \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. \f] For example, using the sub-registers in the previous example and \p encoding = \p UNSIGNED, the following states receive amplitude factors: \f[ \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} \f]

  • If \p qureg is a density matrix \f$\rho\f$, then its elements are modified as \f[ \alpha , |j\rangle\langle k| ; \rightarrow ; \exp(i , (f(\vec{r}_j) - f(\vec{r}_k)) , ) ; \alpha , |j\rangle\langle k|, \f] where \f$f(\vec{r}_j)\f$ and \f$f(\vec{r}_k)\f$ are determined as above.\n\n

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

    startRecordingQASM(qureg);
    applyMultiVarPhaseFunc(qureg, ...);
    printRecordedQASM(qureg);

    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}

\n

@see

  • applyMultiVarPhaseFuncOverrides() to additionally specify explicit phases for specific sub-register values.
  • applyNamedPhaseFunc() for a set of specific and potentially multi-variable phase functions.
  • applyPhaseFunc() for a single-variable polynomial exponential phase function, which is approximately twice as fast.
  • applyDiagonalOp() to apply a non-unitary diagonal operator.

@ingroup operator @param[in,out] qureg the state-vector or density matrix to be modified @param[in] qubits a list of all the qubit indices contained in each sub-register @param[in] numQubitsPerReg a list of the lengths of each sub-list in \p qubits @param[in] numRegs the number of sub-registers, which is the length of both \p numQubitsPerReg and \p numTermsPerReg @param[in] encoding the ::bitEncoding under which to infer the binary value \f$r_j\f$ from the bits of a sub-register @param[in] coeffs the coefficients of all terms of the exponential polynomial phase function \f$f(\vec{r})\f$ @param[in] exponents the exponents of all terms of the exponential polynomial phase function \f$f(\vec{r})\f$ @param[in] numTermsPerReg a list of the number of \p coeff and \p exponent terms supplied for each variable/sub-register @exception invalidQuESTInputError()

  • if any qubit in \p qubits has an invalid index (i.e. does not satisfy 0 <= qubit < qureg.numQubitsRepresented)
  • if the elements of \p qubits are not unique (including if sub-registers overlap)
  • if \p numRegs <= 0 or \p numRegs > 100 (constrained by MAX_NUM_REGS_APPLY_ARBITRARY_PHASE in QuEST_precision.h)
  • if \p encoding is not a valid ::bitEncoding
  • if the size of any sub-register is incompatible with \p encoding (e.g. contains fewer than two qubits in \p encoding = \p TWOS_COMPLEMENT)
  • if any element of \p numTermsPerReg is < 1
  • if \p exponents contains a negative number
  • if \p exponents contains a fractional number despite \p encoding = ::TWOS_COMPLEMENT @author Tyson Jones