qiskit-community / qiskit-ignis

Ignis (deprecated) provides tools for quantum hardware verification, noise characterization, and error correction.
Apache License 2.0
167 stars 162 forks source link

Expectation Value Tomography #280

Open dcmckayibm opened 4 years ago

dcmckayibm commented 4 years ago

Add the code to take a circuit and a list of pauli operators and output the required circuits and then a fitter to calculate the expectation value of those pauli operators. A limiting case of full state tomography.

Should probably also have an option to have a weighted list so the full "energy" can be output as well.

What is the expected behavior?

dongreenberg commented 4 years ago

Can we generalize the "energy" business to be a proper concept in tomography - taking a measurement in the basis of a given operator? The circuits produced in the VQE hamiltonian are the tomographic measurements with respect to each pauli, and the fitter computes the final expectation (both done in Aqua today). This could incorporate commutativity grouping (one measurement for "ZZII" and "IIZI") as an option as well. This would also capture some other desirable tomography techniques, such as measurement in a stabilizer basis, e.g. https://arxiv.org/abs/1908.08909, when these operators are in Terra. Thoughts?

dcmckayibm commented 4 years ago

Yes, I was assuming the module would optimize the number of circuits based on commutativity (that's really the main difference with full tomography).

chriseclectic commented 4 years ago

I think what we want is expectation value estimation of a general operator. This isn't really tomography since we aren't reconstructing a quantum object -- we are estimating a classical parameter <A> for some operator A.

You could break this up into the follow pieces:

  1. Function that decomposes an operator A into a list of measurement bases and coefficients.
  2. Function for preparing measurement circuits in multiple bases.
  3. Fitter that computes list of expectation values from counts of each measurement basis circuit
  4. Fitter that can compute from individual expectation values in step 3 + coefficients from step 1.

We already have 2 for specific case of Pauli basis in the tomography module, and 3 for converting counts to an expectation value for tensor-products of single operators (ie Paulis) here, and 4 is just do the weighted sum of expectation values with the coefficients.

So the bit that is challenging bit is step 1. How this is implemented would depend on the type of operator, some examples of operators you might want to support:

As @dongreenberg says some of these cases are already in Aqua (like weighted Paulis for VQE, and some fancy transformations to minimize the number of measure bases).

Maybe workflow could be something like:

# Get measurement bases for operator
bases, coefficients = expectation_value_bases(operator)

# Generate measurement circuits for given input state circuit
meas_circs = create_measurement_circuits(prep_circ, bases)
results = execute(meas_circs, backend).result()

# Get individual expvals and combine to coeffs
exp_val_operator = expval_fitter(results, bases, coefficients)

# And if you want intermediate expvals maybe have a seperate fitter
exp_vales_bases = expval_bases_fitter(results, bases)
chriseclectic commented 4 years ago

@dcmckayibm for your original point of computing a list of Pauli expectation values you could currently do it as follows (without optimizations for commuting pauli operators to reduce number of meas circuits)

from qiskit import *
import qiskit.ignis.verification.tomography as tomo

# Input circuit
circ = QuantumCircuit(2)
circ.h(0)
circ.cx(0, 1)

# Paulis to measure
meas_labels = [('X', 'X'), ('X', 'Z'), ('Z', 'X'), ('Z', 'Z')]

# Measurement circuits
meas_circs = tomo.state_tomography_circuits(circ, circ.qubits, meas_labels=meas_labels)

# Execute
results = execute(meas_circs, Aer.get_backend('qasm_simulator')).result()

# Convert counts to expectation values
exp_val_counts = [tomo.expectation_counts(results.get_counts(c)) for c in meas_circs]
exp_vals = [counts.get('11', 0) / counts.get('00') for counts in exp_val_counts]
for label, val in zip(meas_labels, exp_vals):
    print('<{}> = {}'.format(label, val))
dcmckayibm commented 4 years ago

Ok, great, we just need the optimizer and we're most of the way there

dongreenberg commented 4 years ago

Thanks, Chris. This all makes sense to me. This will mean a few more operator representations in Terra that can be passed to this module, but I think these were all already on the table (weighted pauli, rank stabilizer). Correct?

We have code for grouping the paulis in Aqua and other parts of piece 1. We can move these into Ignis and Terra if they are appropriate there. Adjusting the basis is an active area of research (especially within IBM), so I would expect some ongoing activity there.

Re building the circuits, two considerations: 1) Maybe we want this to be parameterized instead of copying |paulis| circuits? 2) We need to square away how to know whether construct all of these circuits or build an expectation snapshot for Aer. I think Aqua will need to own that logic.