def qfunc1():
     qml.Hadamard(wires=0)
     qml.PauliX(wires=1)
     qml.SWAP(wires=[0, 1])
     qml.SWAP(wires=[0, 2])
     qml.PauliY(wires=0)
     return qml.expval(qml.PauliZ(0))
Exemple #2
0
 def circuit():
     """A combination of two and three qubit gates with the one_qubit_block and a simple
     PauliZ measurement, all acting on a four qubit input basis state"""
     qml.BasisState(np.array(basis_state), wires=[0, 1, 2, 3])
     qml.RX(0.5, wires=0)
     qml.Hadamard(wires=1)
     qml.RY(0.9, wires=2)
     qml.Rot(0.1, -0.2, -0.3, wires=3)
     qml.CNOT(wires=[0, 1])
     qml.CNOT(wires=[3, 1])
     one_qubit_block(wires=3)
     qml.CNOT(wires=[2, 0])
     qml.CZ(wires=[1, 0])
     one_qubit_block(wires=0)
     qml.Toffoli(wires=[1, 0, 2])
     one_qubit_block(wires=2)
     qml.SWAP(wires=[0, 1])
     qml.SWAP(wires=[0, 2])
     qml.Toffoli(wires=[1, 3, 2])
     qml.CRX(0.5, wires=[1, 0])
     qml.CSWAP(wires=[2, 1, 0])
     qml.CRY(0.9, wires=[2, 1])
     one_qubit_block(wires=1)
     qml.CRZ(0.02, wires=[0, 1])
     qml.CRY(0.9, wires=[2, 3])
     qml.CRot(0.2, 0.3, 0.7, wires=[2, 1])
     qml.RZ(0.4, wires=0)
     qml.Toffoli(wires=[2, 1, 0])
     return qml.expval(qml.PauliZ(0))
def qfunc(theta):
    qml.Hadamard(wires=0)
    qml.RX(theta[0], wires=1)
    qml.SWAP(wires=[0, 1])
    qml.SWAP(wires=[0, 2])
    qml.RY(theta[1], wires=0)
    return qml.expval(qml.PauliZ(0))
Exemple #4
0
    def test_SWAP(self):
        """Test SWAP gate special call"""

        with QuantumTape() as tape:
            qml.SWAP(wires=(0, 1))

        _, ax = tape_mpl(tape)
        layer = 0

        # two wires produce two lines and SWAP contains 5 more lines
        assert len(ax.lines) == 7

        connecting_line = ax.lines[2]
        assert connecting_line.get_data() == ((layer, layer), [0, 1])

        dx = 0.2
        # check the coordinates of the swap lines
        x_lines = ax.lines[3:]
        for line in x_lines:
            assert line.get_xdata() == (layer - dx, layer + dx)

        assert x_lines[0].get_ydata() == (-dx, dx)
        assert x_lines[1].get_ydata() == (dx, -dx)

        assert x_lines[2].get_ydata() == (1 - dx, 1 + dx)
        assert x_lines[3].get_ydata() == (1 + dx, 1 - dx)

        plt.close()
Exemple #5
0
 def decomposition(wires):
     return [
         qml.SWAP(wires=wires),
         qml.S(wires=[wires[0]]),
         qml.S(wires=[wires[1]]),
         qml.CZ(wires=wires),
     ]
Exemple #6
0
 def compute_decomposition(phi, wires):
     return [
         qml.SWAP(wires=wires),
         qml.CNOT(wires=wires),
         qml.PhaseShift(phi, wires=[wires[1]]),
         qml.CNOT(wires=wires),
     ]
    def qfunc(a, b, c, angles):
        qml.RX(a, wires=0)
        qml.RX(b, wires=1)
        qml.PauliZ(1)
        qml.CNOT(wires=[0, 1]).inv()
        qml.CRY(b, wires=[3, 1])
        qml.RX(angles[0], wires=0)
        qml.RX(4 * angles[1], wires=1)
        qml.PhaseShift(17 / 9 * c, wires=2)
        qml.RZ(b, wires=3)
        qml.RX(angles[2], wires=2).inv()
        qml.CRY(0.3589, wires=[3, 1]).inv()
        qml.CSWAP(wires=[4, 2, 1]).inv()
        qml.QubitUnitary(np.eye(2), wires=[2])
        qml.Toffoli(wires=[0, 2, 1])
        qml.CNOT(wires=[0, 2])
        qml.PauliZ(wires=[1])
        qml.PauliZ(wires=[1]).inv()
        qml.CZ(wires=[0, 1])
        qml.CZ(wires=[0, 2]).inv()
        qml.CNOT(wires=[2, 1])
        qml.CNOT(wires=[0, 2])
        qml.SWAP(wires=[0, 2]).inv()
        qml.CNOT(wires=[1, 3])
        qml.RZ(b, wires=3)
        qml.CSWAP(wires=[4, 0, 1])

        return [
            qml.expval(qml.PauliY(0)),
            qml.var(qml.Hadamard(wires=1)),
            qml.sample(qml.PauliX(2)),
            qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])),
        ]
Exemple #8
0
 def circuit():
     qml.Rot(theta, phi, delta, wires=0)
     qml.Rot(theta, phi, delta, wires=1)
     qml.SWAP(wires=[0, 1])
     return (
         qml.expval(qml.PauliX(0)),
         qml.expval(qml.PauliX(1)),
     )
def Turing():
    # distinct fun names in functional placeholders=
    # []
    qml.Hadamard(0)
    qml.PauliX(1)
    qml.PauliY(1)
    qml.PauliZ(1)
    qml.CNOT(wires=[0, 1])
    qml.CZ(wires=[0, 1])
    qml.SWAP(wires=[1, 0])
    qml.RX(-6.283185307179586, wires=2)
    qml.RY(-6.283185307179586, wires=2)
    qml.RZ(-6.283185307179586, wires=2)
    qml.PhaseShift(3.141592653589793, wires=1)

    def rot(rad_ang_x, rad_ang_y, rad_ang_z):
        """
        Returns
    
        exp(1j*(rad_ang_x*sig_x + rad_ang_y*sig_y + rad_ang_z*sig_z))
    
        where rad_ang_x is an angle in radians and sig_x is the x Pauli
        matrix, etc.
    
        Parameters
        ----------
        rad_ang_x : float
        rad_ang_y : float
        rad_ang_z : float
    
        Returns
        -------
        np.ndarray
    
        """
        ty = np.complex128
        mat = np.zeros([2, 2], dtype=ty)
        vec = np.array([rad_ang_x, rad_ang_y, rad_ang_z])
        n = np.linalg.norm(vec)  # sqrt(dot(vec, vec.conj))
        if abs(n) < 1e-8:
            mat[0, 0] = 1
            mat[1, 1] = 1
        else:
            nx = rad_ang_x / n
            ny = rad_ang_y / n
            nz = rad_ang_z / n
            c = np.cos(n)
            s = np.sin(n)
            mat[0, 0] = c + 1j * s * nz
            mat[0, 1] = s * ny + 1j * s * nx
            mat[1, 0] = -s * ny + 1j * s * nx
            mat[1, 1] = c - 1j * s * nz
        return mat

    qml.QubitUnitary(rot(-6.283185307179586, -6.283185307179586,
                         -6.283185307179586),
                     wires=0)
    return qml.expval.Hermitian(hamil)
        def qft_circuit():
            for wire in reversed(range(self.n)):
                qml.Hadamard(wire)
                for i in range(wire):
                    qml.CRZ(np.pi / (2**(wire - i)), wires=[i, wire])

            for i in range(self.n // 2):
                qml.SWAP(wires=[i, self.n - i - 1])

            return qml.probs(wires=range(self.n))
Exemple #11
0
def qft_U(params):
    # Execute QFT
    n_param = 0
    for i in range(n_qubits):
        qml.Hadamard(wires=i)
        for j in range(i + 1, n_qubits):
            U0(params[n_param], wires=[0, 1, 2, 3])
            n_param += 1
    # Final swaps
    for n in range(n_qubits // 2):
        qml.SWAP(wires=[n, n_qubits - n - 1])
Exemple #12
0
def qft():
    # Execute QFT
    for i in range(n_qubits):
        qml.Hadamard(wires=i)
        for n_j, j in enumerate(range(i + 1, n_qubits)):
            R_k = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                            [0, 0, 0, np.exp(2j * π / (2**(n_j + 2)))]])
            qml.QubitUnitary(R_k, wires=[j, i])
    # Final swaps
    for n in range(n_qubits // 2):
        qml.SWAP(wires=[n, (n_qubits - 1) - n])
Exemple #13
0
def op(op_name):
    ops_list = {
        "RX": qml.RX(0.123, wires=0),
        "RY": qml.RY(1.434, wires=0),
        "RZ": qml.RZ(2.774, wires=0),
        "S": qml.S(wires=0),
        "SX": qml.SX(wires=0),
        "T": qml.T(wires=0),
        "CNOT": qml.CNOT(wires=[0, 1]),
        "CZ": qml.CZ(wires=[0, 1]),
        "CY": qml.CY(wires=[0, 1]),
        "SWAP": qml.SWAP(wires=[0, 1]),
        "ISWAP": qml.ISWAP(wires=[0, 1]),
        "SISWAP": qml.SISWAP(wires=[0, 1]),
        "SQISW": qml.SQISW(wires=[0, 1]),
        "CSWAP": qml.CSWAP(wires=[0, 1, 2]),
        "PauliRot": qml.PauliRot(0.123, "Y", wires=0),
        "IsingXX": qml.IsingXX(0.123, wires=[0, 1]),
        "IsingXY": qml.IsingXY(0.123, wires=[0, 1]),
        "IsingYY": qml.IsingYY(0.123, wires=[0, 1]),
        "IsingZZ": qml.IsingZZ(0.123, wires=[0, 1]),
        "Identity": qml.Identity(wires=0),
        "Rot": qml.Rot(0.123, 0.456, 0.789, wires=0),
        "Toffoli": qml.Toffoli(wires=[0, 1, 2]),
        "PhaseShift": qml.PhaseShift(2.133, wires=0),
        "ControlledPhaseShift": qml.ControlledPhaseShift(1.777, wires=[0, 2]),
        "CPhase": qml.CPhase(1.777, wires=[0, 2]),
        "MultiRZ": qml.MultiRZ(0.112, wires=[1, 2, 3]),
        "CRX": qml.CRX(0.836, wires=[2, 3]),
        "CRY": qml.CRY(0.721, wires=[2, 3]),
        "CRZ": qml.CRZ(0.554, wires=[2, 3]),
        "Hadamard": qml.Hadamard(wires=0),
        "PauliX": qml.PauliX(wires=0),
        "PauliY": qml.PauliY(wires=0),
        "PauliZ": qml.PauliZ(wires=0),
        "CRot": qml.CRot(0.123, 0.456, 0.789, wires=[0, 1]),
        "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1.0, 1.0j]), wires=1),
        "ControlledQubitUnitary": qml.ControlledQubitUnitary(
            np.eye(2) * 1j, wires=[0], control_wires=[2]
        ),
        "MultiControlledX": qml.MultiControlledX(wires=(0, 1, 2), control_values="01"),
        "SingleExcitation": qml.SingleExcitation(0.123, wires=[0, 3]),
        "SingleExcitationPlus": qml.SingleExcitationPlus(0.123, wires=[0, 3]),
        "SingleExcitationMinus": qml.SingleExcitationMinus(0.123, wires=[0, 3]),
        "DoubleExcitation": qml.DoubleExcitation(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationPlus": qml.DoubleExcitationPlus(0.123, wires=[0, 1, 2, 3]),
        "DoubleExcitationMinus": qml.DoubleExcitationMinus(0.123, wires=[0, 1, 2, 3]),
        "QFT": qml.QFT(wires=0),
        "QubitSum": qml.QubitSum(wires=[0, 1, 2]),
        "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]),
        "QubitUnitary": qml.QubitUnitary(np.eye(2) * 1j, wires=0),
    }
    return ops_list.get(op_name)
    def test_four_qubit_random_circuit(self, device, tol):
        """Compare a four-qubit random circuit with lots of different gates to default.qubit"""
        n_wires = 4
        dev = device(n_wires)
        dev_def = qml.device("default.qubit", wires=n_wires)

        if dev.name == dev_def.name:
            pytest.skip("Device is default.qubit.")

        if dev.shots is not None:
            pytest.skip("Device is in non-analytical mode.")

        gates = [
            qml.PauliX(wires=0),
            qml.PauliY(wires=1),
            qml.PauliZ(wires=2),
            qml.S(wires=3),
            qml.T(wires=0),
            qml.RX(2.3, wires=1),
            qml.RY(1.3, wires=2),
            qml.RZ(3.3, wires=3),
            qml.Hadamard(wires=0),
            qml.Rot(0.1, 0.2, 0.3, wires=1),
            qml.CRot(0.1, 0.2, 0.3, wires=[2, 3]),
            qml.Toffoli(wires=[0, 1, 2]),
            qml.SWAP(wires=[1, 2]),
            qml.CSWAP(wires=[1, 2, 3]),
            qml.U1(1.0, wires=0),
            qml.U2(1.0, 2.0, wires=2),
            qml.U3(1.0, 2.0, 3.0, wires=3),
            qml.CRX(0.1, wires=[1, 2]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRZ(0.3, wires=[3, 1]),
        ]

        layers = 3
        np.random.seed(1967)
        gates_per_layers = [np.random.permutation(gates).numpy() for _ in range(layers)]

        def circuit():
            """4-qubit circuit with layers of randomly selected gates and random connections for
            multi-qubit gates."""
            np.random.seed(1967)
            for gates in gates_per_layers:
                for gate in gates:
                    qml.apply(gate)
            return qml.expval(qml.PauliZ(0))

        qnode_def = qml.QNode(circuit, dev_def)
        qnode = qml.QNode(circuit, dev)

        assert np.allclose(qnode(), qnode_def(), atol=tol(dev.shots))
    def expand(self):
        with qml.tape.QuantumTape() as tape:
            # block of Hadamard and CR_k gates
            for i in range(len(self.wires)):
                qml.Hadamard(wires=self.wires[i])
                for k in range(2,(len(self.wires)-i)+1):
                    CR_k_inv(k,wires=[self.wires[i+(k-1)],self.wires[i]])

            # block of SWAP gates
            # works both if len(wires)%2 == 0 or len(wires)%2 == 1
            for i in range(int(len(self.wires)/2)):
                qml.SWAP(wires=[self.wires[i],self.wires[len(self.wires)-(i+1)]])
        return tape
Exemple #16
0
    def test_swap_decomposition(self):
        """Tests the swap operator produces the correct output"""
        opr = qml.SWAP(wires=[0, 1])
        decomp = opr.decompose()

        mat = []
        for op in reversed(decomp):
            if isinstance(op, qml.CNOT) and op.wires.tolist() == [0, 1]:
                mat.append(CNOT)
            elif isinstance(op, qml.CNOT) and op.wires.tolist() == [1, 0]:
                mat.append(np.array([[1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0]]))

        decomposed_matrix = np.linalg.multi_dot(mat)

        assert np.allclose(decomposed_matrix, opr.matrix)
Exemple #17
0
 def circuit():
     """A combination of two qubit gates with the one_qubit_block and a simple PauliZ
     measurement applied to an input basis state"""
     qml.BasisState(np.array(basis_state), wires=[0, 1])
     qml.RX(0.5, wires=0)
     qml.Hadamard(wires=1)
     qml.CNOT(wires=[0, 1])
     qml.CZ(wires=[1, 0])
     one_qubit_block(wires=0)
     qml.SWAP(wires=[0, 1])
     qml.CRX(0.5, wires=[1, 0])
     qml.CRY(0.9, wires=[0, 1])
     one_qubit_block(wires=1)
     qml.CRZ(0.02, wires=[0, 1])
     qml.CRot(0.2, 0.3, 0.7, wires=[0, 1])
     return qml.expval(qml.PauliZ(0))
Exemple #18
0
    def test_four_qubit_random_circuit(self, shots):
        """Test a four-qubit random circuit with the whole set of possible gates,
        the test is analog to a failing device test and is used to check the try/except
        expval function from the mixed_simulator device."""
        dev = qml.device("cirq.mixedsimulator", wires=4)

        gates = [
            qml.PauliX(wires=0),
            qml.PauliY(wires=1),
            qml.PauliZ(wires=2),
            qml.S(wires=3),
            qml.T(wires=0),
            qml.RX(2.3, wires=1),
            qml.RY(1.3, wires=2),
            qml.RZ(3.3, wires=3),
            qml.Hadamard(wires=0),
            qml.Rot(0.1, 0.2, 0.3, wires=1),
            qml.CRot(0.1, 0.2, 0.3, wires=[2, 3]),
            qml.Toffoli(wires=[0, 1, 2]),
            qml.SWAP(wires=[1, 2]),
            qml.CSWAP(wires=[1, 2, 3]),
            qml.U1(1.0, wires=0),
            qml.U2(1.0, 2.0, wires=2),
            qml.U3(1.0, 2.0, 3.0, wires=3),
            qml.CRX(0.1, wires=[1, 2]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRZ(0.3, wires=[3, 1]),
        ]

        layers = 3
        np.random.seed(1967)
        gates_per_layers = [pnp.random.permutation(gates).numpy() for _ in range(layers)]

        def circuit():
            """4-qubit circuit with layers of randomly selected gates and random connections for
            multi-qubit gates."""
            np.random.seed(1967)
            for gates in gates_per_layers:
                for gate in gates:
                    qml.apply(gate)
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        assert np.allclose(qnode(), 0.0)
Exemple #19
0
def compute_matrix_from_ops_two_qubit(ops, wire_order):
    """Given a list of two-qubit operations, construct its matrix representation."""

    mat = qml.math.kron(I, I)

    for op in ops:
        if len(op.wires) == 1:
            if op.wires == qml.wires.Wires(wire_order[0]):
                mat = qml.math.dot(qml.math.kron(op.matrix, I), mat)
            else:
                mat = qml.math.dot(qml.math.kron(I, op.matrix), mat)
        else:
            if op.wires == qml.wires.Wires(wire_order):
                mat = qml.math.dot(op.matrix, mat)
            else:
                mat = qml.math.dot(
                    qml.SWAP(wires=[0, 1]).matrix,
                    qml.math.dot(op.matrix, mat))
    return mat
def parameterized_qubit_tape():
    """A parametrized qubit ciruit."""
    a, b, c = 0.1, 0.2, 0.3
    angles = np.array([0.4, 0.5, 0.6])

    with qml.tape.QuantumTape() as tape:
        qml.RX(a, wires=0)
        qml.RX(b, wires=1)
        qml.PauliZ(1)
        qml.CNOT(wires=[0, 1]).inv()
        qml.CRY(b, wires=[3, 1])
        qml.RX(angles[0], wires=0)
        qml.RX(4 * angles[1], wires=1)
        qml.PhaseShift(17 / 9 * c, wires=2)
        qml.RZ(b, wires=3)
        qml.RX(angles[2], wires=2).inv()
        qml.CRY(0.3589, wires=[3, 1]).inv()
        qml.CSWAP(wires=[4, 2, 1]).inv()
        qml.QubitUnitary(np.eye(2), wires=[2])
        qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2])
        qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3])
        qml.Toffoli(wires=[0, 2, 1])
        qml.CNOT(wires=[0, 2])
        qml.PauliZ(wires=[1])
        qml.PauliZ(wires=[1]).inv()
        qml.CZ(wires=[0, 1])
        qml.CZ(wires=[0, 2]).inv()
        qml.CY(wires=[1, 2])
        qml.CY(wires=[2, 0]).inv()
        qml.CNOT(wires=[2, 1])
        qml.CNOT(wires=[0, 2])
        qml.SWAP(wires=[0, 2]).inv()
        qml.CNOT(wires=[1, 3])
        qml.RZ(b, wires=3)
        qml.CSWAP(wires=[4, 0, 1])

        qml.expval(qml.PauliY(0)),
        qml.var(qml.Hadamard(wires=1)),
        qml.sample(qml.PauliX(2)),
        qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])),

    return tape
