"""This module provides functionality for computing the matrix exponential of Pauli operators.It supports both single-term Pauli operators and reflective operators, enabling efficientgeneration of exponential matrix representations for use in quantum computing.Functions included:- single_pauli_expm: Computes the exponential of a single Pauli operator.- reflective_pauli_expm: Efficiently computes the exponential of reflective Pauli operators."""fromtypingimportOptionalimportnumpyasnpfromopenfermionimportQubitOperator,count_qubits,get_sparse_operatorfromscipy.sparseimportspmatrix,identityfromofex.operators.symbolic_operator_toolsimportis_constant__all__=["single_pauli_expm","reflective_pauli_expm"]
[docs]defsingle_pauli_expm(pauli:QubitOperator,n_qubits:Optional[int]=None)->spmatrix:""" Compute the exponential of a single Pauli operator. This function generates the matrix representation of `exp(pauli)` for a given single-term Pauli operator expressed as a `QubitOperator`. Args: pauli (QubitOperator): A single-term QubitOperator representing the Pauli operator. n_qubits (Optional[int]): The number of qubits in the system. If not specified, the number of qubits is inferred from the operator. Returns: spmatrix: A sparse matrix representing the exponential of the given Pauli operator. Raises: ValueError: If the number of qubits specified is invalid or if the operator contains more than one term. """ifn_qubitsisNone:n_qubits=count_qubits(pauli)ifn_qubits<count_qubits(pauli):raiseValueError('Invalid number of qubits specified.')iflen(pauli.terms)!=1:raiseValueError('Invalid number of terms.')returnreflective_pauli_expm(pauli,n_qubits,check_reflective=False)
[docs]defreflective_pauli_expm(pauli:QubitOperator,n_qubits:Optional[int]=None,check_reflective:bool=True)->spmatrix:""" Compute the exponential of reflective qubit operator efficiently. This function generates the matrix representation of `exp(pauli)` for a given Pauli operator, under the assumption that the operator is reflective (i.e., the square of the operator is constant). For example, a sum of mutually anti-commuting Pauli operators or an LCU-fragment is reflective. The exponential of a reflective operator can be computed efficiently. Args: pauli (QubitOperator): The operator for which the exponential is to be calculated. n_qubits (Optional[int]): The number of qubits in the system. If not specified, the number of qubits is inferred from the operator. check_reflective (bool): Whether to validate that the operator is reflective. Set to False to bypass this validation. Returns: spmatrix: A sparse matrix representing the exponential of the given Pauli operator. Raises: ValueError: If the number of qubits specified is invalid or if the operator is not reflective when `check_reflective` is True. """ifn_qubitsisNone:n_qubits=count_qubits(pauli)ifn_qubits<count_qubits(pauli):raiseValueError('Invalid number of qubits specified.')ifcheck_reflective:sq_pauli=pauli*pauliifnotis_constant(sq_pauli):raiseValueError("Not a reflective Pauli operator.")beta=np.emath.sqrt(sum([v**2forvinpauli.terms.values()]))c_re,c_im=beta.real,beta.imagmat=get_sparse_operator(pauli/beta,n_qubits)i_mat=identity(mat.shape[0],format=mat.format)ret=(np.cosh(c_re)*np.cos(c_im)+1j*np.sinh(c_re)*np.sin(c_im))*i_matret+=(np.sinh(c_re)*np.cos(c_im)+1j*np.cosh(c_re)*np.sin(c_im))*matreturnret