def measure_single_paulistring( pauli_observable: pauli_string.PauliString, key: Optional[Union[str, 'cirq.MeasurementKey']] = None, ) -> raw_types.Operation: """Returns a single PauliMeasurementGate which measures the pauli observable Args: pauli_observable: The `cirq.PauliString` observable to measure. key: Optional `str` or `cirq.MeasurementKey` that gate should use. If none provided, it defaults to a comma-separated list of `str(qubit)` for each of the target qubits. Returns: An operation measuring the pauli observable. Raises: ValueError: if the observable is not an instance of PauliString or if the coefficient is not +1. """ if not isinstance(pauli_observable, pauli_string.PauliString): raise ValueError( f'Pauli observable {pauli_observable} should be an instance of cirq.PauliString.' ) if pauli_observable.coefficient != 1: raise ValueError(f"Pauli observable {pauli_observable} must have a coefficient of +1.") if key is None: key = _default_measurement_key(pauli_observable) return PauliMeasurementGate(pauli_observable.values(), key).on(*pauli_observable.keys())
def _mul_with_qubits(self, qubits: Tuple['cirq.Qid', ...], other): if isinstance(other, raw_types.Operation): return other if isinstance(other, (complex, float, int)): from cirq.ops.pauli_string import PauliString return PauliString(coefficient=other) return NotImplemented
def __init__( self, pauli_string: ps.PauliString, *, exponent_neg: Union[int, float, sympy.Expr] = 1, exponent_pos: Union[int, float, sympy.Expr] = 0, ) -> None: """Initializes the operation. Args: pauli_string: The PauliString defining the positive and negative eigenspaces that will be independently phased. exponent_neg: How much to phase vectors in the negative eigenspace, in the form of the t in (-1)**t = exp(i pi t). exponent_pos: How much to phase vectors in the positive eigenspace, in the form of the t in (-1)**t = exp(i pi t). Raises: ValueError: If coefficient is not 1 or -1. """ gate = PauliStringPhasorGate( pauli_string.dense(pauli_string.qubits), exponent_neg=exponent_neg, exponent_pos=exponent_pos, ) super().__init__(gate, pauli_string.qubits) self._pauli_string = gate.dense_pauli_string.on(*self.qubits)
def pauli_string_to_z_ops( pauli_string: PauliString) -> Iterable[ops.Operation]: """Yields the single qubit operations to apply before a Pauli string of Zs (and apply the inverse of these operations after) to make it equivalent to the given pauli_string.""" for qubit, pauli in pauli_string.items(): yield CliffordGate.from_single_map({pauli: (Pauli.Z, False)})(qubit)
def __add__(self, other): if not isinstance(other, (numbers.Complex, PauliString, PauliSum)): if hasattr(other, 'gate') and isinstance(other.gate, identity.IdentityGate): other = PauliString(other) else: return NotImplemented result = self.copy() result += other return result
def __isub__(self, other): if isinstance(other, numbers.Complex): other = PauliSum.from_pauli_strings([PauliString(coefficient=other)]) if isinstance(other, PauliString): other = PauliSum.from_pauli_strings([other]) if not isinstance(other, PauliSum): return NotImplemented self._linear_dict -= other._linear_dict return self
def __iadd__(self, other): if isinstance(other, (float, int, complex)): other = PauliSum.from_pauli_strings( [PauliString(coefficient=other)]) elif isinstance(other, PauliString): other = PauliSum.from_pauli_strings([other]) if not isinstance(other, PauliSum): return NotImplemented self._linear_dict += other._linear_dict return self
def __init__( self, pauli_string: ps.PauliString, qubits: Optional[Sequence['cirq.Qid']] = None, *, exponent_neg: Union[int, float, sympy.Expr] = 1, exponent_pos: Union[int, float, sympy.Expr] = 0, ) -> None: """Initializes the operation. Args: pauli_string: The PauliString defining the positive and negative eigenspaces that will be independently phased. qubits: The qubits upon which the PauliStringPhasor acts. This must be a superset of the qubits of `pauli_string`. If None, it will use the qubits from `pauli_string` The `pauli_string` contains only the non-identity component of the phasor, while the qubits supplied here and not in `pauli_string` are acted upon by identity. The order of these qubits must match the order in `pauli_string`. exponent_neg: How much to phase vectors in the negative eigenspace, in the form of the t in (-1)**t = exp(i pi t). exponent_pos: How much to phase vectors in the positive eigenspace, in the form of the t in (-1)**t = exp(i pi t). Raises: ValueError: If coefficient is not 1 or -1 or the qubits of `pauli_string` are not a subset of `qubits`. """ if qubits is not None: it = iter(qubits) if any(not any(q0 == q1 for q1 in it) for q0 in pauli_string.qubits): raise ValueError( f"PauliStringPhasor's pauli string qubits ({pauli_string.qubits}) " f"are not an ordered subset of the explicit qubits ({qubits})." ) else: qubits = pauli_string.qubits # Use qubits below instead of `qubits or pauli_string.qubits` gate = PauliStringPhasorGate(pauli_string.dense(qubits), exponent_neg=exponent_neg, exponent_pos=exponent_pos) super().__init__(gate, qubits) self._pauli_string = gate.dense_pauli_string.on(*self.qubits)
def from_boolean_expression( cls, boolean_expr: Expr, qubit_map: Dict[str, 'cirq.Qid']) -> 'PauliSum': """Builds the Hamiltonian representation of a Boolean expression. This is based on "On the representation of Boolean and real functions as Hamiltonians for quantum computing" by Stuart Hadfield, https://arxiv.org/abs/1804.09130 Args: boolean_expr: A Sympy expression containing symbols and Boolean operations qubit_map: map of string (boolean variable name) to qubit. Return: The PauliString that represents the Boolean expression. Raises: ValueError: If `boolean_expr` is of an unsupported type. """ if isinstance(boolean_expr, Symbol): # In table 1, the entry for 'x' is '1/2.I - 1/2.Z' return cls.from_pauli_strings([ PauliString({}, 0.5), PauliString({qubit_map[boolean_expr.name]: pauli_gates.Z}, -0.5), ]) if isinstance(boolean_expr, (And, Not, Or, Xor)): sub_pauli_sums = [ cls.from_boolean_expression(sub_boolean_expr, qubit_map) for sub_boolean_expr in boolean_expr.args ] # We apply the equalities of theorem 1. if isinstance(boolean_expr, And): pauli_sum = cls.from_pauli_strings(PauliString({}, 1.0)) for sub_pauli_sum in sub_pauli_sums: pauli_sum = pauli_sum * sub_pauli_sum elif isinstance(boolean_expr, Not): assert len(sub_pauli_sums) == 1 pauli_sum = cls.from_pauli_strings(PauliString( {}, 1.0)) - sub_pauli_sums[0] elif isinstance(boolean_expr, Or): pauli_sum = cls.from_pauli_strings(PauliString({}, 0.0)) for sub_pauli_sum in sub_pauli_sums: pauli_sum = pauli_sum + sub_pauli_sum - pauli_sum * sub_pauli_sum elif isinstance(boolean_expr, Xor): pauli_sum = cls.from_pauli_strings(PauliString({}, 0.0)) for sub_pauli_sum in sub_pauli_sums: pauli_sum = pauli_sum + sub_pauli_sum - 2.0 * pauli_sum * sub_pauli_sum return pauli_sum raise ValueError(f'Unsupported type: {type(boolean_expr)}')
def _pauli_string_from_unit(unit: UnitPauliStringT, coefficient: Union[int, float, complex] = 1): return PauliString(qubit_pauli_map=dict(unit), coefficient=coefficient)