From dd24a74cc80a5f73229ca3e37d85f9b3fd6afd50 Mon Sep 17 00:00:00 2001 From: Jinghong Yang <66985891+yjh-bill@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:40:30 -0500 Subject: [PATCH] Fix the calculation for identity operator's expectation value (#13345) * Fix the calculation for identity operator's expectation value * Add release note and test * reformatted `test_statevector.py` with black * Update releasenotes/notes/fix_identity_operator_9e2ec9770ac046a6.yaml Co-authored-by: Julien Gacon * add a docstring to pass the pylint test * Fix leading `.` --------- Co-authored-by: Julien Gacon (cherry picked from commit edad499f9a9bcc7d4ae8a33624861d9d277e55a4) --- qiskit/quantum_info/states/statevector.py | 2 +- ...ix_identity_operator_9e2ec9770ac046a6.yaml | 5 ++++ .../quantum_info/states/test_statevector.py | 25 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix_identity_operator_9e2ec9770ac046a6.yaml diff --git a/qiskit/quantum_info/states/statevector.py b/qiskit/quantum_info/states/statevector.py index 901ce95af424..1265d677abe4 100644 --- a/qiskit/quantum_info/states/statevector.py +++ b/qiskit/quantum_info/states/statevector.py @@ -476,7 +476,7 @@ def _expectation_value_pauli(self, pauli, qargs=None): pauli_phase = (-1j) ** pauli.phase if pauli.phase else 1 if x_mask + z_mask == 0: - return pauli_phase * np.linalg.norm(self.data) + return pauli_phase * np.linalg.norm(self.data) ** 2 if x_mask == 0: return pauli_phase * expval_pauli_no_x(self.data, self.num_qubits, z_mask) diff --git a/releasenotes/notes/fix_identity_operator_9e2ec9770ac046a6.yaml b/releasenotes/notes/fix_identity_operator_9e2ec9770ac046a6.yaml new file mode 100644 index 000000000000..69779a793cc3 --- /dev/null +++ b/releasenotes/notes/fix_identity_operator_9e2ec9770ac046a6.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixed a bug that caused :meth:`.Statevector.expectation_value` to yield incorrect results + for the identity operator when the statevector was not normalized. diff --git a/test/python/quantum_info/states/test_statevector.py b/test/python/quantum_info/states/test_statevector.py index 29d5d42f3783..d16b3b3453ec 100644 --- a/test/python/quantum_info/states/test_statevector.py +++ b/test/python/quantum_info/states/test_statevector.py @@ -1152,6 +1152,31 @@ def test_expval_pauli_qargs(self, qubits): expval = state.expectation_value(op, qubits) self.assertAlmostEqual(expval, target) + def test_expval_identity(self): + """Test whether the calculation for identity operator has been fixed""" + + # 1 qubit case test + state_1 = Statevector.from_label("0") + state_1_n1 = 2 * state_1 # test the same state with different norms + state_1_n2 = (1 + 2j) * state_1 + identity_op_1 = SparsePauliOp.from_list([("I", 1)]) + expval_state_1 = state_1.expectation_value(identity_op_1) + expval_state_1_n1 = state_1_n1.expectation_value(identity_op_1) + expval_state_1_n2 = state_1_n2.expectation_value(identity_op_1) + self.assertAlmostEqual(expval_state_1, 1.0 + 0j) + self.assertAlmostEqual(expval_state_1_n1, 4 + 0j) + self.assertAlmostEqual(expval_state_1_n2, 5 + 0j) + + # Let's try a multi-qubit case + n_qubits = 3 + state_coeff = 3 - 4j + op_coeff = 2 - 2j + state_test = state_coeff * Statevector.from_label("0" * n_qubits) + op_test = SparsePauliOp.from_list([("I" * n_qubits, op_coeff)]) + expval = state_test.expectation_value(op_test) + target = op_coeff * np.abs(state_coeff) ** 2 + self.assertAlmostEqual(expval, target) + @data(*(qargs for i in range(4) for qargs in permutations(range(4), r=i + 1))) def test_probabilities_qargs(self, qargs): """Test probabilities method with qargs"""