Beispiel #1
0
def from_pennylane(tape: QuantumTape) -> Circuit:
    """Returns a Mitiq circuit equivalent to the input QuantumTape.

    Args:
        tape: Pennylane QuantumTape to convert to a Mitiq circuit.

    Returns:
        Mitiq circuit representation equivalent to the input QuantumTape.
    """
    try:
        wires = sorted(tape.wires)
    except TypeError:
        raise UnsupportedQuantumTapeError(
            f"The wires of the tape must be sortable, but could not sort "
            f"{tape.wires}.")

    for i in range(len(wires)):
        if wires[i] != i:
            raise UnsupportedQuantumTapeError(
                "The wire labels of the tape must contiguously pack 0 "
                "to n-1, for n wires.")

    if len(tape.measurements) > 0:
        raise UnsupportedQuantumTapeError(
            "Measurements are not supported on the input tape. "
            "They should be subsequently added by the executor.")

    tape = tape.expand(stop_at=lambda obj: obj.name in SUPPORTED)
    qasm = tape.to_openqasm(rotations=False, wires=wires, measure_all=False)

    return cirq_from_qasm(qasm)
Beispiel #2
0
    def test_differentiable_expand(self, mocker, tol):
        """Test that operation and nested tapes expansion
        is differentiable"""
        spy = mocker.spy(QuantumTape, "jacobian")
        mock = mocker.patch.object(qml.operation.Operation, "do_check_domain",
                                   False)

        class U3(qml.U3):
            def expand(self):
                tape = QuantumTape()
                theta, phi, lam = self.data
                wires = self.wires
                tape._ops += [
                    qml.Rot(lam, theta, -lam, wires=wires),
                    qml.PhaseShift(phi + lam, wires=wires),
                ]
                return tape

        qtape = QuantumTape()

        dev = qml.device("default.qubit.tf", wires=1)
        a = np.array(0.1)
        p = tf.Variable([0.1, 0.2, 0.3], dtype=tf.float64)

        with tf.GradientTape() as tape:

            with qtape:
                qml.RX(a, wires=0)
                U3(p[0], p[1], p[2], wires=0)
                qml.expval(qml.PauliX(0))

            qtape = qtape.expand()

            assert [i.name
                    for i in qtape.operations] == ["RX", "Rot", "PhaseShift"]
            assert np.all(
                qtape.get_parameters() == [a, p[2], p[0], -p[2], p[1] + p[2]])

            res = qtape.execute(device=dev)

        expected = tf.cos(a) * tf.cos(p[1]) * tf.sin(
            p[0]) + tf.sin(a) * (tf.cos(p[2]) * tf.sin(p[1]) +
                                 tf.cos(p[0]) * tf.cos(p[1]) * tf.sin(p[2]))
        assert np.allclose(res, expected, atol=tol, rtol=0)

        res = tape.jacobian(res, p)
        expected = np.array([
            tf.cos(p[1]) * (tf.cos(a) * tf.cos(p[0]) -
                            tf.sin(a) * tf.sin(p[0]) * tf.sin(p[2])),
            tf.cos(p[1]) * tf.cos(p[2]) * tf.sin(a) - tf.sin(p[1]) *
            (tf.cos(a) * tf.sin(p[0]) +
             tf.cos(p[0]) * tf.sin(a) * tf.sin(p[2])),
            tf.sin(a) * (tf.cos(p[0]) * tf.cos(p[1]) * tf.cos(p[2]) -
                         tf.sin(p[1]) * tf.sin(p[2])),
        ])
        assert np.allclose(res, expected, atol=tol, rtol=0)
        spy.assert_not_called()
Beispiel #3
0
        def cost_fn(a, p, device):
            tape = QuantumTape()

            with tape:
                qml.RX(a, wires=0)
                U3(*p, wires=0)
                qml.expval(qml.PauliX(0))

            tape = tape.expand()

            assert [i.name for i in tape.operations] == ["RX", "Rot", "PhaseShift"]
            assert np.all(tape.get_parameters() == [a, p[2], p[0], -p[2], p[1] + p[2]])

            return tape.execute(device=device)
Beispiel #4
0
        def cost_fn(a, p, device):
            tape = QuantumTape()

            with tape:
                qml.RX(a, wires=0)
                U3(*p, wires=0)
                qml.expval(qml.PauliX(0))

            tape = AutogradInterface.apply(tape.expand())

            assert tape.trainable_params == {1, 2, 3, 4}
            assert [i.name for i in tape.operations] == ["RX", "Rot", "PhaseShift"]
            assert np.all(np.array(tape.get_parameters()) == [p[2], p[0], -p[2], p[1] + p[2]])

            return tape.execute(device=device)
Beispiel #5
0
    def test_differentiable_expand(self, mocker, tol):
        """Test that operation and nested tapes expansion
        is differentiable"""
        mock = mocker.patch.object(qml.operation.Operation, "do_check_domain",
                                   False)

        class U3(qml.U3):
            def expand(self):
                tape = QuantumTape()
                theta, phi, lam = self.data
                wires = self.wires
                tape._ops += [
                    qml.Rot(lam, theta, -lam, wires=wires),
                    qml.PhaseShift(phi + lam, wires=wires),
                ]
                return tape

        tape = QuantumTape()

        dev = qml.device("default.qubit", wires=1)
        a = np.array(0.1)
        p_val = [0.1, 0.2, 0.3]
        p = torch.tensor(p_val, requires_grad=True)

        with tape:
            qml.RX(a, wires=0)
            U3(p[0], p[1], p[2], wires=0)
            qml.expval(qml.PauliX(0))

        tape = TorchInterface.apply(tape.expand())

        assert tape.trainable_params == {1, 2, 3, 4}
        assert [i.name for i in tape.operations] == ["RX", "Rot", "PhaseShift"]

        tape_params = [i.detach().numpy() for i in tape.get_parameters()]
        assert np.allclose(
            tape_params, [p_val[2], p_val[0], -p_val[2], p_val[1] + p_val[2]],
            atol=tol,
            rtol=0)

        res = tape.execute(device=dev)

        expected = np.cos(a) * np.cos(p_val[1]) * np.sin(p_val[0]) + np.sin(
            a) * (np.cos(p_val[2]) * np.sin(p_val[1]) +
                  np.cos(p_val[0]) * np.cos(p_val[1]) * np.sin(p_val[2]))
        assert np.allclose(res.detach().numpy(), expected, atol=tol, rtol=0)

        res.backward()
        expected = np.array([
            np.cos(p_val[1]) *
            (np.cos(a) * np.cos(p_val[0]) -
             np.sin(a) * np.sin(p_val[0]) * np.sin(p_val[2])),
            np.cos(p_val[1]) * np.cos(p_val[2]) * np.sin(a) -
            np.sin(p_val[1]) *
            (np.cos(a) * np.sin(p_val[0]) +
             np.cos(p_val[0]) * np.sin(a) * np.sin(p_val[2])),
            np.sin(a) *
            (np.cos(p_val[0]) * np.cos(p_val[1]) * np.cos(p_val[2]) -
             np.sin(p_val[1]) * np.sin(p_val[2])),
        ])
        assert np.allclose(p.grad, expected, atol=tol, rtol=0)