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
5.1k stars 2.34k forks source link

`HoareOptimizer()` changes circuit semantics #13079

Closed Bennybenassius closed 3 weeks ago

Bennybenassius commented 4 weeks ago

Environment

What is happening?

Ilan and I found this issue when testing our circuit with specific transpiler passes:

When passing a specific circuit through the HoareOptimizer(), there seems to be a change to the semantics of the circuit.

How can we reproduce the issue?

Running the code below will produce 2 state-vectors: one before passing the circuit through HoareOptimizer() and one after. They are not the same, and the subsequent circuit print shows that a CX gate was removed where it shouldn't have.

from qiskit import QuantumCircuit
from helpers.qiskit_helpers import simulate_circuit
from qiskit.transpiler.passes import *
from qiskit.transpiler.passmanager import PassManager
from numpy import vdot
from qiskit.quantum_info import Statevector
from qiskit import QuantumCircuit

def simulate_circuit(qc : QuantumCircuit):
    state = Statevector.from_int(0, 2**qc.num_qubits)
    state = state.evolve(qc)
    return state

main_circ = QuantumCircuit(3)
# Applying gates 
main_circ.cx(1, 0)
main_circ.x(2)
main_circ.x(0)
main_circ.cx(2, 0)

passes = PassManager(
    [HoareOptimizer()]
)

pass_circ = passes.run(main_circ)
sv0 = simulate_circuit(main_circ)
sv1 = simulate_circuit(pass_circ)

# Compare the circuit statevector before and after the pass
if(round(abs(vdot(sv0, sv1)), 6) != 1):
    print("Failed test!\n")
    print(sv0)
    print(sv1)
else:
    print("Passed test!\n")

print(main_circ)
print(pass_circ)

The circuit before optimization:

     ┌───┐┌───┐┌───┐
q_0: ┤ X ├┤ X ├┤ X ├
     └─┬─┘└───┘└─┬─┘
q_1: ──■─────────┼──
     ┌───┐       │  
q_2: ┤ X ├───────■──
     └───┘          

The circuit after:

     ┌───┐
q_0: ┤ X ├
     └───┘
q_1: ─────
     ┌───┐
q_2: ┤ X ├
     └───┘

What should happen?

The circuit should have been optimized in a way that produced the same resulting state-vector.

Might be related to this issue #4981 that was closed.

Any suggestions?

No response

alexanderivrii commented 3 weeks ago

Thanks for reporting the problem. I have not tested this for Qiskit 1.2, but in the current development branch the bug manifested as a DAGCircuitError exception. There was indeed a problem, and I have checked in a fix in #13083. As I have commented in the fix, the code is very messy and I would not be surprised if there were many other bugs as well, please keep reporting these if you find them. The code would probably benefit from a complete rewrite, in addition to porting it to Rust :).

alexanderivrii commented 3 weeks ago

One other small comment: the equality for two Statevectors already takes some tolerance into account, so you can directly check whether sv0 == sv1 instead of computing the dot product of sv0 and sv1.

IlanIwumbwe commented 3 weeks ago

Thanks for the response! We'll keep reporting new bugs if we find any. The point you made about statevector comparison has been noted.