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

num_unique_paulis can falsely report to be 0 #21

Open
mrossinek opened this issue Oct 2, 2024 · 0 comments
Open

num_unique_paulis can falsely report to be 0 #21

mrossinek opened this issue Oct 2, 2024 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@mrossinek
Copy link
Member

Environment

  • qiskit-addon-obp version: 0.1.0
  • Python version: Any
  • Operating system: Any

What is happening and why is it wrong?

The num_unique_paulis field tracked by the metadata when operators are being simplified can falsely report to be 0.
This does not make any sense because it would imply an empty operator has occurred but we know for a fact that the smallest operator size is bound by 1 (when it gets reduced to an identity operator).

Credit to @BryceFuller for finding this!

How can we reproduce the issue?

from qiskit.circuit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp

from qiskit_addon_obp import backpropagate

op = SparsePauliOp.from_list([("ZI", 1)])

circ = QuantumCircuit(2)
circ.h(0)

_, _, metadata = backpropagate(op, [circ])

print(metadata.backpropagation_history[0].num_unique_paulis)  # [0]
print(len(new_op))  # 1

This will output 0 even though the obvious correct number of unique Pauli terms should be 1 (as shown by the second print line).

Traceback

No response

Any suggestions?

The reason that this occurs is the following: when none of the gates in a slice of the circuit overlap with the observable being backpropagated, the num_unique_paulis value never gets set to a correct value and, thus, remains to be its initialized value.

Specifically, the following lines have to always execute:

if not set(qargs_tmp[i]).intersection(op_qargs):
# we can skip this gate if it does not intersect with the local observable
continue

Resulting in the 0 remaining set from here:

num_unique_paulis=[0] * num_observables if operator_budget.simplify else None,


We have multiple solutions for how to fix this.

  1. Change the initialization of num_unique_paulis to be the following:

    num_unique_paulis=[len(op) for op in observables_tmp] if operator_budget.simplify else None,

    This will correctly initialize the num_unique_paulis with the current length of each observable.

  2. Add a check here whether num_unique_paulis is still zero and, if so, fix it at this point.

Personally, I find the first fix cleaner but it adds an additional loop over the observables (which should not be a problem).
The latter fix would be preferable if any of the other metadata fields also need to be handled specially, but looking at it now, those should all be correct when initialized with 0 (because num_paulis will always get updated correctly here).
But it won't hurt to double check whether this is indeed correct.

@caleb-johnson I will leave it up to you with which solution you will go 👍

@mrossinek mrossinek added the bug Something isn't working label Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants