• Docs >
  • Obtaining expectation values
Shortcuts

Obtaining expectation valuesΒΆ

Given a quasi- or standard probability distribution, it is possible to compute the expectation value of diagonal operators directly from the distributions (or collections) of distributions. This can be done using string representation for standard diagonal operators such as I, Z, 0 or 1, or via dictionaries for custom operators.

Let us first generate some quasi-distributions by mitigating 2- and 3-qubit GHZ circuits on a noisy-simulator.

import numpy as np
from qiskit import *
from qiskit.test.mock import FakeAthens
import mthree

backend = FakeAthens()

ghz2 = QuantumCircuit(2)
ghz2.h(0)
ghz2.cx(0,1)
ghz2.measure_all()

trans_ghz2 = transpile(ghz2, backend)

ghz3 = QuantumCircuit(3)
ghz3.h(0)
ghz3.cx(0,1)
ghz3.cx(1,2)
ghz3.measure_all()

trans_ghz3 = transpile(ghz3, backend)

raw2 = backend.run(trans_ghz2, shots=4000).result().get_counts()
raw3 = backend.run(trans_ghz3, shots=4000).result().get_counts()

mit = mthree.M3Mitigation(backend)
mit.cals_from_system()

quasi2 = mit.apply_correction(raw2, [0,1], return_mitigation_overhead=True)
quasi3 = mit.apply_correction(raw3, [0,1,2], return_mitigation_overhead=True)

Now let us compute the expectaion values of these distributions for the default case of Z operators on each qubit:

print('GHZ2:', quasi2.expval())
print('GHZ3:', quasi3.expval())
GHZ2: 0.9817647774891036
GHZ3: -0.004976374434324526

The values are close to one and zero, respectively. We can use strings to repeat the above via:

print('GHZ2:', quasi2.expval('ZZ'))
print('GHZ3:', quasi3.expval('ZZZ'))
GHZ2: 0.9817647774891036
GHZ3: -0.004976374434324526

Replacing a Z measurement with an I on one of the qubits has the affect of changing the sign for the \(|1>^{\otimes N}\) component:

print('GHZ2:', quasi2.expval('IZ'))
print('GHZ3:', quasi3.expval('ZIZ'))
GHZ2: 0.03491596638655464
GHZ3: 0.971193548266315

We can also pass lists of strings:

quasi3.expval_and_stddev(['ZZZ','ZIZ'])
(array([-0.00497637,  0.97119355]), 0.01832167780467993)

Alternatively, users can specify their own custom diagonal operators using dictionaries. Here we form the projectors on the all ones and zeros states:

all_zeros_proj = {'000': 1}
all_ones_proj = {'111': 1}
quasi3.expval(all_zeros_proj)
0.4911920941923766

Like strings, one can pass an array of dicts:

quasi3.expval([all_zeros_proj, all_ones_proj])
array([0.49119209, 0.49261521])

We can verify that the projectors return the correct values:

p0s, p1s = quasi3.expval([all_zeros_proj, all_ones_proj])
np.allclose([p0s, p1s], [quasi3['000'], quasi3['111']])
True