Skip to content

🐛 Fix ancillary handling in ZX checker #512

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

burgholzer
Copy link
Member

@burgholzer burgholzer commented Nov 25, 2024

Description

Fixes #508

The regression tests and the corresponding CI failures demonstrate the underlying issue in the ZX checkers:

  • the first C++ test, which previously segfaulted, now returns equivalent, while all other checkers agree that the two circuits are not equivalent.
  • the second C++ test is a full C++ reproducer of the failing Python test. This test segfaults due to a map out of range error.
  • the Python test is adapted from 🐛 Partial equivalence with ancillary qubits #508

Note the first two tests fail for separate reasons, which means there are multiple things going wrong here.

This PR adjusts the conditions under which the ZX checker declares it can handle the underlying circuits, making it more conservative than before.
Additionally, the out of range error is fixed.

Checklist:

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

@burgholzer burgholzer added c++ Anything related to C++ code fix Anything related to bugfixes labels Nov 25, 2024
pehamTom and others added 3 commits May 5, 2025 15:45
Disables ZX Checker when non-garbage ancillae are defined.
Copy link

codecov bot commented May 5, 2025

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Copy link
Member Author

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pehamTom many thanks for the changes here. I pushed a couple of commits with cleanups of unrelated changes and a small fix for an oversight in the new shortcut of the ZX Checker run method.

I only have two real questions left, which you will find inline.
Other than that, it would be nice if you could add a changelog entry for this fix.

Comment on lines +47 to 70
if (qc1->getNqubitsWithoutAncillae() == 0) {
miter = zx::ZXDiagram();
} else {
const auto numQubits1 = static_cast<zx::Qubit>(qc1->getNqubits());
for (zx::Qubit i = 0; i < static_cast<zx::Qubit>(qc1->getNancillae());
++i) {
const auto anc = numQubits1 - i - 1;
miter.makeAncilla(
anc, static_cast<zx::Qubit>(p1.at(static_cast<qc::Qubit>(anc))));
}
miter.invert();
}

if (qc2->getNqubitsWithoutAncillae() == 0) {
return;
}
const auto numQubits2 = static_cast<zx::Qubit>(qc2->getNqubits());
for (zx::Qubit i = 0; i < static_cast<zx::Qubit>(qc2->getNancillae()); ++i) {
const auto anc = numQubits2 - i - 1;
dPrime.makeAncilla(
anc, static_cast<zx::Qubit>(p2.at(static_cast<qc::Qubit>(anc))));
}
miter.invert();
miter.concat(dPrime);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand the reasoning behind this change.
Could you please clarify why adding ancillary qubits to the circuits isn't an option when they lack data qubits?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It became clear in our discussion, non-garbage ancillaries cannot be supported in the current version of the ZX checker. Since all garbage ancillaries are traced out, a lack of data qubits is equivalent to no operation at all.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A, fair enough. That make sense.
Would you mind adding some of that as an in-code comment? Otherwise, the next person looking at the code might wonder the same thing as I just did.

@@ -191,6 +191,7 @@ TEST_F(ZXTest, Ancilla) {
qc1.i(0);
qc2.cx(1, 0);
qc2.setLogicalQubitAncillary(1);
qc2.setLogicalQubitGarbage(1);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify, why this is needed now, but was not needed previously?
Before this PR, the test worked without this change.
Would it be too hard to continue supporting that?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a misunderstanding on my part on the role of ancillaries in mqt core. As discussed, the current state of the ZX checker cannot support non-garbage ancillaries. That this worked before was simply because every ancillary was treated as if it were garbage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Makes sense...
Do you think it would be worth it to add a dedicated option for the ZX Checker to simply treat all ancillaries as garbage?
I could imagine that many people would probably be using that option.

@burgholzer burgholzer marked this pull request as ready for review May 5, 2025 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Anything related to C++ code fix Anything related to bugfixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

🐛 Partial equivalence with ancillary qubits
2 participants