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.98k stars 2.32k forks source link

Conditionals prevent identifying equivalent circuits/DAGs #3164

Closed kdk closed 1 year ago

kdk commented 4 years ago

The circuit identity check does not distinguish between classical wires used as cargs and classical wires used as conditionals, and so the following two circuits are marked as non-equivalent:

>>> import qiskit as qk
>>> qr = qk.QuantumRegister(2)
>>> cr = qk.ClassicalRegister(1)
>>> qc1 = qk.QuantumCircuit(qr, cr)
>>> qc1.h(0).c_if(cr, 0)
>>> qc1.h(1).c_if(cr, 0)
>>> print(qc1)
          ┌───┐
q0_0: |0>─┤ H ├────────
          └─┬─┘  ┌───┐
q0_1: |0>───┼────┤ H ├─
            │    └─┬─┘
         ┌──┴──┐┌──┴──┐
 c0_0: 0 ╡ = 0 ╞╡ = 0 ╞
         └─────┘└─────┘
>>> qc2 = qk.QuantumCircuit(qr, cr)
>>> qc2.h(1).c_if(cr, 0)
>>> qc2.h(0).c_if(cr, 0)
>>> print(qc2)
                 ┌───┐
q0_0: |0>────────┤ H ├─
          ┌───┐  └─┬─┘
q0_1: |0>─┤ H ├────┼───
          └─┬─┘    │
         ┌──┴──┐┌──┴──┐
 c0_0: 0 ╡ = 0 ╞╡ = 0 ╞
         └─────┘└─────┘
>>> qc1 == qc2
False

Since both gates use c0 as a condition, and there is no gate between them which uses c0 as a carg, it should be possible to determine that the order of the two gates on c0 is not important. Ref. test.python.transpiler.test_cx_direction.TestCXDirection.test_preserves_conditions .

fs1132429 commented 2 years ago

Update for GoGP

✅ Issue still reproducible as per the original author. The Code:

import qiskit as qk
qr = qk.QuantumRegister(2)
cr = qk.ClassicalRegister(1)
qc1 = qk.QuantumCircuit(qr, cr)
qc1.h(0).c_if(cr, 0)
qc1.h(1).c_if(cr, 0)
print(qc1)
Screenshot 2021-12-14 at 12 14 31 AM
qc2 = qk.QuantumCircuit(qr, cr)
qc2.h(1).c_if(cr, 0)
qc2.h(0).c_if(cr, 0)
print(qc2)
Screenshot 2021-12-14 at 12 14 29 AM
>>> qc1 == qc2
False

The output is still False when we compare both the circuits.

jakelishman commented 1 year ago

The two circuits given in this example are structurally different because of the data dependency flowing along bit 0; without an optimising compiler recognising that these are the same condition and that they can be merged into a single classical check, there's no practical way for the DAG comparison to see these two circuits as equal, because under the IR, they are different.

There's not entirely a problem with conditionals: if I instead make the circuits as

import qiskit as qk
qr = qk.QuantumRegister(2)
cr1 = qk.ClassicalRegister(1)
cr2 = qk.ClassicalRegister(1)
qc1 = qk.QuantumCircuit(qr, cr1, cr2)
qc1.h(0).c_if(cr1, 0)
qc1.h(1).c_if(cr2, 0)
print(qc1)

qc2 = qk.QuantumCircuit(qr, cr1, cr2)
qc2.h(1).c_if(cr2, 0)
qc2.h(0).c_if(cr1, 0)
print(qc2)

then we have qc1 == qc2, despite the re-ordering of the circuits required.

I think that if we use "the bit can't have changed between the conditions" as a requirement, we're opening a separate can of worms - should two circuits compare equal if there's extra explicit quantum no-ops on some of its qubits too? It feels like we're getting into the realm of larger equivalence checkers at that point, which I think is a separate and larger issue than this one.

I propose to close this bug report as "not a bug", and fold its requests into a potential equivalence checker feature request (e.g. #761). In the interests of slimming the issues, I'll just close this pre-emptively, but feel free to re-open if you disagree with me.