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

Different behaviour with and without barriers #439

Open
ritu-thombre99 opened this issue Aug 11, 2024 · 1 comment
Open

Different behaviour with and without barriers #439

ritu-thombre99 opened this issue Aug 11, 2024 · 1 comment
Labels
bug Something isn't working c++ Anything related to C++ code

Comments

@ritu-thombre99
Copy link

ritu-thombre99 commented Aug 11, 2024

Environment information

OS: MacOS
MQT version: 2.6.0
Compiler: C++

Description

This is related to the earlier issue 424

I'm trying to run a circuit equivalence check for two particular circuits (Steane code).
The segmentation fault was fixed by removing measurements of two qubits onto the same clbit.

But now, when I run the code with Barriers, it runs properly (the result being non_equivalent)
However, when I run it after removing all the barriers I get the following error:

ValueError                                Traceback (most recent call last)
Cell In[204], line 3
      1 from mqt import qcec
      2 from qiskit import qasm2
----> 3 result = qcec.verify(qc1, qc2,
      4                      transform_dynamic_circuit=True,
      5                      backpropagate_output_permutation=True,
      6                      fix_output_permutation_mismatch=True,
      7                     )
      9 print(result.equivalence)

File /opt/anaconda3/envs/smt_compiler/lib/python3.11/site-packages/mqt/qcec/verify.py:59, in verify(circ1, circ2, configuration, **kwargs)
     56 ecm = EquivalenceCheckingManager(circ1, circ2, configuration)
     58 # execute the check
---> 59 ecm.run()
     61 # obtain the result
     62 return ecm.get_results()

ValueError: DD for non-unitary operation not available!

Circuit 1:

from qiskit import QuantumCircuit, qasm3, transpile, qasm2
import numpy as np
from qiskit.transpiler.passes import RemoveBarriers

qc1 = QuantumCircuit(10, 3)

qc1.x(5)
qc1.cx(0, 7)
qc1.cx(2, 7)
qc1.cx(4, 7)
qc1.cx(6, 7)


qc1.cx(1, 8)
qc1.cx(2, 8)
qc1.cx(5, 8)
qc1.cx(6, 8)

qc1.cx(3, 9)
qc1.cx(4, 9)
qc1.cx(5, 9)
qc1.cx(6, 9)


qc1.measure([7, 8, 9], [0, 1, 2])

qc1.draw('mpl')

image

Circuit 2:

output = """OPENQASM 3.0;
include "stdgates.inc";
bit[3] c;
qubit[15] q;
cx q[0], q[1];
cx q[4], q[5];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[5];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[1];
cx q[5], q[8];
cx q[10], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[3];
cx q[8], q[5];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[3], q[2];
cx q[5], q[8];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[3];
cx q[7], q[8];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
rx(pi) q[2];
cx q[3], q[11];
cx q[5], q[8];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[1];
cx q[8], q[9];
cx q[11], q[3];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[5];
cx q[3], q[11];
cx q[9], q[8];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[3], q[11];
cx q[5], q[2];
cx q[8], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[5];
cx q[7], q[8];
cx q[9], q[10];
cx q[11], q[3];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[2], q[1];
cx q[3], q[11];
cx q[5], q[8];
cx q[10], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[0], q[1];
cx q[2], q[5];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[1], q[0];
cx q[5], q[2];
c[0] = measure q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[0], q[1];
cx q[2], q[5];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[5], q[8];
c[1] = measure q[0];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[4], q[5];
cx q[8], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[5], q[4];
cx q[9], q[8];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[4], q[5];
cx q[8], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[10], q[9];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
cx q[9], q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
c[2] = measure q[10];
barrier q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13], q[14];
"""

qc2 = qasm3.loads(output)
# qc2 = RemoveBarriers()(qc2) # to remove the barriers
qc2.draw('mpl')

Circuit 2 without barriers:
image
Output: ValueError: DD for non-unitary operation not available!

Circuit 2 with barriers:
image
Output: not_equivalent

Expected behavior

Not equivalent even when running the code with circuits that do not have barriers

How to Reproduce

Import qiskit, mqt.qcec and the run the code blocks mentioned above.

@burgholzer burgholzer added bug Something isn't working c++ Anything related to C++ code labels Aug 22, 2024
@burgholzer
Copy link
Member

I can confirm that this is a bug in how we eliminate measurements at the end of the circuit before we perform the equivalence check.
The barriers after the measurements in the circuit prevent the optimiser to remove the measurements and the equivalence checker, then, can't handle them.

This should be a pretty easy fix here: https://github.com/cda-tum/mqt-core/blob/5be1c3ec4efb773d0330298621704e876afa7c16/src/circuit_optimizer/CircuitOptimizer.cpp#L468-L570

On vacation right now, but can look at that once I am back.
Maybe @pehamTom has some time until then?

burgholzer added a commit to cda-tum/mqt-core that referenced this issue Sep 9, 2024
## Description

The previous implementation of the `isDynamicCircuit` check would
falsely report a circuit to not be dynamic if the circuit contains
multiple measurements on one qubit.
This PR fixes the underlying error and refactors the logic of the
respective method to handle more cases.

This was discovered while working on
cda-tum/mqt-qcec#439

## Checklist:

<!---
This checklist serves as a reminder of a couple of things that ensure
your pull request will be merged swiftly.
-->

- [x] The pull request only contains commits that are related to it.
- [x] I have added appropriate tests and documentation.
- [x] I have made sure that all CI jobs on GitHub pass.
- [x] The pull request introduces no new warnings and follows the
project's style guidelines.

---------

Signed-off-by: burgholzer <burgholzer@me.com>
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: Todo
Status: Todo
Development

No branches or pull requests

2 participants