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

Statevector._expectation_value_pauli returns incorrect result in certain cases #13029

Closed
yjh-bill opened this issue Aug 23, 2024 · 4 comments · Fixed by #13345
Closed

Statevector._expectation_value_pauli returns incorrect result in certain cases #13029

yjh-bill opened this issue Aug 23, 2024 · 4 comments · Fixed by #13345

Comments

@yjh-bill
Copy link
Contributor

yjh-bill commented Aug 23, 2024

The calculation for the expectation value of the identity operator seems incorrect when the statevector is not normalized to 1.

I think the reason is that one should use the norm squared rather than the norm in the following lines.

if x_mask + z_mask == 0:
return pauli_phase * np.linalg.norm(self.data)


The whole function is attached below to provide context.

def _expectation_value_pauli(self, pauli, qargs=None):
"""Compute the expectation value of a Pauli.
Args:
pauli (Pauli): a Pauli operator to evaluate expval of.
qargs (None or list): subsystems to apply operator on.
Returns:
complex: the expectation value.
"""
n_pauli = len(pauli)
if qargs is None:
qubits = np.arange(n_pauli)
else:
qubits = np.array(qargs)
x_mask = np.dot(1 << qubits, pauli.x)
z_mask = np.dot(1 << qubits, pauli.z)
pauli_phase = (-1j) ** pauli.phase if pauli.phase else 1
if x_mask + z_mask == 0:
return pauli_phase * np.linalg.norm(self.data)
if x_mask == 0:
return pauli_phase * expval_pauli_no_x(self.data, self.num_qubits, z_mask)
x_max = qubits[pauli.x][-1]
y_phase = (-1j) ** pauli._count_y()
y_phase = y_phase[0]
return pauli_phase * expval_pauli_with_x(
self.data, self.num_qubits, z_mask, x_mask, y_phase, x_max
)

@jakelishman
Copy link
Member

Please can you show a reproducing code block following the bug report template, and the output you expected?

@yjh-bill
Copy link
Contributor Author

Sure. Here it is

from qiskit.quantum_info import Statevector, SparsePauliOp, Pauli

state_normed = Statevector.from_label("0")
state_not_normed = 2 * state_normed

identity_op = SparsePauliOp.from_list([("I", 1)])

# using the public interface (expectation_value)
print(state_not_normed.expectation_value(identity_op))

# using _expectation_value_pauli (the backend)
print(state_not_normed._expectation_value_pauli(Pauli('I')))

Environment

Python 3.11.6
qiskit 0.45.3

Judging from the source code on github, the issue should be platform-independent and exists across different versions.

What is the expected result

The two print statement should give 4+0j and 4.0 respectively.

What is the actual result

The two print statement gave 2+0j and 2.0 respectively.

@Cryoris
Copy link
Contributor

Cryoris commented Oct 17, 2024

Nice catch, that seems to be unique only to the Pauli-I operator. Would you like to open a PR to fix the issue? 🙂

@yjh-bill
Copy link
Contributor Author

Sure, I have created one PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants