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

🐛 Partial equivalence with ancillary qubits #508

Open
jricc opened this issue Nov 21, 2024 · 5 comments · May be fixed by #512
Open

🐛 Partial equivalence with ancillary qubits #508

jricc opened this issue Nov 21, 2024 · 5 comments · May be fixed by #512
Labels
bug Something isn't working c++ Anything related to C++ code

Comments

@jricc
Copy link

jricc commented Nov 21, 2024

Environment information

  • OS: Linux Mint 21.2
  • C++ compiler: g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
  • mqt.qcec: 2.8.1

Description

I’m facing an issue when trying to verify the partial equivalence between two quantum circuits, qc1 and qc2.
qc1:
image
qc2:
image

Expected behavior

When I check the equivalence of these two circuits, the result is not_equivalent, but I expected a partial equivalence between them.
I would like to:

  • Understand why the circuits are reported as not equivalent.
  • Find a solution or guidance on how to verify partial equivalence correctly.

Thank you for your help!

How to Reproduce

import sys
from mqt.qcec import verify
from qiskit import QuantumCircuit

qc1 = QuantumCircuit(3, 1)

qc1.reset(1)
qc1.reset(2)
qc1.measure([2], [0])

qc2 = QuantumCircuit(3, 1)

qc2.reset(1)
qc2.reset(2)
qc2.h(0)
qc2.cx(0, 1)
qc2.measure([2], [0])

result = verify(
    qc1, qc2, check_partial_equivalence=True, transform_dynamic_circuit=True
)
print(result.equivalence)
@github-project-automation github-project-automation bot moved this to In Progress in MQT Verification Nov 21, 2024
@jricc jricc changed the title 🐛 <title>Partial equivalence with ancillary qubits 🐛 Partial equivalence with ancillary qubits Nov 21, 2024
@burgholzer
Copy link
Member

Hey 👋🏻

Thanks for raising this issue!

Let me start by pointing out a couple of things:

I suppose you are placing the reset operations in the circuit to indicate that these qubits are ancillaries that should be in the zero state. Rather than that, you should be able to explicitly add these as AncillaQubits (https://docs.quantum.ibm.com/api/qiskit/circuit#qiskit.circuit.AncillaQubit) in Qiskit and that should directly flag them as such when being imported in QCEC.

You are not really building a dynamic quantum circuit here because you are not using the non-unitary primitives in the middle of the computation. So enabling that flag for QCEC does not really help much.

One could argue that QCEC could strip these operations from the circuit and instead mark them as ancillaries, which might be a pretty reasonable thing to do. Especially since we already try to determine output permutations from final measurements.
I am not really close to my laptop right now and for the next couple days. But let me try to get back to you on this.

In the meantime, it should work if you remove the reset operations and disable the dynamic circuit option.

@jricc
Copy link
Author

jricc commented Nov 22, 2024

Hey!
Thank you for your response and the proposed solution. I tried implementing it, but I encountered an error related to the use of AncillaQubit, even when testing with a minimal example.
Could you please help clarify or suggest an alternative approach?
Thank you in advance!

import sys
from mqt.qcec import verify
from qiskit import QuantumCircuit
from qiskit.circuit import AncillaQubit

ancilla = AncillaQubit()

qc1 = QuantumCircuit(1, 0)

qc1.add_bits([ancilla])
qc1.h(ancilla)

qc2 = QuantumCircuit(1, 0)
qc2.add_bits([ancilla])

result = verify(
    qc1,
    qc2,
    check_partial_equivalence=True,
)
print(result.equivalence)

qc1:
image
qc2:
image

  File ".../lib/python3.10/site-packages/mqt/qcec/verify.py", line 56, in verify
    ecm = EquivalenceCheckingManager(circ1, circ2, configuration)
RuntimeError: Could not import first circuit: KeyError: <qiskit.circuit.quantumregister.AncillaQubit object at 0x7f8da4895400>

@burgholzer
Copy link
Member

Hey!

Thank you for your response and the proposed solution. I tried implementing it, but I encountered an error related to the use of AncillaQubit, even when testing with a minimal example.

Could you please help clarify or suggest an alternative approach?

Thank you in advance!

import sys

from mqt.qcec import verify

from qiskit import QuantumCircuit

from qiskit.circuit import AncillaQubit



ancilla = AncillaQubit()



qc1 = QuantumCircuit(1, 0)



qc1.add_bits([ancilla])

qc1.h(ancilla)



qc2 = QuantumCircuit(1, 0)

qc2.add_bits([ancilla])



result = verify(

    qc1,

    qc2,

    check_partial_equivalence=True,

)

print(result.equivalence)

qc1:

image

qc2:

image

  File ".../lib/python3.10/site-packages/mqt/qcec/verify.py", line 56, in verify

    ecm = EquivalenceCheckingManager(circ1, circ2, configuration)

RuntimeError: Could not import first circuit: KeyError: <qiskit.circuit.quantumregister.AncillaQubit object at 0x7f8da4895400>

Alright. One step closer. I can reproduce your error. It has something to do with the way we translate Qiskit circuits.
If you change AncillaQubit for AncillaRegister and add that instead of the individual qubit, you'll get one step further in the sense that the circuit import will work, but some other error pops up in the equivalence check.
Although, I am pretty sure this is just because of the artificial nature of the circuits (with one of them being empty), I'd still like to get this fixed.
I am traveling today and will probably get to it beginning next week.
I'll also investigate whether the above mentioned solution of inferring the ancillaries from the resets would work.

@burgholzer burgholzer linked a pull request Nov 25, 2024 that will close this issue
4 tasks
@burgholzer
Copy link
Member

Alright, I did some digging. Turns out this seems to only really affect the ZX-based equivalence checker. The following code works just fine on my machine

from qiskit import QuantumCircuit
from qiskit.circuit import AncillaRegister

from mqt.qcec import verify

anc = AncillaRegister(1)

qc1 = QuantumCircuit(1, 0)

qc1.add_register(anc)
qc1.h(anc[0])

qc2 = QuantumCircuit(1, 0)
qc2.add_register(anc)

result = verify(
    qc1,
    qc2,
    check_partial_equivalence=True,
    run_zx_checker=False,
)
print(result.equivalence)

While we work on fixing the ZX Checker, the above should allow you to run the equivalence check as desired.

@burgholzer burgholzer added bug Something isn't working c++ Anything related to C++ code labels Nov 25, 2024
@burgholzer burgholzer added this to MQT Nov 25, 2024
@github-project-automation github-project-automation bot moved this to In Progress in MQT Nov 25, 2024
@jricc
Copy link
Author

jricc commented Nov 26, 2024

Great, thanks! It works on my machine too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working c++ Anything related to C++ code
Projects
Status: In Progress
Status: In Progress
Development

Successfully merging a pull request may close this issue.

2 participants