Exemple #21
0
def permute_qubits(num_qubits):
    # A random permutation
    perm_order = list(rng.permutation(num_qubits))

    working_order = list(range(num_qubits))

    # We will permute by iterating through the permutation and swapping
    # things back to their proper place.
    for idx_here in range(num_qubits):
        if working_order[idx_here] != perm_order[idx_here]:
            # Where do we need to send the qubit at this location?
            idx_there = working_order.index(perm_order[idx_here])

            qml.SWAP(wires=[idx_here, idx_there])

            # Update the working order to account for the SWAP
            working_order[idx_here], working_order[idx_there] = (
                working_order[idx_there],
                working_order[idx_here],
            )
def qft_3():
    """ 3 qubit Quantum Fourier Transform.
    
    Returns:
        the probabilities of each of the basis states from qml.probs
    """

    # The following 2 for loops represent the Quantum Fourier Transform
    for n in range(3, 0, -1):
        qml.Hadamard(wires=('wire' + str(n)))
        for k in range(n - 1, 0, -1):
            b = n - 1
            U = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                          [0, 0, 0,
                           np.exp((np.pi / float(2**(n - k))) * 1j)]])
            qml.QubitUnitary(U,
                             wires=[('wire' + str(k)), ('wire' + str(b + 1))])

    qml.SWAP(wires=['wire1', 'wire3'])

    return qml.probs(wires=['wire3', 'wire2', 'wire1'])
