The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches

Functions for comparing multiple quantum states. More...

Functions

qreal calcDistance (Qureg qureg, Qureg other)
 
qreal calcFidelity (Qureg qureg, Qureg other)
 
qcomp calcInnerProduct (Qureg qureg, Qureg other)
 

Detailed Description

Functions for comparing multiple quantum states.

Function Documentation

◆ calcDistance()

qreal calcDistance ( Qureg qureg,
Qureg other )

Calculates one of three distance measures between qureg and other, depending upon whether one or both are density matrices. These are the Hilbert-Schmidt distance, Bures distance and purified distance.

Formulae
  • When both qureg and other are statevectors (respectively \(\ket{\psi}\) and \(\ket{\phi}\)), this function returns the Bures distance defined as

    \[ d_B\left(\ket{\psi},\ket{\phi}\right) = \sqrt{2 - 2 \left| \braket{\phi}{\psi} \right|} \]

    where \(\left| \braket{\phi}{\psi} \right|\) is the square-root of the fidelity between \(\ket{\psi}\) and \(\ket{\phi}\) as would be computed by calcFidelity().
  • When both qureg and other are density matrices (respectively \(\mathbf{\rho}\) and \(\mathbf{\sigma}\)), this function returns the Hilbert-Schmidt distance defined as

    \[ d_{HS}\left(\mathbf{\rho}, \mathbf{\sigma}\right) = \sqrt{ \tr{ \left| \mathbf{\rho} - \mathbf{\sigma} \right|^2 } } = \sqrt{ \sum\limits_{ij} \left| \rho_{ij} - \sigma_{ij} \right|^2 }. \]

  • When one of qureg or other is a statevector \(\svpsi\), and the other is a density matrix \(\dmrho\), this function returns the purified distance defined as

    \[ d_p\left(\svpsi,\dmrho\right) = \sqrt{ 1 - \brapsi \dmrho \svpsi } \]

    where \(\brapsi \dmrho \svpsi\) is the fidelity as returned by calcFidelity().
Constraints
  • The output of this function is always real, which is always mathematically satisfied by the Hilbert-Schmidt distance, but may be violated by the Bures and purified distances when the input Qureg are not normalised, or otherwise due to numerical imprecision. Postcondition validation of the Bures distance will check that

    \[ \left| \braket{\phi}{\psi} \right| \le 1 + \valeps \]

    while the purified distance validation will check that

    \[ \left| \, \im{ \brapsi \dmrho \svpsi } \, \right| \le \valeps, \\ \re{ \brapsi \dmrho \svpsi } \le 1 + \valeps, \]

    where \(\valeps\) is the validation epsilon, adjustable via setValidationEpsilon().
  • Even when the above postcondition validation is disabled, the Bures and purified distance calculations will respectively replace \(\left| \braket{\phi}{\psi} \right|\) and \(\re{ \brapsi \dmrho \svpsi }\) which exceed \(1\) with value \(1\), and the imaginary component of \(\brapsi \dmrho \svpsi\) is discarded.
  • When qureg and other are both statevectors, or both density matrices, then both or neither must be GPU-accelerated. That is, their CPU vs GPU deployments must agree. They are permitted to differ in distribution however. Such considerations are only relevant when creating the registers using createCustomQureg(), since the automatic deployments of createQureg() and createDensityQureg() will always agree.
  • When qureg and other dimensionally differ (i.e. one is a statevector while the other is a density matrix), the statevector must not be distributed unless the density matrix is distributed. The CPU vs GPU deployments however are permitted to disagree. These requirements are again consistent with the automatic deployments of the createQureg() and createDensityQureg() functions.
Equivalences
  • When both qureg and other are statevectors, this function wraps calcInnerProduct().
    qcomp prod = calcInnerProduct(qureg, other); // <qureg|other>
    qreal mag = abs(prod);
    mag = (mag > 1)? 1 : mag;
    qreal dist = std::sqrt(2 - 2 * mag);
    qcomp calcInnerProduct(Qureg qureg, Qureg other)
  • When qureg is a density matrix and other is a statevector, this function wraps calcInnerProduct() as a complex-valued proxy for calcFidelity().
    qcomp prod = calcInnerProduct(other, qureg); // <other|qureg|other>
    qreal re = real(prod);
    re = (re > 1)? 1 : re;
    qreal dist = sqrt(1 - re);
Example
setQuregToClone(rho2, rho1);
qreal distA = calcDistance(rho1, rho2); // = 0
qreal distB = calcDistance(rho1, rho2); // > 0
qreal calcDistance(Qureg qureg, Qureg other)
void setQuregToClone(Qureg outQureg, Qureg inQureg)
void initRandomMixedState(Qureg qureg, qindex numPureStates)
Qureg createDensityQureg(int numQubits)
Definition qureg.cpp:291
Definition qureg.h:49
Parameters
[in]qurega state
[in]otheranother state containing an equal number of qubits
Returns
The distance between qureg and other, according to the above measures.
Exceptions
error
  • if qureg or other is uninitialised.
  • if qureg and other contain a different number of qubits.
  • if qureg and other are incompatible deployed.
  • if qureg or other is unnormalised such that the Bures or purified distances would be non-real.
