Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HoareOptimizer() changes circuit semantics #13079

Closed
Bennybenassius opened this issue Sep 3, 2024 · 3 comments · Fixed by #13083
Closed

HoareOptimizer() changes circuit semantics #13079

Bennybenassius opened this issue Sep 3, 2024 · 3 comments · Fixed by #13083
Assignees
Labels
bug Something isn't working

Comments

@Bennybenassius
Copy link

Environment

  • Qiskit version: 1.2.0
  • Python version: 3.10.12
  • Operating system: Ubuntu 23.10 LTS

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

@Bennybenassius Bennybenassius added the bug Something isn't working label Sep 3, 2024
@alexanderivrii alexanderivrii self-assigned this Sep 4, 2024
@alexanderivrii
Copy link
Contributor

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
Copy link
Contributor

alexanderivrii commented Sep 4, 2024

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
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants