Esempio n. 1
0
    def expectation_from_state_vector(
        self,
        state_vector: 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 state vector.

        See `PauliString.expectation_from_state_vector`.

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

        Returns:
            The expectation value of the input state.

        Raises:
            NotImplementedError: If any of the coefficients are imaginary,
                so that this is not Hermitian.
            TypeError: If the input state is not a complex type.
            ValueError: If the input vector is not the correct size or shape.
        """
        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))

        # TODO: Avoid enforce specific complex type. This is necessary to
        # prevent an `apply_unitary` bug.
        # Github issue: https://github.com/quantumlib/Cirq/issues/2041
        if state_vector.dtype.kind != 'c':
            raise TypeError(
                "Input state dtype must be np.complex64 or np.complex128")

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

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

        if check_preconditions:
            qis.validate_normalized_state_vector(
                state_vector=state_vector,
                qid_shape=(2, ) * num_qubits,
                dtype=state_vector.dtype,
                atol=atol,
            )
        return sum(
            p._expectation_from_state_vector_no_validation(
                state_vector, qubit_map) for p in self)
Esempio n. 2
0
    def expectation_from_density_matrix(
        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 density matrix.

        See `PauliString.expectation_from_density_matrix`.

        Args:
            state: An array representing a valid  density matrix.
            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 density matrix.

        Returns:
            The expectation value of the input state.

        Raises:
            NotImplementedError: If any of the coefficients are imaginary,
                so that this is not Hermitian.
            TypeError: If the input state is not a complex type.
            ValueError: If the input vector is not the correct size or shape.
        """
        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 = int(np.sqrt(size)).bit_length() - 1
        _validate_qubit_mapping(qubit_map, self.qubits, num_qubits)

        dim = int(np.sqrt(size))
        if state.shape != (dim, dim) and state.shape != (2, 2) * num_qubits:
            raise ValueError("Input array does not represent a density matrix "
                             "with shape `(2 ** n, 2 ** n)` or `(2, ..., 2)`.")

        if check_preconditions:
            # Do not enforce reshaping if the state all axes are dimension 2.
            _ = qis.to_valid_density_matrix(
                density_matrix_rep=state.reshape(dim, dim),
                num_qubits=num_qubits,
                dtype=state.dtype,
                atol=atol,
            )
        return sum(
            p._expectation_from_density_matrix_no_validation(state, qubit_map)
            for p in self)
Esempio n. 3
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)
Esempio n. 4
0
    def expectation_from_density_matrix(self, state: np.ndarray,
                                        qubit_map: Mapping[raw_types.Qid, int]
                                       ) -> float:
        """Evaluate the expectation of this PauliSum given a density matrix.

        See `PauliString.expectation_from_density_matrix`.

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

        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 = int(np.sqrt(size)).bit_length() - 1
        _validate_qubit_mapping(qubit_map, self.qubits, num_qubits)

        dim = int(np.sqrt(size))
        if state.shape != (dim, dim) and state.shape != (2, 2) * num_qubits:
            raise ValueError("Input array does not represent a density matrix "
                             "with shape `(2 ** n, 2 ** n)` or `(2, ..., 2)`.")

        # HACK: avoid circular import
        from cirq.sim.density_matrix_utils import to_valid_density_matrix
        # Do not enforce reshaping if the state all axes are dimension 2.
        _ = to_valid_density_matrix(density_matrix_rep=state.reshape(dim, dim),
                                    num_qubits=num_qubits,
                                    dtype=state.dtype)
        return sum(
            p._expectation_from_density_matrix_no_validation(state, qubit_map)
            for p in self)