Exemple #23
0
def test_integration():
    gates = [
        qml.PauliX(wires=0),
        qml.PauliY(wires=0),
        qml.PauliZ(wires=0),
        qml.S(wires=0),
        qml.T(wires=0),
        qml.RX(0.4, wires=0),
        qml.RY(0.4, wires=0),
        qml.RZ(0.4, wires=0),
        qml.Hadamard(wires=0),
        qml.Rot(0.4, 0.5, 0.6, wires=1),
        qml.CRot(0.4, 0.5, 0.6, wires=(0, 1)),
        qml.Toffoli(wires=(0, 1, 2)),
        qml.SWAP(wires=(0, 1)),
        qml.CSWAP(wires=(0, 1, 2)),
        qml.U1(0.4, wires=0),
        qml.U2(0.4, 0.5, wires=0),
        qml.U3(0.4, 0.5, 0.6, wires=0),
        qml.CRX(0.4, wires=(0, 1)),
        qml.CRY(0.4, wires=(0, 1)),
        qml.CRZ(0.4, wires=(0, 1)),
    ]

    layers = 3
    np.random.seed(1967)
    gates_per_layers = [np.random.permutation(gates) for _ in range(layers)]

    with qml.tape.QuantumTape() as tape:
        np.random.seed(1967)
        for gates in gates_per_layers:
            for gate in gates:
                qml.apply(gate)

    base_circ = from_pennylane(tape)
    tape_recovered = to_pennylane(base_circ)
    circ_recovered = from_pennylane(tape_recovered)
    u_1 = cirq.unitary(base_circ)
    u_2 = cirq.unitary(circ_recovered)
    cirq.testing.assert_allclose_up_to_global_phase(u_1, u_2, atol=0)
def qpe():
    """ Quantum phase estimation on a single-qubit unitary with 3-bit prcision.
    
    Returns:
        the probabilities of each of the basis stats from qml.probs
    """
    # Initialize qubit 4 to state 1
    qml.PauliX(wires='wire4')

    # Transform the other 3 qubits into the Hadamard basis
    qml.Hadamard(wires='wire3')
    qml.Hadamard(wires='wire2')
    qml.Hadamard(wires='wire1')

    angle = 5 * (np.pi / 4)
    U1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                   [0, 0, 0, np.exp(angle * 1j)]])

    # The following two for loops represent the relevant controlled unitary operations
    iterations = 1
    for i in range(3):
        for j in range(iterations):
            qml.QubitUnitary(U1, wires=[('wire' + str(i + 1)), 'wire4'])
        iterations = iterations * 2

    qml.SWAP(wires=['wire1', 'wire3'])

    # The following two for loops represent the Inverse Quantum Fourier Transform
    for n in range(3):
        for k in range(n):
            U2 = np.array(
                [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                 [0, 0, 0, np.exp((-np.pi / float(2**(n - k))) * 1j)]])
            qml.QubitUnitary(U2,
                             wires=[('wire' + str(k + 1)),
                                    ('wire' + str(n + 1))])
        qml.Hadamard(wires=('wire' + str(n + 1)))

    return qml.probs(wires=['wire3', 'wire2', 'wire1'])
    def test_nested_tapes(self):

        with qml.tape.QuantumTape() as tape:
            with qml.tape.QuantumTape():
                qml.PauliX(0)
                qml.CNOT(wires=[0, 2])
                with qml.tape.QuantumTape():
                    qml.QuantumPhaseEstimation(
                        qml.PauliY.matrix, target_wires=[1], estimation_wires=[2]
                    )
                    qml.CNOT(wires=[1, 2])
            qml.Hadamard(1)
            with qml.tape.QuantumTape():
                qml.SWAP(wires=[0, 1])
            qml.state()

        expected = (
            " 0: ──╭QuantumTape:T0─────╭QuantumTape:T1──╭┤ State \n"
            + " 1: ──├QuantumTape:T0──H──╰QuantumTape:T1──├┤ State \n"
            + " 2: ──╰QuantumTape:T0──────────────────────╰┤ State \n"
            + "T0 =\n"
            + " 0: ──X──╭C───────────────────┤  \n"
            + " 2: ─────╰X──╭QuantumTape:T2──┤  \n"
            + " 1: ─────────╰QuantumTape:T2──┤  \n"
            + "T2 =\n"
            + " 1: ──╭QuantumPhaseEstimation(M0)──╭C──┤  \n"
            + " 2: ──╰QuantumPhaseEstimation(M0)──╰X──┤  \n"
            + "M0 =\n"
            + "[[ 0.+0.j -0.-1.j]\n"
            + " [ 0.+1.j  0.+0.j]]\n"
            + "\n"
            + "\n"
            + "T1 =\n"
            + " 0: ──╭SWAP──┤  \n"
            + " 1: ──╰SWAP──┤  \n"
            + "\n"
        )

        assert tape.draw(wire_order=qml.wires.Wires([0, 1, 2])) == expected
