예제 #1
0
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())
예제 #2
0
 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
예제 #3
0
    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)
예제 #4
0
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)
예제 #5
0
 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
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
    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)
예제 #9
0
    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)}')
예제 #10
0
def _pauli_string_from_unit(unit: UnitPauliStringT,
                            coefficient: Union[int, float, complex] = 1):
    return PauliString(qubit_pauli_map=dict(unit), coefficient=coefficient)