Esempio n. 1
0
    def expectation_from_wavefunction(self,
                                      state: np.ndarray,
                                      qubit_map: Mapping[raw_types.Qid, int],
                                      atol: float = 1e-7) -> float:
        r"""Evaluate the expectation of this PauliString given a wavefunction.

        Compute the expectation value of this PauliString with respect to a
        wavefunction. By convention expectation values are defined for Hermitian
        operators, and so this method will fail if this PauliString is
        non-Hermitian.

        `state` must be an array representation of a wavefunction and have
        shape `(2 ** n, )` or `(2, 2, ..., 2)` (n entries) where `state` is
        expressed over n qubits.

        `qubit_map` must assign an integer index to each qubit in this
        PauliString that determines which bit position of a computational basis
        state that qubit corresponds to. For example if `state` represents
        $|0\rangle |+\rangle$ and `q0, q1 = cirq.LineQubit.range(2)` then:

            cirq.X(q0).expectation(state, qubit_map={q0: 0, q1: 1}) = 0
            cirq.X(q0).expectation(state, qubit_map={q0: 1, q1: 0}) = 1

        Args:
            state: An array representing a valid wavefunction.
            qubit_map: A map from all qubits used in this PauliString to the
            indices of the qubits that `state` is defined over.

        Returns:
            The expectation value of the input state.

        Raises:
            NotImplementedError if this PauliString is non-Hermitian.
        """
        if abs(self.coefficient.imag) > 0.0001:
            raise NotImplementedError(
                "Cannot compute expectation value of a non-Hermitian "
                "PauliString <{}>. Coefficient must be real.".format(self))

        # FIXME: Avoid enforce specific complex type. This is necessary to
        # prevent an `apply_unitary` bug (Issue #2041).
        if state.dtype.kind != 'c':
            raise TypeError("Input state dtype must be np.complex64 or "
                            "np.complex128")

        size = state.size
        num_qubits = size.bit_length() - 1
        if len(state.shape) != 1 and state.shape != (2,) * num_qubits:
            raise ValueError("Input array does not represent a wavefunction "
                             "with shape `(2 ** n,)` or `(2, ..., 2)`.")

        _validate_qubit_mapping(qubit_map, self.qubits, num_qubits)
        # HACK: avoid circular import
        from cirq.sim.wave_function import validate_normalized_state
        validate_normalized_state(state=state,
                                  qid_shape=(2,) * num_qubits,
                                  dtype=state.dtype,
                                  atol=atol)
        return self._expectation_from_wavefunction_no_validation(
            state, qubit_map)
Esempio n. 2
0
    def expectation_from_wavefunction(
            self,
            state: np.ndarray,
            qubit_map: Mapping[raw_types.Qid, int],
            *,
            atol: float = 1e-7,
            check_preconditions: bool = True) -> float:
        """Evaluate the expectation of this PauliSum given a wavefunction.

        See `PauliString.expectation_from_wavefunction`.

        Args:
            state: An array representing a valid wavefunction.
            qubit_map: A map from all qubits used in this PauliSum to the
                indices of the qubits that `state` is defined over.
            atol: Absolute numerical tolerance.
            check_preconditions: Whether to check that `state` represents a
                valid wavefunction.

        Returns:
            The expectation value of the input state.
        """
        if any(abs(p.coefficient.imag) > 0.0001 for p in self):
            raise NotImplementedError(
                "Cannot compute expectation value of a non-Hermitian "
                "PauliString <{}>. Coefficient must be real.".format(self))

        # FIXME: Avoid enforce specific complex type. This is necessary to
        # prevent an `apply_unitary` bug (Issue #2041).
        if state.dtype.kind != 'c':
            raise TypeError("Input state dtype must be np.complex64 or "
                            "np.complex128")

        size = state.size
        num_qubits = size.bit_length() - 1
        _validate_qubit_mapping(qubit_map, self.qubits, num_qubits)

        if len(state.shape) != 1 and state.shape != (2, ) * num_qubits:
            raise ValueError("Input array does not represent a wavefunction "
                             "with shape `(2 ** n,)` or `(2, ..., 2)`.")

        if check_preconditions:
            # HACK: avoid circular import
            from cirq.sim.wave_function import validate_normalized_state
            validate_normalized_state(state=state,
                                      qid_shape=(2, ) * num_qubits,
                                      dtype=state.dtype,
                                      atol=atol)
        return sum(
            p._expectation_from_wavefunction_no_validation(state, qubit_map)
            for p in self)