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

Operator equality with (clean) ancillas #12968

Merged
merged 3 commits into from
Aug 22, 2024

Conversation

alexanderivrii
Copy link
Contributor

Summary

This PR adds a new method equal_with_ancillas to the Operator class that checks whether the two operators are equal in the subspace where the ancilla qubits are zero.

While this is not immediately required for #12961 and #12911, it allows to check correctness of various synthesis methods and transformations in the presence of clean ancilla qubits. (The dirty ancilla qubits should be interpreted as regular qubits and don't matter).

Details and comments

Many thanks to @ShellyGarion for the idea how to implement this in a simple way.

Here is an example (which also appears in the release notes):

qc1 = QuantumCircuit(4)
qc1.x(0)
qc1.x(2)
qc1.cx(1, 0)
qc1.cx(1, 2)
qc1.cx(1, 3)
op1 = Operator(qc1)

qc2 = QuantumCircuit(4)
qc2.x(0)
qc2.x(2)
op2 = Operator(qc2)

assert op1 != op2
assert op1.equal_with_ancillas(op2, [1])

The first assertion checks that the two circuits are not equal, and they are not -- due to the CX gates from qubit 1 to other qubits. However, the two circuits are equal if qubit 1 is initially zero, then the CX gates do not matter.

@alexanderivrii alexanderivrii requested a review from a team as a code owner August 16, 2024 11:31
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core

@alexanderivrii alexanderivrii added the mod: quantum info Related to the Quantum Info module (States & Operators) label Aug 16, 2024
@alexanderivrii alexanderivrii added this to the 1.3 beta milestone Aug 16, 2024
@coveralls
Copy link

coveralls commented Aug 16, 2024

Pull Request Test Coverage Report for Build 10471646092

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 24 of 25 (96.0%) changed or added relevant lines in 1 file are covered.
  • 31 unchanged lines in 5 files lost coverage.
  • Overall coverage increased (+0.009%) to 89.596%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/quantum_info/operators/operator_utils.py 24 25 96.0%
Files with Coverage Reduction New Missed Lines %
qiskit/circuit/library/basis_change/qft.py 1 90.43%
crates/qasm2/src/lex.rs 3 92.73%
qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py 4 91.76%
crates/qasm2/src/parse.rs 6 97.61%
qiskit/quantum_info/operators/operator.py 17 94.34%
Totals Coverage Status
Change from base Build 10408599020: 0.009%
Covered Lines: 67633
Relevant Lines: 75487

💛 - Coveralls

@alexanderivrii
Copy link
Contributor Author

As @Cryoris suggested offline, it is better to make this function private for now. So I have prefixed it with the underscore and removed the lovingly-created release notes.

ancilla_qubits: a list of clean ancilla qubits.
rtol (float): relative tolerance value for comparison.
atol (float): absolute tolerance value for comparison.
ignore_phase (bool): ignore complex-phase difference between matrices.
Copy link
Contributor

Choose a reason for hiding this comment

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

Change the order to match the actual args order

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, done in 4de623a.

ignore_phase (bool): ignore complex-phase difference between matrices.

Returns:
bool: True if operators are equal up to clean ancilla qubits.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
bool: True if operators are equal up to clean ancilla qubits.
bool: True iff operators are equal up to clean ancilla qubits.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 4de623a.

def _equal_with_ancillas(
self,
other: Operator,
ancilla_qubits: list,
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe List[int] instead of list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 4de623a (well, list[int], which I believe is now a bit more preferred).

Returns:
bool: True if operators are equal up to clean ancilla qubits.
"""
if self.dim != other.dim:
Copy link
Contributor

Choose a reason for hiding this comment

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

Add type checking on other similarly to how it's done in equiv()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The equiv code does more than just type-checking: if converts other to an Operator when it's not already, so for example one can check the equivalence of an Operator and a QuantumCircuit. I don't think this fully makes sense for this (currently private) function.

for q in range(num_qubits):
if q in ancilla_qubits:
pattern[pos] = q
pos += 1
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be a nitpicking, but I disliked the loop duplication up to the if condition ...
So to alleviate this and hopefully also improve readability, consider something like this:

        pattern = []
        ancillas = []
        for q in range(num_qubits):
            if q in ancilla_qubits:
                ancillas.append(q)
            else:
                pattern.append(q)
        pattern += ancillas

Copy link
Contributor Author

@alexanderivrii alexanderivrii Aug 20, 2024

Choose a reason for hiding this comment

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

That's a great suggestion, done in 4de623a.

@alexanderivrii
Copy link
Contributor Author

Thanks @Cryoris and @eliarbel for the reviews!

I haven't fully understood Julien's comment the first time: as the new function is not yet used anywhere in the main Qiskit code, for now it's better to make it a private function and not have it in operator.py. This is now done in 4de623a. I have created a special file operator_utils.py for this function since no other place seemed suitable: the utils directory contains some high-level utilities (commutator, anti-commutator), the predicates.py is used by the Operator class while the new function uses the Operator class, etc.

Eli, I have addressed your review comments in 4de623a.

Copy link
Contributor

@eliarbel eliarbel left a comment

Choose a reason for hiding this comment

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

LGTM

I approve for merge, though I'm not 100% happy with adding a new file ('operator_utils.py') just for this, knowing that there is a chance that '_equiv_with_ancillas' would become public and even part of Operator. Since there are already _ methods in Operator, roughly in the same vein like _multiply and _add I would prefer to keep '_equiv_with_ancillas' in Operator and spare an additional new file in the module.

@Cryoris
Copy link
Contributor

Cryoris commented Aug 22, 2024

_multiply and _add are used in overloading the __rmult__ and __add__ operations on the public interface, but the ancilla equality wouldn't be connected to a user-facing API 🙂

@Cryoris Cryoris added the Changelog: None Do not include in changelog label Aug 22, 2024
@Cryoris Cryoris added this pull request to the merge queue Aug 22, 2024
Merged via the queue into Qiskit:main with commit fb81116 Aug 22, 2024
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: None Do not include in changelog mod: quantum info Related to the Quantum Info module (States & Operators)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants