Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
4.91k stars 2.31k forks source link

OptimizeSwapBeforeMeasure doesn't preserve unitary if swap is only operation #4911

Open ewinston opened 3 years ago

ewinston commented 3 years ago

Information

What is the current behavior?

When swap is the only operation in the circuit, with no measures, the OptimizeSwapBeforeMeasure transpiler pass removes the swap changing the behavior of the circuit.

Steps to reproduce the problem

from qiskit import QuantumCircuit, BasicAer simulator = BasicAer.get_backend('unitary_simulator') circ = QuantumCircuit(2) circ.swap(0, 1) print(execute(circ, simulator, optimization_level=2).result().get_unitary()) print(execute(circ, simulator, optimization_level=3).result().get_unitary())

What is the expected behavior?

Suggested solutions

georgios-ts commented 3 years ago

I think the most appropriate way to handle this issue is to skip the OptimizeSwapBeforeMeasure transpiler pass if the circuit does not contain any measurements. After all, the name of the pass suggests that there should be a measurement. It's a simple check and , if you agree, i can add this.

1ucian0 commented 3 years ago

With @kdk are thinking in introducing a preserve_statevector=<bool> (final name to be defined) option to the transpiler to support this cases. This option will skip passes that do not preserve the statevector of the input circuit, including OptimizeSwapBeforeMeasure.

Would this be a reasonable solution to this issue?

1ucian0 commented 3 years ago

@ajavadia says in https://github.com/Qiskit/qiskit-terra/issues/4608#issuecomment-678569404:

Also not sure a preserve_statevector flag is the right approach. I think we should always preserve statevector. Just need a pass to clean up extra swaps if they appear before measurements (absorb them into the measurements and retarget them).

Probably the preserve_statevector=<bool> name is too confusing. Maybe preserve_unitary=<bool> is better?

The "always preserve statevector/unitary" approach has some negatives aspects:

ajavadia commented 3 years ago

Point 1: I would assume that doing/undoing swaps is pretty fast. Likewise cleaning up of swaps that are immediately followed by measurements (we should do this always anyway).

Point 3: If you add a preserve_unitary=True flag, then I don't know how mapping can be done in general. When you embed the circuit onto some larger coupling map, the unitary is different (bigger).

I agree with Point 2, but not sure yet another compiler flag is needed to deal with this. Since we are moving towards making the initial state explicit (i.e. explicit reset), we could just allow such passes that assume an initial state (such as Hoare) to run when there is an initial state, not on general circuits.