Observable Job

The second type of final measurement, the “OBSERVABLE” mode can be used to compute the average value of an observable. We will reuse the simple Bell pair \(|\psi\rangle=(|00\rangle+|11\rangle)/\sqrt{2}\) circuit, and compute the average value of the following observable:

\[O = X_0 \otimes Z_1\]

A straightforward computation yields \(\langle O \rangle = 0\). Let us now perform this computation with Qaptiva and verify the result.

We start with a computation devoid of any shot noise (infinite number of shots).

from qat.lang.AQASM import Program, H, CNOT
from qat.qpus import get_default_qpu

# Create a circuit
qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

# Create an observable
from qat.core import Observable, Term
obs = Observable(2, pauli_terms=[Term(1, "XZ", [0, 1])])

# Create a job
job = circuit.to_job(observable=obs)

# Execute
result = get_default_qpu().submit(job)
print("<O> = ", result.value)
<O> =  0.0

We verify that the expectation value \(\langle O \rangle\) of the result is 0.

We now look at the effect of shot noise. In practice one can only repeat the measurement a finite number of times. Here, we will submit three jobs, each with a different number of shots nbshots, to the QPU.

from qat.lang.AQASM import Program, H, CNOT
from qat.qpus import get_default_qpu

# Create a circuit
qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

# Create an observable
from qat.core import Observable, Term
obs = Observable(2, pauli_terms=[Term(1, "XZ", [0, 1])])

# Create a job
for nbshots in [100, 1000, 10000]:
    job = circuit.to_job(observable=obs, nbshots=nbshots)

    # The QPU is stacked with ObservableSplitter, as the default QPU does not support
    # a finite number of shots for observable sampling
    from qat.plugins import ObservableSplitter
    result = (ObservableSplitter() | get_default_qpu()).submit(job)

    print(f"<O> ({nbshots} shots) = {result.value} +/- {result.error}")
<O> (100 shots) = -0.06 +/- 0.10032271160931837
<O> (1000 shots) = -0.02400000000000002 +/- 0.03162948662916337
<O> (10000 shots) = 0.005399999999999988 +/- 0.010000354229149628

We can see that the expectation value \(\langle O \rangle\) of the result differs from the ideal one due to “shot noise”. The error field contains the standard error of the estimated expectation value.