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

Conditionals prevent identifying equivalent circuits/DAGs #3164

Closed
kdk opened this issue Sep 27, 2019 · 2 comments
Closed

Conditionals prevent identifying equivalent circuits/DAGs #3164

kdk opened this issue Sep 27, 2019 · 2 comments
Labels
bug Something isn't working priority: low

Comments

@kdk
Copy link
Member

kdk commented Sep 27, 2019

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 .

@kdk kdk added bug Something isn't working priority: low labels Sep 27, 2019
@fs1132429
Copy link
Contributor

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

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.

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

No branches or pull requests

3 participants