1

I want to use IBMQ's runtime Estimator primitive to address their systems. Since it has no function to return the transpiled circuit, but I need the knowledge what circuit exactly was executed in the end, I want to do the transpilation locally and then give that circuit into the estimator.

For the transpiling I add the needed post-rotations for measuring non-PauliZ, then add the classical registers for the measurements and then transpile this circuit. So I end up with a complete circuit with classical registers and qubits on which nothing happens, they are just part of the device. (see code below)

What is a elegant way to separate this into a circuit and an observable that I can pass to the estimator?

minimal `code example:

from qiskit import QuantumCircuit, transpile, IBMQ
from qiskit_ibm_runtime import QiskitRuntimeService
backend='ibmq_quito'
service=QiskitRuntimeService()
backend=service.get_backend(backend)

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

#post-rotations: want to measure 'XZ' meas_circuit= QuantumCircuit(2) meas_circuit.h(0)

#add post-rotations to circuit full_circ=circuit.compose(meas_circuit).measure_all(inplace=False)

#transpile trans_circ = transpile(full_circ, backend)

print(trans_circ)

I want to use the estimator to measure the expectation value of ZZ on the non-idle qubits of trans_circ.

Since I need the same number of observables and qubits, can I just take the identity as observable for the qubits I am not interested in? Those will just give factors of 1 to each term of the expectation value. What I tried was:

service=QiskitRuntimeService()
session=Session(service=service, backend=backend)
options=Options()
options.resilience_level=3
estimator=Estimator(session=session, options=options)

params=[] obs=SparsePauliOp.from_list([("IIIZZ", 1)])

job=estimator.run(circuits=trans_circ, observables=obs, parameter_values=params) expvals=job.result().values print(expvals)

This gives me some output, but I am not sure whether it is correct: It returns values around 0.95 while I calculated an expectation value of 0.5 on paper. Is there a mistake or do I see the impact of noise of the hardware here like in this question?

Also what happens to the measurement instructions here? Are they ignored? Do I need them or better separate?

qcabepsilon
  • 195
  • 9

1 Answers1

1

The problem here should be in how your are creating your SparsePauliOp observable: if you want to measure the expectation value of $Z_0Z_1$ (non-idle qubits of the transpiled circuit), you have to do

obs = SparsePauliOp.from_list([("IIIZZ", 1)])

and not

obs = SparsePauliOp.from_list([("ZZIII", 1)])

Take a look to the qiskit.quantum_info.SparsePauliOp.from_list documentation for more details.

SimoneGasperini
  • 1,492
  • 1
  • 2
  • 18
  • Thank you for this note. I have overseen this completely. I changed the code above accordingly. But this still doesn't give me the expected result. – qcabepsilon Dec 19 '22 at 12:51
  • Could you give some more details about the expected result you are looking for? – SimoneGasperini Jan 13 '23 at 09:52
  • I tested it again with error mitigation. With that I get reasonable results of ~-0.009 when I expect 0 as expectation value. It seems like the deviance I have seen is actually due to the hardware errors only. – qcabepsilon Jan 13 '23 at 12:22
  • The question remaining is what happens to the measurement instructions? Are they ignored in any case or do they influence my result and I just don't see it in my simple example? – qcabepsilon Jan 13 '23 at 12:23