Attention
This function's input validation has not yet been unit tested, so erroneous usage may produce unexpected output. Please use with caution!
See also
Author
Tyson Jones

Definition at line 331 of file calculations.cpp.

331 {
332 validate_quregFields(quregA, __func__);
333 validate_quregFields(quregB, __func__);
334 validate_quregsCanBeProducted(quregA, quregB, __func__);
335
336 bool isDensA = quregA.isDensityMatrix;
337 bool isDensB = quregB.isDensityMatrix;
338
339 // Hilbert-Schmidt = sqrt( Tr((A-B)(A-B)^dagger) = sqrt(sum_ij |A_ij - B_ij|^2)
340 if (isDensA && isDensB) {
341 qreal dif = localiser_densmatr_calcHilbertSchmidtDistance(quregA, quregB); // >= 0
342 return std::sqrt(dif);
343 }
344
345 // Bures = sqrt(2 - 2 |<A|B>|) (even when unnormalised)
346 if (!isDensA && !isDensB) {
347 qcomp prod = localiser_statevec_calcInnerProduct(quregA, quregB);
348 qreal mag = std::abs(prod); // >= 0
349
350 validate_buresDistanceInnerProdIsNormalised(mag, __func__);
351 mag = (mag > 1)? 1 : mag; // forgive eps error to avoid complex
352 return std::sqrt(2 - 2 * mag);
353 }
354
355 // purified distance = sqrt(1 - <psi|rho|psi>)
356 qcomp fid = (quregA.isDensityMatrix)?
357 localiser_densmatr_calcFidelityWithPureState(quregA, quregB, false): // no conj
358 localiser_densmatr_calcFidelityWithPureState(quregB, quregA, false); // no conj
359
360 validate_purifiedDistanceIsNormalised(fid, __func__);
361 qreal re = std::real(fid);
362 re = (re > 1)? 1 : re; // forgive eps error to avoid complex
363 return std::sqrt(1 - re);
364}

Referenced by TEST_CASE().

◆ calcFidelity()

qreal calcFidelity ( Qureg qureg,
Qureg other )

Calculates the fidelity between qureg and other, where at least one is a statevector.

Formulae
  • When both qureg and other are statevectors (respectively \(\ket{\psi}\) and \(\ket{\phi}\)), this function returns

    \[ \left| \braket{\phi}{\psi} \right|^2. \]

  • When qureg is a density matrix \(\dmrho\) and other is a statevector \(\svpsi\), this function returns

    \[ \bra{\psi} \dmrho \ket{\psi}, \]

    and similarly when qureg is a statevector and other is a density matrix.
Constraints
  • The output of this function is always real, which validation will check after computing the fidelity as a complex scalar. Specifically, validation will assert that the result has an absolute imaginary component less than the validation epsilon, which can be adjusted with setValidationEpsilon().
  • This function does not yet support both qureg and other being density matrices, for which the fidelity calculation is more substantial.
  • When qureg and other are both statevectors, or both density matrices, then both or neither must be GPU-accelerated. That is, their CPU vs GPU deployments must agree. They are permitted to differ in distribution however. Such considerations are only relevant when creating the registers using createCustomQureg(), since the automatic deployments of createQureg() and createDensityQureg() will always agree.
  • When qureg and other dimensionally differ (i.e. one is a statevector while the other is a density matrix), the statevector must not be distributed unless the density matrix is distributed. The CPU vs GPU deployments however are permitted to disagree. These requirements are again consistent with the automatic deployments of the createQureg() and createDensityQureg() functions.
Equivalences
  • When both qureg and other are statevectors, this function is equivalent to calling calcInnerProduct() and squaring the absolute value of the result.
    qcomp prod = calcInnerProduct(qureg, other);
    qreal fid = pow(abs(prod), 2);
  • When one of qureg or other is a statevector in the computational basis state \(\ket{i}\) (e.g. as can be produced via initClassicalState()), this function is slower but equivalent to finding directly the probability of the basis state.
    // initClassicalState(other, index);
    qreal fid = calcProbOfBasisState(qureg, index);
    qreal calcProbOfBasisState(Qureg qureg, qindex index)
Example
// rho = |psi><psi|
Qureg psi = createQureg(5);
initPureState(rho, psi);
qreal fid0 = calcFidelity(rho, psi); // = 1
mixDepolarising(rho, 0, 0.5);
qreal fid1 = calcFidelity(rho, psi); // < 1
qreal calcFidelity(Qureg qureg, Qureg other)
void mixDepolarising(Qureg qureg, int target, qreal prob)
void initRandomPureState(Qureg qureg)
void initPureState(Qureg qureg, Qureg pure)
Qureg createQureg(int numQubits)
Definition qureg.cpp:283
Parameters
[in]qurega state
[in]otheranother state containing an equal number of qubits.
Returns
The fidelity between qureg and other.
Exceptions
error
  • if qureg or other is uninitialised.
  • if qureg and other contain a different number of qubits.
  • if qureg and other are incompatible deployed.
  • if both qureg and other are density matrices (as is not yet supported).
  • if qureg or other is unnormalised such that the calculated fidelity is non-real.
