Example #1
0
 def test_cache_usage(self, depth):
     """Test that the right number of cachings have been executed after clearing the cache"""
     pu.pauli_eigs.cache_clear()
     pu.pauli_eigs(depth)
     total_runs = sum([2**x for x in range(depth)])
     assert functools._CacheInfo(depth - 1, depth, 128,
                                 depth) == pu.pauli_eigs.cache_info()
Example #2
0
class PauliZ(Observable, Operation):
    r"""PauliZ(wires)
    The Pauli Z operator

    .. math:: \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)

    @staticmethod
    def _matrix(*params):
        return np.array([[1, 0], [0, -1]])

    def diagonalizing_gates(self):
        return []
Example #3
0
 def test_correct_eigenvalues_pauli_kronecker_products_three_qubits(
         self, pauli_product):
     """Test the paulieigs function for three qubits"""
     assert np.array_equal(
         pu.pauli_eigs(3),
         np.diag(np.kron(self.pauliz, np.kron(self.pauliz, self.pauliz))),
     )
Example #4
0
    def generator(self):
        if self._generator is None:
            pauli_word = self.parameters[1]

            # Simplest case is if the Pauli is the identity matrix
            if pauli_word == "I" * len(pauli_word):
                self._generator = [np.eye(2 ** len(pauli_word)), -1 / 2]
                return self._generator

            # We first generate the matrix excluding the identity parts and expand it afterwards.
            # To this end, we have to store on which wires the non-identity parts act
            non_identity_wires, non_identity_gates = zip(
                *[(wire, gate) for wire, gate in enumerate(pauli_word) if gate != "I"]
            )

            # get MultiRZ's generator
            multi_Z_rot_generator = np.diag(pauli_eigs(len(non_identity_gates)))

            # now we conjugate with Hadamard and RX to create the Pauli string
            conjugation_matrix = functools.reduce(
                np.kron,
                [PauliRot._PAULI_CONJUGATION_MATRICES[gate] for gate in non_identity_gates],
            )

            self._generator = [
                expand(
                    conjugation_matrix.T.conj() @ multi_Z_rot_generator @ conjugation_matrix,
                    non_identity_wires,
                    list(range(len(pauli_word))),
                ),
                -1 / 2,
            ]

        return self._generator
Example #5
0
class PauliZ(Observable, DiagonalOperation):
    r"""PauliZ(wires)
    The Pauli Z operator

    .. math:: \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
    matrix = np.array([[1, 0], [0, -1]])

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        return []

    @staticmethod
    def decomposition(wires):
        decomp_ops = [PhaseShift(np.pi, wires=wires)]
        return decomp_ops
Example #6
0
class Hadamard(Observable, Operation):
    r"""Hadamard(wires)
    The Hadamard operator

    .. math:: H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1\\ 1 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    is_self_inverse = True
    eigvals = pauli_eigs(1)
    matrix = np.array([[INV_SQRT2, INV_SQRT2], [INV_SQRT2, -INV_SQRT2]])

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of the Hadamard operator.

        For the Hadamard operator,

        .. math:: H = U^\dagger Z U

        where :math:`U = R_y(-\pi/4)`.

        Returns:
            list(~.Operation): A list of gates that diagonalize Hadamard in
            the computational basis.
        """
        return [qml.RY(-np.pi / 4, wires=self.wires)]

    @staticmethod
    def decomposition(wires):
        decomp_ops = [
            qml.PhaseShift(np.pi / 2, wires=wires),
            qml.RX(np.pi / 2, wires=wires),
            qml.PhaseShift(np.pi / 2, wires=wires),
        ]
        return decomp_ops

    def adjoint(self):
        return Hadamard(wires=self.wires)

    def single_qubit_rot_angles(self):
        # H = RZ(\pi) RY(\pi/2) RZ(0)
        return [np.pi, np.pi / 2, 0.0]
Example #7
0
    def _eigvals(cls, theta, n):
        eigs = qml.math.convert_like(pauli_eigs(n), theta)

        if qml.math.get_interface(theta) == "tensorflow":
            theta = qml.math.cast_like(theta, 1j)
            eigs = qml.math.cast_like(eigs, 1j)

        return qml.math.exp(-1j * theta / 2 * eigs)
Example #8
0
class PauliY(Observable, Operation):
    r"""PauliY(wires)
    The Pauli Y operator

    .. math:: \sigma_y = \begin{bmatrix} 0 & -i \\ i & 0\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
    matrix = np.array([[0, -1j], [1j, 0]])

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of PauliY.

        For the Pauli-Y observable,

        .. math:: Y = U^\dagger Z U

        where :math:`U=HSZ`.

        Returns:
            list(~.Operation): A list of gates that diagonalize PauliY in the
                computational basis.
        """
        return [
            PauliZ(wires=self.wires),
            S(wires=self.wires),
            Hadamard(wires=self.wires)
        ]

    @staticmethod
    def decomposition(wires):
        decomp_ops = [
            PhaseShift(np.pi / 2, wires=wires),
            RY(np.pi, wires=wires),
            PhaseShift(np.pi / 2, wires=wires),
        ]
        return decomp_ops
Example #9
0
def MultiRZ(theta, n):
    r"""Arbitrary multi Z rotation.

    Args:
        theta (float): rotation angle :math:`\theta`
        wires (Sequence[int] or int): the wires the operation acts on
    Returns:
        array[complex]: diagonal part of the multi-qubit rotation matrix
    """
    return jnp.exp(-1j * theta / 2 * pauli_eigs(n))
Example #10
0
    def _eigvals(theta, n):
        """Return the eigenvalues corresponding to a specific rotation angle.

        Args:
            theta (float): Rotation angle

        Returns:
            (array[float]): Eigenvalues of the transformation
        """
        return np.exp(-1j * theta / 2 * pauli_eigs(n))
Example #11
0
def MultiRZ(theta, n):
    r"""Arbitrary multi Z rotation.

    Args:
        theta (float): rotation angle
        n (int): number of wires the rotation acts on

    Returns:
        tf.Tensor[complex]: diagonal part of the MultiRZ matrix
    """
    theta = tf.cast(theta, dtype=C_DTYPE)
    multi_Z_rot_eigs = tf.exp(-1j * theta / 2 * pauli_eigs(n))
    return tf.convert_to_tensor(multi_Z_rot_eigs)
Example #12
0
class PauliZ(Observable, Operation):
    r"""PauliZ(wires)
    The Pauli Z operator

    .. math:: \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_wires = 1
    basis = "Z"
    eigvals = pauli_eigs(1)
    matrix = np.array([[1, 0], [0, -1]])

    @property
    def num_params(self):
        return 0

    def label(self, decimals=None, base_label=None):
        return base_label or "Z"

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        return []

    @staticmethod
    def decomposition(wires):
        decomp_ops = [qml.PhaseShift(np.pi, wires=wires)]
        return decomp_ops

    def adjoint(self):
        return PauliZ(wires=self.wires)

    def _controlled(self, wire):
        CZ(wires=Wires(wire) + self.wires)

    def single_qubit_rot_angles(self):
        # Z = RZ(\pi) RY(0) RZ(0)
        return [np.pi, 0.0, 0.0]
Example #13
0
class PauliZ(Observable, Operation):
    r"""PauliZ(wires)
    The Pauli Z operator

    .. math:: \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
