Esempio n. 1
0
    def init_from_mul(cls, qu_gates):
        """ Create a quantum gate by multiplying existing gates

        The multiplication will be done from left to right starting zeroth
        element of the qu_gates list. For example:
        qu_gates = [H, X, H] will be H * X * H

        Args:
            qu_gates: a list of QuGates to multiply

        Raises:
            InvalidQuGateError: if the result of the multiplication is
                                not unitary or if the shape of the
                                matrices does not match
        """
        if qu_gates:
            matrix = qu_gates[0].matrix
            for i in range(1, len(qu_gates)):
                if matrix.shape != qu_gates[i].matrix.shape:
                    message = "The matrices supplied have different shapes"
                    raise errors.InvalidQuGateError(message)

                matrix = matrix * qu_gates[i].matrix

            return QuGate(matrix)
        else:
            raise errors.InvalidQuGateError("No gates specified")
Esempio n. 2
0
    def __init__(self, matrix, multiplier=0):
        """Create a quantum gate from a numpy matrix.

        Note that if the matrix dtype is not complex it will be converted
        to a complex matrix.

        Args:
            matrix: a complex typed numpy matrix
            multiplier: if supplied all the elements of the matrix will
                        be multiplied by the multiplier

        Raises:
            InvalidQuGateError: if the gate is not unitary
        """

        if matrix.dtype == np.dtype('complex128'):
            self._matrix = matrix
        else:
            self._matrix = matrix.astype('complex128')

        shape = self._matrix.shape
        if shape[0] != shape[1]:
            raise errors.InvalidQuGateError("Gate is not a square matrix")

        if multiplier:
            self._matrix = self._matrix * multiplier

        #TODO: choose and configure project wide tolerance value
        is_unitary = np.allclose(self._matrix.H * self._matrix,
                                 np.eye(shape[0]))
        if not is_unitary:
            raise errors.InvalidQuGateError("Gate is not unitary")
Esempio n. 3
0
    def init_control_gate(cls,
                          qu_gate,
                          control_qubit=1,
                          target_qubit=2,
                          num_qubits=2):
        """ Creates a CONTROL-U gate where qu_gate is U

        Note we use the handy formula for control-U gates in
        Rieffel/Polak page 78:
        |0><0| x I + |1><1| x U
        where x is the tensor product

        Args:
            qu_gate: a QuGate which acts as your U in control-U
            control_qubit: the index of the control bit, default is 1
            target_qubit: the index of the target bit, default is 2
            num_qubits: total number of qubits, default is 2
        """
        if num_qubits < 2:
            msg = "control gates must operate on at least 2 qubits"
            raise errors.InvalidQuGateError(msg)

        if control_qubit == target_qubit:
            msg = "control qubit must be different than target qubit"
            raise errors.InvalidQuGateError(msg)

        if control_qubit > num_qubits:
            msg = "control qubit cannot be greater than total number of qubits"
            raise errors.InvalidQuGateError(msg)

        if target_qubit > num_qubits:
            msg = "target qubit cannot be greater than total number of qubits"
            raise errors.InvalidQuGateError(msg)

        index = 1
        # start with 1x1 matrix, a.k.a a number
        control_mat = 1
        target_mat = 1
        # build control and target matrices
        while index <= num_qubits:
            if index == control_qubit:
                control_mat = np.kron(control_mat, ZERO.ket * ZERO.bra)
                target_mat = np.kron(target_mat, ONE.ket * ONE.bra)
            elif index == target_qubit:
                control_mat = np.kron(control_mat, np.eye(2))
                target_mat = np.kron(target_mat, qu_gate.matrix)
            else:
                control_mat = np.kron(control_mat, np.eye(2))
                target_mat = np.kron(target_mat, np.eye(2))

            index += 1

        control_gate = control_mat + target_mat
        return QuGate(control_gate)
Esempio n. 4
0
    def apply_control_gate(self, qu_gate, control_qubit, target_qubit):
        """Apply a control gate to the state.

        Args:
            qu_gate: the U gate in a control-U operation
            control_qubit: the control qubit
            target_qubit: the target qubit

        Raises:
            InvalidQuGateError: if control or target qubits are out of range
        """
        if control_qubit <= 0 or control_qubit > self.num_qubits:
            raise errors.InvalidQuGateError("control qubit out of range")

        if target_qubit <= 0 or target_qubit > self.num_qubits:
            raise errors.InvalidQuGateError("target qubit out of range")

        control_qugate = QuGate.init_control_gate(qu_gate, control_qubit,
                                                  target_qubit,
                                                  self.num_qubits)
        self.apply_gate(control_qugate)
Esempio n. 5
0
    def init_from_tensor_product(cls, qu_gates):
        """ Create a quantum gate by the tensor product of other gates

        The tensor product will be done from left to right starting zeroth
        element of the qu_gates list. For example:
        qu_gates = [H, X, H] will be H tensor X tensor H

        Args:
            qu_gates: a list of QuGates to tensor

        Raises:
            InvalidQuGateError: if the result is not unitary
        """
        if qu_gates:
            matrix = np.matrix([1], dtype="complex128")
            for i in range(len(qu_gates) - 1, -1, -1):
                matrix = np.kron(qu_gates[i].matrix, matrix)

            return QuGate(matrix)
        else:
            raise errors.InvalidQuGateError("No gates specified")