Wavefunction overlaps

Qadence offers convenience functions for computing the overlap between the wavefunctions generated by two quantum circuits \(U\) and \(W\) as:

\[ S = |\langle \psi_U | \psi_W \rangle|^2 \quad \textrm{where} \quad \psi_U = U|\psi_0\rangle \]

Here is an example on how to compute the overlap between two very simple parametric circuits consisting of a single RX rotation on different qubits. The overlap is expected to be non-zero only when the rotation angle is different from \(\pi \; \textrm{mod}\; 2\pi\) for both rotations:

import torch
import numpy as np
from qadence import Overlap, OverlapMethod, QuantumCircuit, H, RX, X, FeatureParameter, hea


# Create two quantum circuits
# with a single qubit rotation on two random qubits
n_qubits = 4
qubits = np.random.choice(n_qubits, n_qubits, replace=False)

phi = FeatureParameter("phi")
circuit_bra = QuantumCircuit(n_qubits, RX(qubits[0], phi))

psi = FeatureParameter("psi")
circuit_ket = QuantumCircuit(n_qubits, RX(qubits[1], psi))

# Values for the feature parameters
values_bra = {"phi": torch.Tensor([torch.pi / 2, torch.pi])}
values_ket = {"psi": torch.Tensor([torch.pi / 2, torch.pi])}

# Calculate overlap by assigning values to the given bra and ket circuits
ovrlp = Overlap(circuit_bra, circuit_ket)
ovrlp = ovrlp(bra_param_values=values_bra, ket_param_values=values_ket)
Overlap with exact method:
 tensor([[2.5000e-01, 1.8747e-33],
        [1.8747e-33, 1.4058e-65]])

The Overlap class above inherits from QuantumModel and is executed through its inherited forward method for the given input parameter values. By default, the overlap is computed exactly by performing the dot product of the wavefunction propagated from bra and ket circuits.

However, it is possible to choose a different method from the OverlapMethod enumeration to be passed via the overlap_method argument in the Overlap initializer. Currently, one can choose from:

  • EXACT: exact computation using the wavefunction matrix representation. Does not work with real devices since it assumes access to the complete qubit system wavefunction.
  • COMPUTE_UNCOMPUTE: exact or sampling-based computation using bra \(U\) and ket \(W^{\dagger}\) unitaries.
  • SWAP_TEST: exact or sampling-based computation using the SWAP test method.
  • HADAMARD_TEST: exact or sampling-based computation using the Hadamard test method.
  • JENSEN_SHANNON: compute the overlap using the Jensen-Shannon divergence of the two probability distributions obtained by sampling the propagated circuits. This will yield a different result than the other methods.

All methods (except for the EXACT method) take an optional n_shots argument which can be used to perform shot-based calculations.

Warning

If you select a finite number of shots, the overlap is not differentiable. Therefore, it cannot be used as output of a quantum model if gradients are required.

# Calculate overlap with SWAP test
ovrlp = Overlap(circuit_bra, circuit_ket, method=OverlapMethod.SWAP_TEST)
ovrlp_ha = ovrlp(values_bra, values_ket)

# Calculate overlap with SWAP test
# using a finite number of shots
ovrlp = Overlap(circuit_bra, circuit_ket, method=OverlapMethod.SWAP_TEST)
ovrlp_ha = ovrlp(values_bra, values_ket, n_shots=10_000)
Overlap with SWAP test:
 tensor([[2.5000e-01, 4.4409e-16],
        [4.4409e-16, 4.4409e-16]])
Overlap with SWAP test with finite number of shots:
 tensor([[ 0.2524, -0.0104],
        [ 0.0020,  0.0012]])