Exemple #26
0
    def decomposition(wires):
        num_wires = len(wires)
        shifts = [2 * np.pi * 2**-i for i in range(2, num_wires + 1)]

        decomp_ops = []
        for i, wire in enumerate(wires):
            decomp_ops.append(qml.Hadamard(wire))

            for shift, control_wire in zip(shifts[:len(shifts) - i],
                                           wires[i + 1:]):
                op = qml.ControlledPhaseShift(shift,
                                              wires=[control_wire, wire])
                decomp_ops.append(op)

        first_half_wires = wires[:num_wires // 2]
        last_half_wires = wires[-(num_wires // 2):]

        for wire1, wire2 in zip(first_half_wires, reversed(last_half_wires)):
            swap = qml.SWAP(wires=[wire1, wire2])
            decomp_ops.append(swap)

        return decomp_ops
def qft_3_with_inverse_check():
    """ 3 qubit Quantum Fourier Transform as well as a 3 Qubit Inverse Fourier Transform
        used to verify QFT implementation        
    
    Returns:
        the probabilities of each of the basis states from qml.probs
    """

    # Lets test with 100
    qml.PauliX('wire1')

    # The following 2 for loops represent the Quantum Fourier Transform
    for n in range(3, 0, -1):
        qml.Hadamard(wires=('wire' + str(n)))
        for k in range(n - 1, 0, -1):
            b = n - 1
            U1 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                           [0, 0, 0,
                            np.exp((np.pi / float(2**(n - k))) * 1j)]])
            qml.QubitUnitary(U1,
                             wires=[('wire' + str(k)), ('wire' + str(b + 1))])

    # The following 2 for loops represent the Inverse Quantum Fourier Transform used to ensure that
    # we can return to the original state after the Quantum Fourier Transform
    for n in range(3):
        for k in range(n):
            U2 = np.array(
                [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                 [0, 0, 0, np.exp((-np.pi / float(2**(n - k))) * 1j)]])
            qml.QubitUnitary(U2,
                             wires=[('wire' + str(k + 1)),
                                    ('wire' + str(n + 1))])
        qml.Hadamard(wires=('wire' + str(n + 1)))

    qml.SWAP(wires=['wire1', 'wire3'])

    #return qml.probs(wires=['wire1' ,'wire2', 'wire3'])
    return qml.probs(wires=['wire3', 'wire2', 'wire1'])
Exemple #28
0
def circuit2():
    # create input state of 1
    qml.PauliX(wires=3)
    # apply phase estimation circuit
    qml.Hadamard(wires=0)
    qml.Hadamard(wires=1)
    qml.Hadamard(wires=2)

    qml.CRZ(5*pi/2, wires=[2,3])
    for i in range (2):    
        qml.CRZ(5*pi/2, wires=[1,3])   

    for i in range(4):
        qml.CRZ(5*pi/2, wires=[0,3])
# QFT-1
    qml.SWAP(wires=[0,2])
    qml.Hadamard(wires=2)
    qml.CRZ(pi/2,wires=[2,1]).inv()
    qml.CRZ(pi/4,wires=[2,0]).inv()
    qml.Hadamard(wires=1)
    qml.CRZ(pi/2,wires=[1,0]).inv()
    qml.Hadamard(wires=0)
    return qml.probs(wires=[0,1,2])
Exemple #29
0
class TestProgramConverter:
    """Test that PyQuil Program instances are properly converted."""
    @pytest.mark.parametrize(
        "pyquil_operation,expected_pl_operation",
        [
            (g.I(0), qml.Identity(wires=[0])),
            (g.H(0), qml.Hadamard(0)),
            (g.H(0).dagger(), qml.Hadamard(0).inv()),
            (g.H(0).dagger().dagger(), qml.Hadamard(0).inv().inv()),
            (g.S(0), qml.S(wires=[0])),
            (g.S(0).dagger(), qml.S(wires=[0]).inv()),
            (g.S(0).dagger().dagger(), qml.S(wires=[0]).inv().inv()),
            (g.T(0), qml.T(wires=[0])),
            (g.T(0).dagger(), qml.T(wires=[0]).inv()),
            (g.T(0).dagger().dagger(), qml.T(wires=[0]).inv().inv()),
            (g.X(0), qml.PauliX(0)),
            (g.X(0).dagger(), qml.PauliX(0).inv()),
            (g.X(0).dagger().dagger(), qml.PauliX(0).inv().inv()),
            (g.X(0).controlled(1), qml.CNOT(wires=[1, 0])),
            (g.X(0).controlled(1).dagger(), qml.CNOT(wires=[1, 0]).inv()),
            (g.X(0).controlled(1).dagger().dagger(),
             qml.CNOT(wires=[1, 0]).inv().inv()),
            (g.X(0).controlled(1).controlled(2),
             plf.ops.CCNOT(wires=[2, 1, 0])),
            (g.X(0).controlled(1).controlled(2).dagger(),
             plf.ops.CCNOT(wires=[2, 1, 0]).inv()),
            (
                g.X(0).controlled(1).controlled(2).dagger().dagger(),
                plf.ops.CCNOT(wires=[2, 1, 0]).inv().inv(),
            ),
            (g.Y(0), qml.PauliY(0)),
            (g.Y(0).dagger(), qml.PauliY(0).inv()),
            (g.Y(0).dagger().dagger(), qml.PauliY(0).inv().inv()),
            (g.Z(0), qml.PauliZ(0)),
            (g.Z(0).dagger(), qml.PauliZ(0).inv()),
            (g.Z(0).dagger().dagger(), qml.PauliZ(0).inv().inv()),
            (g.Z(0).controlled(1), qml.CZ(wires=[1, 0])),
            (g.Z(0).controlled(1).dagger(), qml.CZ(wires=[1, 0]).inv()),
            (g.Z(0).controlled(1).dagger().dagger(),
             qml.CZ(wires=[1, 0]).inv().inv()),
            (g.CNOT(0, 1), qml.CNOT(wires=[0, 1])),
            (g.CNOT(0, 1).dagger(), qml.CNOT(wires=[0, 1]).inv()),
            (g.CNOT(0,
                    1).dagger().dagger(), qml.CNOT(wires=[0, 1]).inv().inv()),
            (g.CNOT(0, 1).controlled(2), plf.ops.CCNOT(wires=[2, 0, 1])),
            (g.CNOT(0, 1).controlled(2).dagger(),
             plf.ops.CCNOT(wires=[2, 0, 1]).inv()),
            (
                g.CNOT(0, 1).controlled(2).dagger().dagger(),
                plf.ops.CCNOT(wires=[2, 0, 1]).inv().inv(),
            ),
            (g.SWAP(0, 1), qml.SWAP(wires=[0, 1])),
            (g.SWAP(0, 1).dagger(), qml.SWAP(wires=[0, 1]).inv()),
            (g.SWAP(0,
                    1).dagger().dagger(), qml.SWAP(wires=[0, 1]).inv().inv()),
            (g.SWAP(0, 1).controlled(2), qml.CSWAP(wires=[2, 0, 1])),
            (g.SWAP(0, 1).controlled(2).dagger(),
             qml.CSWAP(wires=[2, 0, 1]).inv()),
            (g.SWAP(0, 1).controlled(2).dagger().dagger(),
             qml.CSWAP(wires=[2, 0, 1]).inv().inv()),
            (g.ISWAP(0, 1), plf.ops.ISWAP(wires=[0, 1])),
            (g.ISWAP(0, 1).dagger(), plf.ops.ISWAP(wires=[0, 1]).inv()),
            (g.ISWAP(0, 1).dagger().dagger(),
             plf.ops.ISWAP(wires=[0, 1]).inv().inv()),
            (g.PSWAP(0.3, 0, 1), plf.ops.PSWAP(0.3, wires=[0, 1])),
            (g.PSWAP(0.3, 0, 1).dagger(), plf.ops.PSWAP(0.3, wires=[0, 1
                                                                    ]).inv()),
            (g.PSWAP(0.3, 0, 1).dagger().dagger(),
             plf.ops.PSWAP(0.3, wires=[0, 1]).inv().inv()),
            (g.CZ(0, 1), qml.CZ(wires=[0, 1])),
            (g.CZ(0, 1).dagger(), qml.CZ(wires=[0, 1]).inv()),
            (g.CZ(0, 1).dagger().dagger(), qml.CZ(wires=[0, 1]).inv().inv()),
            (g.PHASE(0.3, 0), qml.PhaseShift(0.3, wires=[0])),
            (g.PHASE(0.3, 0).dagger(), qml.PhaseShift(0.3, wires=[0]).inv()),
            (g.PHASE(0.3, 0).dagger().dagger(), qml.PhaseShift(
                0.3, wires=[0]).inv().inv()),
            (g.PHASE(0.3, 0).controlled(1), plf.ops.CPHASE(
                0.3, 3, wires=[1, 0])),
            (g.PHASE(0.3, 0).controlled(1).dagger(),
             plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv()),
            (
                g.PHASE(0.3, 0).controlled(1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 3, wires=[1, 0]).inv().inv(),
            ),
            (g.RX(0.3, 0), qml.RX(0.3, wires=[0])),
            (g.RX(0.3, 0).dagger(), qml.RX(0.3, wires=[0]).inv()),
            (g.RX(0.3, 0).dagger().dagger(), qml.RX(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RX(0.3, 0).controlled(1), qml.CRX(0.3, wires=[1, 0])),
            (g.RX(0.3, 0).controlled(1).dagger(), qml.CRX(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RX(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRX(0.3, wires=[1, 0]).inv().inv()),
            (g.RY(0.3, 0), qml.RY(0.3, wires=[0])),
            (g.RY(0.3, 0).dagger(), qml.RY(0.3, wires=[0]).inv()),
            (g.RY(0.3, 0).dagger().dagger(), qml.RY(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RY(0.3, 0).controlled(1), qml.CRY(0.3, wires=[1, 0])),
            (g.RY(0.3, 0).controlled(1).dagger(), qml.CRY(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RY(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRY(0.3, wires=[1, 0]).inv().inv()),
            (g.RZ(0.3, 0), qml.RZ(0.3, wires=[0])),
            (g.RZ(0.3, 0).dagger(), qml.RZ(0.3, wires=[0]).inv()),
            (g.RZ(0.3, 0).dagger().dagger(), qml.RZ(0.3,
                                                    wires=[0]).inv().inv()),
            (g.RZ(0.3, 0).controlled(1), qml.CRZ(0.3, wires=[1, 0])),
            (g.RZ(0.3, 0).controlled(1).dagger(), qml.CRZ(0.3,
                                                          wires=[1, 0]).inv()),
            (g.RZ(0.3, 0).controlled(1).dagger().dagger(),
             qml.CRZ(0.3, wires=[1, 0]).inv().inv()),
            (g.CPHASE(0.3, 0, 1), plf.ops.CPHASE(0.3, 3, wires=[0, 1])),
            (g.CPHASE(0.3, 0, 1).dagger(), plf.ops.CPHASE(0.3, 3,
                                                          wires=[0, 1]).inv()),
            (
                g.CPHASE(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 3, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE00(0.3, 0, 1), plf.ops.CPHASE(0.3, 0, wires=[0, 1])),
            (g.CPHASE00(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv()),
            (
                g.CPHASE00(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 0, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE01(0.3, 0, 1), plf.ops.CPHASE(0.3, 1, wires=[0, 1])),
            (g.CPHASE01(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv()),
            (
                g.CPHASE01(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 1, wires=[0, 1]).inv().inv(),
            ),
            (g.CPHASE10(0.3, 0, 1), plf.ops.CPHASE(0.3, 2, wires=[0, 1])),
            (g.CPHASE10(0.3, 0, 1).dagger(),
             plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv()),
            (
                g.CPHASE10(0.3, 0, 1).dagger().dagger(),
                plf.ops.CPHASE(0.3, 2, wires=[0, 1]).inv().inv(),
            ),
            (g.CSWAP(0, 1, 2), qml.CSWAP(wires=[0, 1, 2])),
            (g.CSWAP(0, 1, 2).dagger(), qml.CSWAP(wires=[0, 1, 2]).inv()),
            (g.CSWAP(0, 1, 2).dagger().dagger(),
             qml.CSWAP(wires=[0, 1, 2]).inv().inv()),
            (g.CCNOT(0, 1, 2), plf.ops.CCNOT(wires=[0, 1, 2])),
            (g.CCNOT(0, 1, 2).dagger(), plf.ops.CCNOT(wires=[0, 1, 2]).inv()),
            (g.CCNOT(0, 1, 2).dagger().dagger(),
             plf.ops.CCNOT(wires=[0, 1, 2]).inv().inv()),
        ],
    )
    def test_convert_operation(self, pyquil_operation, expected_pl_operation):
        """Test that single pyquil gates are properly converted."""
        program = pyquil.Program()

        program += pyquil_operation

        with OperationRecorder() as rec:
            loader = load_program(program)
            loader(wires=range(len(loader.defined_qubits)))

        assert rec.queue[0].name == expected_pl_operation.name
        assert rec.queue[0].wires == expected_pl_operation.wires
        assert rec.queue[0].params == expected_pl_operation.params

    def test_convert_simple_program(self):
        """Test that a simple program is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        # The wires should be assigned as
        # 0  1  2  3  7
        # 0  1  2  3  4

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]),
            qml.CNOT(wires=[0, 3]),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_simple_program_with_parameters(self):
        """Test that a simple program with parameters is properly converted."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.H(0)

        a, b, c = 0.1, 0.2, 0.3

        parameter_map = {"alpha": a, "beta": b, "gamma": c}

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_parameter_not_given_error(self):
        """Test that the correct error is raised if a parameter is not given."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)

        a = 0.1

        parameter_map = {"alpha": a}

        with pytest.raises(
                qml.DeviceError,
                match=
                "The PyQuil program defines a variable .* that is not present in the given variable map",
        ):
            load_program(program)(wires=range(2), parameter_map=parameter_map)

    def test_convert_simple_program_with_parameters_mixed_keys(self):
        """Test that a parametrized program is properly converted when
        the variable map contains mixed key types."""
        program = pyquil.Program()

        alpha = program.declare("alpha", "REAL")
        beta = program.declare("beta", "REAL")
        gamma = program.declare("gamma", "REAL")
        delta = program.declare("delta", "REAL")

        program += g.H(0)
        program += g.CNOT(0, 1)
        program += g.RX(alpha, 1)
        program += g.RZ(beta, 1)
        program += g.RX(gamma, 1)
        program += g.CNOT(0, 1)
        program += g.RZ(delta, 0)
        program += g.H(0)

        a, b, c, d = 0.1, 0.2, 0.3, 0.4

        parameter_map = {"alpha": a, beta: b, gamma: c, "delta": d}

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2), parameter_map=parameter_map)

        expected_queue = [
            qml.Hadamard(0),
            qml.CNOT(wires=[0, 1]),
            qml.RX(0.1, wires=[1]),
            qml.RZ(0.2, wires=[1]),
            qml.RX(0.3, wires=[1]),
            qml.CNOT(wires=[0, 1]),
            qml.RZ(0.4, wires=[0]),
            qml.Hadamard(0),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_simple_program_wire_assignment(self):
        """Test that the assignment of qubits to wires works as expected."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1)
        program += g.CNOT(0, 3)
        program += g.H(2)
        program += g.H(7)
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=[3, 6, 4, 9, 1])

        # The wires should be assigned as
        # 0  1  2  3  7
        # 3  6  4  9  1

        expected_queue = [
            qml.Hadamard(3),
            qml.RZ(0.34, wires=[6]),
            qml.CNOT(wires=[3, 9]),
            qml.Hadamard(4),
            qml.Hadamard(1),
            qml.PauliX(1),
            qml.PauliY(6),
            qml.RZ(0.34, wires=[6]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    @pytest.mark.parametrize("wires", [[0, 1, 2, 3], [4, 5]])
    def test_convert_wire_error(self, wires):
        """Test that the conversion raises an error if the given number 
        of wires doesn't match the number of qubits in the Program."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.H(1)
        program += g.H(2)

        with pytest.raises(
                qml.DeviceError,
                match=
                "The number of given wires does not match the number of qubits in the PyQuil Program",
        ):
            load_program(program)(wires=wires)

    def test_convert_program_with_inverses(self):
        """Test that a program with inverses is properly converted."""
        program = pyquil.Program()

        program += g.H(0)
        program += g.RZ(0.34, 1).dagger()
        program += g.CNOT(0, 3).dagger()
        program += g.H(2)
        program += g.H(7).dagger().dagger()
        program += g.X(7).dagger()
        program += g.X(7)
        program += g.Y(1)
        program += g.RZ(0.34, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            qml.Hadamard(0),
            qml.RZ(0.34, wires=[1]).inv(),
            qml.CNOT(wires=[0, 3]).inv(),
            qml.Hadamard(2),
            qml.Hadamard(4),
            qml.PauliX(4).inv(),
            qml.PauliX(4),
            qml.PauliY(1),
            qml.RZ(0.34, wires=[1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_operations(self):
        """Test that a program with controlled operations is properly converted."""
        program = pyquil.Program()

        program += g.RZ(0.34, 1)
        program += g.RY(0.2, 3).controlled(2)
        program += g.RX(0.4, 2).controlled(0)
        program += g.CNOT(1, 4)
        program += g.CNOT(1, 6).controlled(3)
        program += g.X(3).controlled(4).controlled(1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(6))

        expected_queue = [
            qml.RZ(0.34, wires=[1]),
            qml.CRY(0.2, wires=[2, 3]),
            qml.CRX(0.4, wires=[0, 2]),
            qml.CNOT(wires=[1, 4]),
            plf.ops.CCNOT(wires=[3, 1, 5]),
            plf.ops.CCNOT(wires=[1, 4, 3]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_operations_not_in_pl_core(
            self, tol):
        """Test that a program with controlled operations out of scope of PL core/PLF 
        is properly converted, i.e. the operations are replaced with controlled operations."""
        program = pyquil.Program()

        CS_matrix = np.eye(4, dtype=complex)
        CS_matrix[3, 3] = 1j

        CCT_matrix = np.eye(8, dtype=complex)
        CCT_matrix[7, 7] = np.exp(1j * np.pi / 4)

        program += g.CNOT(0, 1)
        program += g.S(0).controlled(1)
        program += g.S(1).controlled(0)
        program += g.T(0).controlled(1).controlled(2)
        program += g.T(1).controlled(0).controlled(2)
        program += g.T(2).controlled(1).controlled(0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(CS_matrix, wires=[1, 0]),
            qml.QubitUnitary(CS_matrix, wires=[0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 1, 0]),
            qml.QubitUnitary(CCT_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(CCT_matrix, wires=[0, 1, 2]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.params,
                               expected.params,
                               atol=tol,
                               rtol=0)

    def test_convert_program_with_controlled_dagger_operations(self):
        """Test that a program that combines controlled and daggered operations
        is properly converted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1).controlled(2)
        program += g.CNOT(0, 1).dagger().controlled(2)
        program += g.CNOT(0, 1).controlled(2).dagger()
        program += g.CNOT(0, 1).dagger().controlled(2).dagger()
        program += g.RX(0.3, 3).controlled(4)
        program += g.RX(0.2, 3).controlled(4).dagger()
        program += g.RX(0.3, 3).dagger().controlled(4)
        program += g.RX(0.2, 3).dagger().controlled(4).dagger()
        program += g.X(2).dagger().controlled(4).controlled(1).dagger()
        program += g.X(0).dagger().controlled(4).controlled(1)
        program += g.X(0).dagger().controlled(4).dagger().dagger().controlled(
            1).dagger()

        with OperationRecorder() as rec:
            load_program(program)(wires=range(5))

        expected_queue = [
            plf.ops.CCNOT(wires=[2, 0, 1]),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]).inv(),
            plf.ops.CCNOT(wires=[2, 0, 1]),
            qml.CRX(0.3, wires=[4, 3]),
            qml.CRX(0.2, wires=[4, 3]).inv(),
            qml.CRX(0.3, wires=[4, 3]).inv(),
            qml.CRX(0.2, wires=[4, 3]),
            plf.ops.CCNOT(wires=[1, 4, 2]),
            plf.ops.CCNOT(wires=[1, 4, 0]).inv(),
            plf.ops.CCNOT(wires=[1, 4, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_defgates(self):
        """Test that a program that defines its own gates is properly converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])

        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)
        sqrt_x_t3 = np.kron(sqrt_x, sqrt_x_t2)

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()
        sqrt_x_t3_definition = pyquil.quil.DefGate("SQRT-X-T3", sqrt_x_t3)
        SQRT_X_T3 = sqrt_x_t3_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition
        program += sqrt_x_t3_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0)
        program += SQRT_X_T2(1, 2)
        program += SQRT_X_T3(1, 0, 2)
        program += g.CNOT(0, 1)
        program += g.CNOT(1, 2)
        program += g.CNOT(2, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(sqrt_x, wires=[0]),
            qml.QubitUnitary(sqrt_x_t2, wires=[1, 2]),
            qml.QubitUnitary(sqrt_x_t3, wires=[1, 0, 2]),
            qml.CNOT(wires=[0, 1]),
            qml.CNOT(wires=[1, 2]),
            qml.CNOT(wires=[2, 0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert converted.params == expected.params

    def test_convert_program_with_controlled_defgates(self, tol):
        """Test that a program with controlled defined gates is properly
        converted."""
        program = pyquil.Program()

        sqrt_x = np.array([[0.5 + 0.5j, 0.5 - 0.5j], [0.5 - 0.5j, 0.5 + 0.5j]])
        sqrt_x_t2 = np.kron(sqrt_x, sqrt_x)

        c_sqrt_x = np.eye(4, dtype=complex)
        c_sqrt_x[2:, 2:] = sqrt_x

        c_sqrt_x_t2 = np.eye(8, dtype=complex)
        c_sqrt_x_t2[4:, 4:] = sqrt_x_t2

        sqrt_x_definition = pyquil.quil.DefGate("SQRT-X", sqrt_x)
        SQRT_X = sqrt_x_definition.get_constructor()
        sqrt_x_t2_definition = pyquil.quil.DefGate("SQRT-X-T2", sqrt_x_t2)
        SQRT_X_T2 = sqrt_x_t2_definition.get_constructor()

        program += sqrt_x_definition
        program += sqrt_x_t2_definition

        program += g.CNOT(0, 1)
        program += SQRT_X(0).controlled(1)
        program += SQRT_X_T2(1, 2).controlled(0)
        program += g.X(0).controlled(1)
        program += g.RX(0.4, 0)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(c_sqrt_x, wires=[1, 0]),
            qml.QubitUnitary(c_sqrt_x_t2, wires=[0, 1, 2]),
            qml.CNOT(wires=[1, 0]),
            qml.RX(0.4, wires=[0]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.allclose(converted.params,
                               expected.params,
                               atol=tol,
                               rtol=0)

    def test_convert_program_with_defpermutationgates(self):
        """Test that a program with gates defined via DefPermutationGate is 
        properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(2))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_matrix, wires=[0, 1]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.params, expected.params)

    def test_convert_program_with_controlled_defpermutationgates(self):
        """Test that a program that uses controlled permutation gates 
        is properly converted."""
        program = pyquil.Program()

        expected_matrix = np.eye(4)
        expected_matrix = expected_matrix[:, [1, 0, 3, 2]]

        expected_controlled_matrix = np.eye(8)
        expected_controlled_matrix[4:, 4:] = expected_matrix

        x_plus_x_definition = pyquil.quil.DefPermutationGate(
            "X+X", [1, 0, 3, 2])
        X_plus_X = x_plus_x_definition.get_constructor()

        program += x_plus_x_definition

        program += g.CNOT(0, 1)
        program += X_plus_X(0, 1).controlled(2)
        program += X_plus_X(1, 2).controlled(0)
        program += g.CNOT(0, 1)

        with OperationRecorder() as rec:
            load_program(program)(wires=range(3))

        expected_queue = [
            qml.CNOT(wires=[0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[2, 0, 1]),
            qml.QubitUnitary(expected_controlled_matrix, wires=[0, 1, 2]),
            qml.CNOT(wires=[0, 1]),
        ]

        for converted, expected in zip(rec.queue, expected_queue):
            assert converted.name == expected.name
            assert converted.wires == expected.wires
            assert np.array_equal(converted.params, expected.params)

    def test_forked_gate_error(self):
        """Test that an error is raised if conversion of a 
        forked gate is attempted."""
        program = pyquil.Program()

        program += g.CNOT(0, 1)
        program += g.RX(0.3, 1).forked(2, [0.5])
        program += g.CNOT(0, 1)

        with pytest.raises(
                qml.DeviceError,
                match=
                "Forked gates can not be imported into PennyLane, as this functionality is not supported",
        ):
            load_program(program)(wires=range(3))
 def circuit(x):
     qml.RX(x, wires=[0])
     qml.CNOT(wires=[0, 1])
     qml.SWAP(wires=[1, 0])
     qml.RZ(-0.2, wires=[1])
     return qml.probs(wires=[0]), qml.var(qml.Hermitian(H, wires=1))