Attention
This function's input validation has not yet been unit tested, so erroneous usage may produce unexpected output. Please use with caution!
See also
Author
Tyson Jones

Definition at line 303 of file calculations.cpp.

303 {
304 validate_quregFields(quregA, __func__);
305 validate_quregFields(quregB, __func__);
306 validate_quregsCanBeProducted(quregA, quregB, __func__);
307
308 bool isDensA = quregA.isDensityMatrix;
309 bool isDensB = quregB.isDensityMatrix;
310
311 // F(rho,sigma) not yet supported
312 if (isDensA && isDensB)
313 validate_throwErrorBecauseCalcFidOfDensMatrNotYetImplemented(__func__);
314
315 // |<A|B>|^2
316 if (!isDensA && !isDensB) {
317 qcomp prod = localiser_statevec_calcInnerProduct(quregA, quregB);
318 return std::norm(prod);
319 }
320
321 // Re[<B|A|B>] or Re[<A|B|A>]
322 qcomp fid = (quregA.isDensityMatrix)?
323 localiser_densmatr_calcFidelityWithPureState(quregA, quregB, false): // no conj
324 localiser_densmatr_calcFidelityWithPureState(quregB, quregA, false); // no conj
325
326 validate_fidelityIsReal(fid, __func__);
327 return std::real(fid);
328}

Referenced by TEST_CASE(), and TEST_CASE().

◆ calcInnerProduct()

qcomp calcInnerProduct ( Qureg qureg,
Qureg other )

Calculates the inner product of state qureg with other.

Formulae
  • When both qureg and other are statevectors (respectively \(\ket{\psi}\) and \(\ket{\phi}\)), this function returns

    \[ \braket{\psi}{\phi} = \sum\limits_i \psi_i^* \phi_i \]

    where \(\psi_i\) and \(\phi_i\) are the \(i\)-th amplitudes of \(\ket{\psi}\) (qureg) and \(\ket{\phi}\) (other) respectively, and \(\alpha^*\) notates the complex conjugate of scalar \(\alpha\).
  • When both qureg and other are density matrices (respectively \(\mathbf{\rho}\) and \(\mathbf{\sigma}\)), this function returns

    \[ \tr{ \rho^\dagger \sigma } = \sum\limits_{ij} {\rho_{ij}}^* \, \sigma_{ij}. \]

  • When qureg is a density matrix \(\dmrho\) and other is a statevector \(\ket{\phi}\), this function returns

    \[ \bra{\phi} \dmrho^\dagger \ket{\phi}. \]

  • When qureg is a statevector \(\svpsi\) and other is a density matrix \(\mathbf{\sigma}\), this function returns

    \[ \brapsi \mathbf{\sigma} \svpsi. \]

Constraints
  • When qureg and other are both statevectors, or both density matrices, then both or neither must be GPU-accelerated. That is, their CPU vs GPU deployments must agree. They are permitted to differ in distribution however. Such considerations are only relevant when creating the registers using createCustomQureg(), since the automatic deployments of createQureg() and createDensityQureg() will always agree.
  • When qureg and other dimensionally differ (i.e. one is a statevector while the other is a density matrix), the statevector must not be distributed unless the density matrix is distributed. The CPU vs GPU deployments however are permitted to disagree. These requirements are again consistent with the automatic deployments of the createQureg() and createDensityQureg() functions.
Example
// rho1 = rho2 = |psi><psi|
setQuregToClone(rho2, rho1);
qcomp prodA = calcInnerProduct(rho1, rho2); // = 1
// rho1 = rho2 = sum_i prob_i |psi_i><psi_i|
setQuregToClone(rho2, rho1);
qcomp prodB = calcInnerProduct(rho1, rho2); // < 1, real
// rho1 != rho2
qcomp prodC = calcInnerProduct(rho1, rho2); // abs < 1, complex
Parameters
[in]qurega state
[in]otheranother state with an equal number of qubits
Returns
The inner product of qureg with other.
Exceptions
error
  • if qureg or other is uninitialised.
  • if qureg and other contain a different number of qubits.
  • if qureg and other are incompatibly deployed.
Attention
This function's input validation has not yet been unit tested, so erroneous usage may produce unexpected output. Please use with caution!
See also
Author
Tyson Jones

Definition at line 49 of file calculations.cpp.

49 {
50 validate_quregFields(quregA, __func__);
51 validate_quregFields(quregB, __func__);
52 validate_quregsCanBeProducted(quregA, quregB, __func__);
53
54 // <A|B> or Tr(A^dagger B) = <<A|B>>
55 if (quregA.isDensityMatrix == quregB.isDensityMatrix)
56 return localiser_statevec_calcInnerProduct(quregA, quregB);
57
58 return (quregA.isDensityMatrix)?
59 localiser_densmatr_calcFidelityWithPureState(quregA, quregB, true): // <B|A^dagger|B>
60 localiser_densmatr_calcFidelityWithPureState(quregB, quregA, false); // <A|B|A>
61}

Referenced by TEST_CASE(), and TEST_CASE().