Source code for qiskit_addon_cutting.utils.observable_terms
# This code is a Qiskit project.# (C) Copyright IBM 2024.# This code is licensed under the Apache License, Version 2.0. You may# obtain a copy of this license in the LICENSE.txt file in the root directory# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.# Any modifications or derivative works of this code must retain this# copyright notice, and modified files need to carry a notice indicating# that they have been altered from the originals.# Reminder: update the RST file in docs/apidocs when adding new interfaces.r"""Utilities for working with the unique terms of a collection of :class:`~qiskit.quantum_info.SparsePauliOp`\ s."""from__future__importannotationsfromtypingimportSequence,Iterable,Mappingfromqiskit.quantum_infoimportPauli,PauliList,SparsePauliOpfrom.iterationimportstrict_zip
[docs]defgather_unique_observable_terms(observables:Sequence[Pauli|SparsePauliOp]|PauliList,)->PauliList:"""Inspect the contents of each observable to find and return the unique Pauli terms."""ifnotobservables:ifisinstance(observables,PauliList):returnobservables.copy()raiseValueError("observables list cannot be empty")pauli_list:list[Pauli]=[]pauli_set:set[Pauli]=set()forobservableinobservables:ifisinstance(observable,Pauli):observable=SparsePauliOp(observable)forpauli,coeffinstrict_zip(observable.paulis,observable.coeffs):assertpauli.phase==0# SparsePauliOp should do this for usifcoeff==0:continueifpaulinotinpauli_set:pauli_list.append(pauli)pauli_set.add(pauli)ifnotpauli_list:# Handle this special case, which can happen if all coeffs are zero.# We create an empty PauliList with the correct number of qubits. See# https://github.com/Qiskit/qiskit/pull/9770 for a proposal to make# this simpler in Qiskit.returnPauliList(["I"*observables[0].num_qubits])[:0]try:returnPauliList(pauli_list)exceptValueErrorasex:raiseValueError("Cannot construct PauliList. Do provided observables all have ""the same number of qubits?")fromex
def_reconstruct_observable_expval_from_terms(observable:Pauli|SparsePauliOp,term_expvals:Mapping[Pauli,float|complex],)->complex:ifisinstance(observable,Pauli):observable=SparsePauliOp(observable)rv=0.0jforpauli,coeffinstrict_zip(observable.paulis,observable.coeffs):assertpauli.phase==0# SparsePauliOp should do this for usifcoeff==0:continuetry:term_expval=term_expvals[pauli]exceptKeyErrorasex:raiseValueError("An observable contains a Pauli term whose expectation value ""was not provided.")fromexrv+=coeff*term_expvalreturnrv
[docs]defreconstruct_observable_expvals_from_terms(observables:Iterable[Pauli|SparsePauliOp]|PauliList,term_expvals:Mapping[Pauli,float|complex],)->list[complex]:"""Reconstruct the expectation values given the expectation value of each unique term."""return[_reconstruct_observable_expval_from_terms(observable,term_expvals)forobservableinobservables]