def taper(self, operator: PauliSumOp) -> OperatorBase: """ Taper an operator based on the z2_symmetries info and sector defined by `tapering_values`. The `tapering_values` will be stored into the resulted operator for a record. Args: operator: the to-be-tapered operator. Returns: If tapering_values is None: [:class`PauliSumOp`]; otherwise, :class:`PauliSumOp` Raises: OpflowError: Z2 symmetries, single qubit pauli and single qubit list cannot be empty """ if not self._symmetries or not self._sq_paulis or not self._sq_list: raise OpflowError( "Z2 symmetries, single qubit pauli and " "single qubit list cannot be empty." ) if operator.is_zero(): logger.warning("The operator is empty, return the empty operator directly.") return operator for clifford in self.cliffords: operator = cast(PauliSumOp, clifford @ operator @ clifford) if self._tapering_values is None: tapered_ops_list = [ self._taper(operator, list(coeff)) for coeff in itertools.product([1, -1], repeat=len(self._sq_list)) ] tapered_ops: OperatorBase = ListOp(tapered_ops_list) else: tapered_ops = self._taper(operator, self._tapering_values) return tapered_ops
def taper(self, operator: PauliSumOp) -> OperatorBase: """ Taper an operator based on the z2_symmetries info and sector defined by `tapering_values`. The `tapering_values` will be stored into the resulted operator for a record. Args: operator: the to-be-tapered operator. Returns: If tapering_values is None: [:class`PauliSumOp`]; otherwise, :class:`PauliSumOp` Raises: OpflowError: Z2 symmetries, single qubit pauli and single qubit list cannot be empty """ if not self._symmetries or not self._sq_paulis or not self._sq_list: raise OpflowError( "Z2 symmetries, single qubit pauli and single qubit list cannot be empty." ) # If the operator is zero then we can skip the following. We still need to taper the # operator to reduce its size i.e. the number of qubits so for example 0*"IIII" could # taper to 0*"II" when symmetries remove two qubits. if not operator.is_zero(): for clifford in self.cliffords: operator = cast(PauliSumOp, clifford @ operator @ clifford) if self._tapering_values is None: tapered_ops_list = [ self._taper(operator, list(coeff)) for coeff in itertools.product([1, -1], repeat=len(self._sq_list)) ] tapered_ops: OperatorBase = ListOp(tapered_ops_list) else: tapered_ops = self._taper(operator, self._tapering_values) return tapered_ops