Example #14
0
class Hadamard(Observable, Operation):
    r"""Hadamard(wires)
    The Hadamard operator

    .. math:: H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1\\ 1 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
Example #15
0
File: qubit.py Project: kant/DL-PoC
class Hadamard(Observable, Operation):
    r"""Hadamard(wires)
    The Hadamard operator

    .. math:: H = \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1\\ 1 & -1\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
    matrix = np.array([[INV_SQRT2, INV_SQRT2], [INV_SQRT2, -INV_SQRT2]])

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of the Hadamard operator.

        For the Hadamard operator,

        .. math:: H = U^\dagger Z U

        where :math:`U = R_y(-\pi/4)`.

        Returns:
            list(~.Operation): A list of gates that diagonalize Hadamard in
            the computational basis.
        """
        return [RY(-np.pi / 4, wires=self.wires)]
Example #16
0
File: qubit.py Project: kant/DL-PoC
class PauliX(Observable, Operation):
    r"""PauliX(wires)
    The Pauli X operator

    .. math:: \sigma_x = \begin{bmatrix} 0 & 1 \\ 1 & 0\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_params = 0
    num_wires = 1
    par_domain = None
    eigvals = pauli_eigs(1)
    matrix = np.array([[0, 1], [1, 0]])

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of the Pauli-X operator.

        For the Pauli-X operator,

        .. math:: X = H^\dagger Z H.

        Returns:
            list(qml.Operation): A list of gates that diagonalize PauliY in the
            computational basis.
        """
        return [Hadamard(wires=self.wires)]
Example #17
0
 def generator(self):
     if self._generator is None:
         self._generator = [np.diag(pauli_eigs(len(self.wires))), -1 / 2]
     return self._generator
Example #18
0
class PauliY(Observable, Operation):
    r"""PauliY(wires)
    The Pauli Y operator

    .. math:: \sigma_y = \begin{bmatrix} 0 & -i \\ i & 0\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_wires = 1
    basis = "Y"
    eigvals = pauli_eigs(1)
    matrix = np.array([[0, -1j], [1j, 0]])

    @property
    def num_params(self):
        return 0

    def label(self, decimals=None, base_label=None):
        return base_label or "Y"

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of PauliY.

        For the Pauli-Y observable,

        .. math:: Y = U^\dagger Z U

        where :math:`U=HSZ`.

        Returns:
            list(~.Operation): A list of gates that diagonalize PauliY in the
                computational basis.
        """
        return [
            PauliZ(wires=self.wires),
            S(wires=self.wires),
            Hadamard(wires=self.wires),
        ]

    @staticmethod
    def decomposition(wires):
        decomp_ops = [
            qml.PhaseShift(np.pi / 2, wires=wires),
            qml.RY(np.pi, wires=wires),
            qml.PhaseShift(np.pi / 2, wires=wires),
        ]
        return decomp_ops

    def adjoint(self):
        return PauliY(wires=self.wires)

    def _controlled(self, wire):
        CY(wires=Wires(wire) + self.wires)

    def single_qubit_rot_angles(self):
        # Y = RZ(0) RY(\pi) RZ(0)
        return [0.0, np.pi, 0.0]
Example #19
0
 def test_correct_eigenvalues_paulis(self, pauli):
     """Test the paulieigs function for one qubit"""
     assert np.array_equal(pu.pauli_eigs(1), np.diag(self.pauliz))
Example #20
0
class PauliX(Observable, Operation):
    r"""PauliX(wires)
    The Pauli X operator

    .. math:: \sigma_x = \begin{bmatrix} 0 & 1 \\ 1 & 0\end{bmatrix}.

    **Details:**

    * Number of wires: 1
    * Number of parameters: 0

    Args:
        wires (Sequence[int] or int): the wire the operation acts on
    """
    num_wires = 1
    basis = "X"
    eigvals = pauli_eigs(1)
    matrix = np.array([[0, 1], [1, 0]])

    @property
    def num_params(self):
        return 0

    def label(self, decimals=None, base_label=None):
        return base_label or "X"

    @classmethod
    def _matrix(cls, *params):
        return cls.matrix

    @classmethod
    def _eigvals(cls, *params):
        return cls.eigvals

    def diagonalizing_gates(self):
        r"""Rotates the specified wires such that they
        are in the eigenbasis of the Pauli-X operator.

        For the Pauli-X operator,

        .. math:: X = H^\dagger Z H.

        Returns:
            list(qml.Operation): A list of gates that diagonalize PauliY in the
            computational basis.
        """
        return [Hadamard(wires=self.wires)]

    @staticmethod
    def decomposition(wires):
        decomp_ops = [
            qml.PhaseShift(np.pi / 2, wires=wires),
            qml.RX(np.pi, wires=wires),
            qml.PhaseShift(np.pi / 2, wires=wires),
        ]
        return decomp_ops

    def adjoint(self):
        return PauliX(wires=self.wires)

    def _controlled(self, wire):
        CNOT(wires=Wires(wire) + self.wires)

    def single_qubit_rot_angles(self):
        # X = RZ(-\pi/2) RY(\pi) RZ(\pi/2)
        return [np.pi / 2, np.pi, -np.pi / 2]
Example #21
0
File: qubit.py Project: kant/DL-PoC
 def _eigvals(cls, theta, n):
     return np.exp(-1j * theta / 2 * pauli_eigs(n))