unitaryfund / mitiq

Mitiq is an open source toolkit for implementing error mitigation techniques on most current intermediate-scale quantum computers.
https://mitiq.readthedocs.io
GNU General Public License v3.0
358 stars 157 forks source link

Measurement order changed after folding #551

Closed pgysbers closed 3 years ago

pgysbers commented 3 years ago

Issue Description

When the measurement operators of a circuit are re-appended after folding they can be added back in the wrong order (mixing up which ClassicalRegisters correspond to which QuantumRegisters). This changes the value of some expectation values.

How to Reproduce

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from mitiq.zne.scaling import fold_gates_at_random

q, c = QuantumRegister(2), ClassicalRegister(2)
circuit = QuantumCircuit(q, c)
circuit.h(q[0])
circuit.measure(q, c)

print(circuit)
      ┌───┐┌─┐
q0_0: ┤ H ├┤M├
      └┬─┬┘└╥┘
q0_1: ─┤M├──╫─
       └╥┘  ║ 
c0: 2/══╩═══╩═
        1   0 
folded = fold_gates_at_random(circuit, scale_factor=1.)

print(folded)
      ┌───┐┌─┐
q0_0: ┤ H ├┤M├
      └┬─┬┘└╥┘
q0_1: ─┤M├──╫─
       └╥┘  ║ 
c0: 2/══╩═══╩═
        0   1 

Environment Context

from mitiq import about
about()

Mitiq: A Python toolkit for implementing error mitigation on quantum computers
==============================================================================
Authored by: Mitiq team, 2020 & later (https://github.com/unitaryfund/mitiq)

Mitiq Version:  0.5.0

Core Dependencies
-----------------
Cirq Version:   0.10.0.dev
NumPy Version:  1.20.0
SciPy Version:  1.4.1

Optional Dependencies
---------------------
PyQuil Version: Not installed
Qiskit Version: 0.16.4

Python Version: 3.8.6
Platform Info:  Linux (x86_64)
rmlarose commented 3 years ago

Yeah, that's not good. Thanks for reporting this.

rmlarose commented 3 years ago

It looks like this is not due to transforming registers as I originally thought but rather from the base (Cirq) conversions:

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit

q, c = QuantumRegister(2), ClassicalRegister(2)
circuit = QuantumCircuit(q, c)
circuit.x(q[0])
circuit.measure(q, c)

print(circuit)
#          ┌───┐┌─┐
# q1_0: |0>┤ X ├┤M├
#          └┬─┬┘└╥┘
# q1_1: |0>─┤M├──╫─
#           └╥┘  ║ 
#  c1_0: 0 ══╬═══╩═
#            ║     
#  c1_1: 0 ══╩═════

Converting to Cirq then back to Qiskit results in flipped classical register order:

from mitiq.mitiq_qiskit.conversions import from_qiskit, to_qiskit

converted = to_qiskit(from_qiskit(circuit))
print(converted)
#             ┌───┐┌─┐
#     q_0: |0>┤ X ├┤M├
#             └┬─┬┘└╥┘
#     q_1: |0>─┤M├──╫─
#              └╥┘  ║ 
# m_c0_1_0: 0 ══╩═══╬═
#                   ║ 
# m_c0_0_0: 0 ══════╩═
rmlarose commented 3 years ago

What I should say is that the reversed measurement order is due to base conversions, and transforming registers doesn't help.

Continuing from the previous example:

converted = to_qiskit(from_qiskit(circuit), qregs=circuit.qregs, cregs=circuit.cregs)

print(converted)
#          ┌───┐┌─┐
# q0_0: |0>┤ H ├┤M├
#          └┬─┬┘└╥┘
# q0_1: |0>─┤M├──╫─
#           └╥┘  ║ 
#  c0_0: 0 ══╩═══╬═
#                ║ 
#  c0_1: 0 ══════╩═

So here the issue is:

rmlarose commented 3 years ago

After investigating more, it appears the order gets changed due to the the following fact: The X gate below causes the measurement "q1_1 -> c1_1" to appear before (in a left-to-right sense) the measurement "q1_0 -> c1_0". The base converter probably looks at the first measurement, sees what bit it writes to, then calls this the first bit in the converted circuit. So here, it causes the bits to get reversed.

#          ┌───┐┌─┐
# q1_0: |0>┤ X ├┤M├
#          └┬─┬┘└╥┘
# q1_1: |0>─┤M├──╫─
#           └╥┘  ║ 
#  c1_0: 0 ══╬═══╩═
#            ║     
#  c1_1: 0 ══╩═════

I think this is the general behavior, so the top-to-bottom order of the returned registers corresponds to the left-to-right order of measurements in the original circuit. How wonderful.

pgysbers commented 3 years ago

Thanks @rmlarose ! Your pull request fixes the issues I was experiencing