cda-tum / mqt-qcec

MQT QCEC - A tool for Quantum Circuit Equivalence Checking
https://mqt.readthedocs.io/projects/qcec
MIT License
95 stars 21 forks source link

šŸ› Partial equivalence with ancillary qubits #508

Open jricc opened 1 day ago

jricc commented 1 day ago

Environment information

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:

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)
burgholzer commented 23 hours ago

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 commented 8 hours ago

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>