Example #1
0
    def test_var(self, shots, qvm, compiler):
        """Tests for variance calculation"""
        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        phi = 0.543
        theta = 0.6543

        with qml.tape.QuantumTape() as tape:
            qml.RX(phi, wires=[0])
            qml.RY(theta, wires=[0])
            O1 = qml.var(qml.PauliZ(wires=[0]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        var = np.array([dev.var(O1.obs)])
        expected = 0.25 * (3 - np.cos(2 * theta) -
                           2 * np.cos(theta)**2 * np.cos(2 * phi))

        self.assertAlmostEqual(var, expected, delta=3 / np.sqrt(shots))
Example #2
0
    def test_var(self, shots, qvm, compiler):
        """Tests for variance calculation"""
        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        phi = 0.543
        theta = 0.6543

        O1 = qml.var(qml.PauliZ(wires=[0]))

        circuit_graph = CircuitGraph([qml.RX(phi, wires=[0]), qml.RY(theta, wires=[0])] + [O1], {}, dev.wires)

        # test correct variance for <Z> of a rotated state
        dev.apply(circuit_graph.operations, rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        var = np.array([dev.var(O1)])
        expected = 0.25 * (3 - np.cos(2 * theta) - 2 * np.cos(theta) ** 2 * np.cos(2 * phi))

        self.assertAlmostEqual(var, expected, delta=3 / np.sqrt(shots))
Example #3
0
    def test_pauliz_expectation(self, shots, qvm, compiler):
        """Test that PauliZ expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device='2q-qvm', shots=shots)
        dev.apply('RX', wires=[0], par=[theta])
        dev.apply('RX', wires=[1], par=[phi])
        dev.apply('CNOT', wires=[0, 1], par=[])

        O = qml.expval.PauliZ
        name = 'PauliZ'

        dev._expval_queue = [O(wires=[0], do_queue=False), O(wires=[1], do_queue=False)]
        res = dev.pre_expval()

        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(res, np.array([np.cos(theta), np.cos(theta)*np.cos(phi)]), delta=3/np.sqrt(shots))
Example #4
0
    def test_identity_expectation(self, shots, qvm, compiler):
        """Test that identity expectation value (i.e. the trace) is 1"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device='2q-qvm', shots=shots)
        dev.apply('RX', wires=[0], par=[theta])
        dev.apply('RX', wires=[1], par=[phi])
        dev.apply('CNOT', wires=[0, 1], par=[])

        O = qml.expval.qubit.Identity
        name = 'Identity'

        dev._expval_queue = [O(wires=[0], do_queue=False), O(wires=[1], do_queue=False)]
        res = dev.pre_expval()

        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])

        # below are the analytic expectation values for this circuit (trace should always be 1)
        self.assertAllAlmostEqual(res, np.array([1, 1]), delta=3/np.sqrt(shots))
Example #5
0
    def test_sample_values(self, qvm, tol):
        """Tests if the samples returned by sample have
        the correct values
        """
        dev = plf.QVMDevice(device="1q-qvm", shots=10)

        O1 = qml.expval(qml.PauliZ(wires=[0]))

        circuit_graph = CircuitGraph([qml.RX(1.5708, wires=[0])] + [O1], {})

        dev.apply(circuit_graph.operations,
                  rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1)

        # s1 should only contain 1 and -1
        self.assertAllAlmostEqual(s1**2, 1, delta=tol)
        self.assertAllAlmostEqual(s1, 1 - 2 * dev._samples[:, 0], delta=tol)
Example #6
0
    def test_sample_values_hermitian(self, qvm, tol):
        """Tests if the samples of a Hermitian observable returned by sample have
        the correct values
        """
        theta = 0.543
        shots = 1_000_000
        A = np.array([[1, 2j], [-2j, 0]])

        dev = plf.QVMDevice(device="1q-qvm", shots=shots)

        O1 = qml.sample(qml.Hermitian(A, wires=[0]))

        circuit_graph = CircuitGraph([qml.RX(theta, wires=[0])] + [O1], {},
                                     dev.wires)

        dev.apply(circuit_graph.operations,
                  rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1)

        # s1 should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A)
        assert np.allclose(sorted(list(set(s1))),
                           sorted(eigvals),
                           atol=tol,
                           rtol=0)

        # the analytic mean is 2*sin(theta)+0.5*cos(theta)+0.5
        assert np.allclose(np.mean(s1),
                           2 * np.sin(theta) + 0.5 * np.cos(theta) + 0.5,
                           atol=0.1,
                           rtol=0)

        # the analytic variance is 0.25*(sin(theta)-4*cos(theta))^2
        assert np.allclose(np.var(s1),
                           0.25 * (np.sin(theta) - 4 * np.cos(theta))**2,
                           atol=0.1,
                           rtol=0)
Example #7
0
    def test_hermitian_expectation(self, shots, qvm, compiler):
        """Test that arbitrary Hermitian expectation values are correct.

        As the results coming from the qvm are stochastic, a constraint of 3 out of 5 runs was added.
        """

        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)
        O1 = qml.expval(qml.Hermitian(H, wires=[0]))
        O2 = qml.expval(qml.Hermitian(H, wires=[1]))

        circuit_graph = CircuitGraph(
            [
                qml.RY(theta, wires=[0]),
                qml.RY(phi, wires=[1]),
                qml.CNOT(wires=[0, 1])
            ] + [O1, O2],
            {},
        )

        dev.apply(circuit_graph.operations,
                  rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1), dev.expval(O2)])

        # below are the analytic expectation values for this circuit with arbitrary
        # Hermitian observable H
        a = H[0, 0]
        re_b = H[0, 1].real
        d = H[1, 1]
        ev1 = ((a - d) * np.cos(theta) +
               2 * re_b * np.sin(theta) * np.sin(phi) + a + d) / 2
        ev2 = ((a - d) * np.cos(theta) * np.cos(phi) + 2 * re_b * np.sin(phi) +
               a + d) / 2
        expected = np.array([ev1, ev2])

        self.assertAllAlmostEqual(res, expected, delta=4 / np.sqrt(shots))
Example #8
0
    def test_sample_values_hermitian_multi_qubit(self, qvm, tol):
        """Tests if the samples of a multi-qubit Hermitian observable returned by sample have
        the correct values
        """
        theta = 0.543
        shots = 100_000

        A = np.array([
            [1, 2j, 1 - 2j, 0.5j],
            [-2j, 0, 3 + 4j, 1],
            [1 + 2j, 3 - 4j, 0.75, 1.5 - 2j],
            [-0.5j, 1, 1.5 + 2j, -1],
        ])

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RY(2 * theta, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.sample(qml.Hermitian(A, wires=[0, 1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O1.obs)

        # s1 should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A)
        assert np.allclose(sorted(list(set(s1))),
                           sorted(eigvals),
                           atol=tol,
                           rtol=0)

        # make sure the mean matches the analytic mean
        expected = (88 * np.sin(theta) + 24 * np.sin(2 * theta) -
                    40 * np.sin(3 * theta) + 5 * np.cos(theta) -
                    6 * np.cos(2 * theta) + 27 * np.cos(3 * theta) + 6) / 32
        assert np.allclose(np.mean(s1), expected, atol=0.1, rtol=0)
Example #9
0
    def test_var(self, shots):
        """Tests for variance calculation"""
        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        phi = 0.543
        theta = 0.6543

        # test correct variance for <Z> of a rotated state
        dev.apply("RX", wires=[0], par=[phi])
        dev.apply("RY", wires=[0], par=[theta])

        O = qml.PauliZ
        name = "PauliZ"

        dev._obs_queue = [O(wires=[0], do_queue=False)]
        dev.pre_measure()

        var = dev.var(name, [0], [])
        expected = 0.25 * (3 - np.cos(2 * theta) - 2 * np.cos(theta) ** 2 * np.cos(2 * phi))

        self.assertAlmostEqual(var, expected, delta=3 / np.sqrt(shots))
Example #10
0
    def test_pauliy_expectation(self, shots, qvm, compiler):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)
        dev.apply("RX", wires=[0], par=[theta])
        dev.apply("RX", wires=[1], par=[phi])
        dev.apply("CNOT", wires=[0, 1], par=[])

        O = qml.PauliY
        name = "PauliY"

        dev._obs_queue = [O(wires=[0], do_queue=False), O(wires=[1], do_queue=False)]
        dev.pre_measure()

        # below are the analytic expectation values for this circuit
        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])
        self.assertAllAlmostEqual(
            res, np.array([0, -np.cos(theta) * np.sin(phi)]), delta=3 / np.sqrt(shots)
        )
Example #11
0
    def test_hadamard_expectation(self, shots, qvm, compiler):
        """Test that Hadamard expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)
        dev.apply("RY", wires=[0], par=[theta])
        dev.apply("RY", wires=[1], par=[phi])
        dev.apply("CNOT", wires=[0, 1], par=[])

        O = qml.Hadamard
        name = "Hadamard"

        dev._obs_queue = [O(wires=[0], do_queue=False), O(wires=[1], do_queue=False)]
        dev.pre_measure()

        res = np.array([dev.expval(name, [0], []), dev.expval(name, [1], [])])
        # below are the analytic expectation values for this circuit
        expected = np.array(
            [np.sin(theta) * np.sin(phi) + np.cos(theta), np.cos(theta) * np.cos(phi) + np.sin(phi)]
        ) / np.sqrt(2)
        self.assertAllAlmostEqual(res, expected, delta=3 / np.sqrt(shots))
Example #12
0
    def test_identity_expectation(self, shots, qvm, compiler):
        """Test that identity expectation value (i.e. the trace) is 1"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        O1 = qml.expval(qml.Identity(wires=[0]))
        O2 = qml.expval(qml.Identity(wires=[1]))

        circuit_graph = CircuitGraph(
            [qml.RX(theta, wires=[0]), qml.RX(phi, wires=[1]), qml.CNOT(wires=[0, 1])], [O1, O2], dev.wires
        )

        dev.apply(circuit_graph.operations, rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1), dev.expval(O2)])

        # below are the analytic expectation values for this circuit (trace should always be 1)
        self.assertAllAlmostEqual(res, np.array([1, 1]), delta=3 / np.sqrt(shots))
Example #13
0
    def test_multi_mode_hermitian_expectation(self, shots, qvm, compiler):
        """Test that arbitrary multi-mode Hermitian expectation values are correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=10 * shots)
        dev.apply("RY", wires=[0], par=[theta])
        dev.apply("RY", wires=[1], par=[phi])
        dev.apply("CNOT", wires=[0, 1], par=[])

        O = qml.Hermitian
        name = "Hermitian"

        A = np.array(
            [
                [-6, 2 + 1j, -3, -5 + 2j],
                [2 - 1j, 0, 2 - 1j, -5 + 4j],
                [-3, 2 + 1j, 0, -4 + 3j],
                [-5 - 2j, -5 - 4j, -4 - 3j, -6],
            ]
        )

        dev._obs_queue = [O(A, wires=[0, 1], do_queue=False)]
        dev.pre_measure()

        res = np.array([dev.expval(name, [0, 1], [A])])

        # below is the analytic expectation value for this circuit with arbitrary
        # Hermitian observable A
        expected = 0.5 * (
            6 * np.cos(theta) * np.sin(phi)
            - np.sin(theta) * (8 * np.sin(phi) + 7 * np.cos(phi) + 3)
            - 2 * np.sin(phi)
            - 6 * np.cos(phi)
            - 6
        )

        self.assertAllAlmostEqual(res, expected, delta=4 / np.sqrt(shots))
Example #14
0
    def test_pauliy_expectation(self, shots, qvm, compiler):
        """Test that PauliY expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.PauliY(wires=[0]))
            O2 = qml.expval(qml.PauliY(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)
        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(res,
                                  np.array([0, -np.cos(theta) * np.sin(phi)]),
                                  delta=3 / np.sqrt(shots))
Example #15
0
    def test_paulix_expectation(self, shots):
        """Test that PauliX expectation value is correct"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-pyqvm", shots=shots)
        O1 = qml.expval(qml.PauliX(wires=[0]))
        O2 = qml.expval(qml.PauliX(wires=[1]))

        circuit_graph = CircuitGraph(
            [qml.RY(theta, wires=[0]), qml.RY(phi, wires=[1]), qml.CNOT(wires=[0, 1])] + [O1, O2],
            {},
        )

        dev.apply(circuit_graph.operations, rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1), dev.expval(O2)])
        # below are the analytic expectation values for this circuit
        self.assertAllAlmostEqual(
            res, np.array([np.sin(theta) * np.sin(phi), np.sin(phi)]), delta=3 / np.sqrt(shots)
        )
Example #16
0
    def test_multi_qubit_hermitian_expectation(self, shots, qvm, compiler):
        """Test that arbitrary multi-qubit Hermitian expectation values are correct"""
        theta = np.random.random()
        phi = np.random.random()

        A = np.array(
            [
                [-6, 2 + 1j, -3, -5 + 2j],
                [2 - 1j, 0, 2 - 1j, -5 + 4j],
                [-3, 2 + 1j, 0, -4 + 3j],
                [-5 - 2j, -5 - 4j, -4 - 3j, -6],
            ]
        )

        dev = plf.QVMDevice(device="2q-pyqvm", shots=10 * shots)
        O1 = qml.expval(qml.Hermitian(A, wires=[0, 1]))

        circuit_graph = CircuitGraph(
            [qml.RY(theta, wires=[0]), qml.RY(phi, wires=[1]), qml.CNOT(wires=[0, 1])] + [O1], {}
        )

        dev.apply(circuit_graph.operations, rotations=circuit_graph.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1)])
        # below is the analytic expectation value for this circuit with arbitrary
        # Hermitian observable A
        expected = 0.5 * (
            6 * np.cos(theta) * np.sin(phi)
            - np.sin(theta) * (8 * np.sin(phi) + 7 * np.cos(phi) + 3)
            - 2 * np.sin(phi)
            - 6 * np.cos(phi)
            - 6
        )

        self.assertAllAlmostEqual(res, expected, delta=6 / np.sqrt(shots))
Example #17
0
    def test_apply(self, op, apply_unitary, shots, qvm, compiler):
        """Test the application of gates to a state"""
        dev = plf.QVMDevice(device="3q-qvm",
                            shots=shots,
                            parametric_compilation=False)

        obs = qml.expval(qml.PauliZ(0))

        if op.name == "QubitUnitary":
            state = apply_unitary(U, 3)
        elif op.name == "BasisState":
            state = np.array([0, 0, 0, 0, 0, 0, 0, 1])
        elif op.name == "CPHASE":
            state = apply_unitary(test_operation_map["CPHASE"](0.432, 2), 3)
        elif op.name == "ISWAP":
            state = apply_unitary(test_operation_map["ISWAP"], 3)
        elif op.name == "PSWAP":
            state = apply_unitary(test_operation_map["PSWAP"](0.432), 3)
        else:
            state = apply_unitary(op.matrix, 3)

        with qml.tape.QuantumTape() as tape:
            qml.apply(op)
            obs

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = dev.expval(obs.obs)
        expected = np.vdot(state, np.kron(np.kron(Z, I), I) @ state)

        # verify the device is now in the expected state
        # Note we have increased the tolerance here, since we are only
        # performing 1024 shots.
        self.assertAllAlmostEqual(res, expected, delta=3 / np.sqrt(shots))
Example #18
0
    def test_identity_expectation(self, shots, qvm, compiler):
        """Test that identity expectation value (i.e. the trace) is 1"""
        theta = 0.432
        phi = 0.123

        dev = plf.QVMDevice(device="2q-qvm", shots=shots)

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.CNOT(wires=[0, 1])
            O1 = qml.expval(qml.Identity(wires=[0]))
            O2 = qml.expval(qml.Identity(wires=[1]))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = np.array([dev.expval(O1.obs), dev.expval(O2.obs)])

        # below are the analytic expectation values for this circuit (trace should always be 1)
        self.assertAllAlmostEqual(res,
                                  np.array([1, 1]),
                                  delta=3 / np.sqrt(shots))
Example #19
0
 def test_timeout_set_correctly(self, shots):
     """Test that the timeout attrbiute for the QuantumComputer stored by the QVMDevice
     is set correctly when passing a value as keyword argument"""
     device = np.random.choice(TEST_QPU_LATTICES)
     dev = plf.QVMDevice(device=device, shots=shots, timeout=100)
     assert dev.qc.compiler.client.timeout == 100
Example #20
0
    def test_apply(self, gate, apply_unitary, shots, qvm, compiler):
        """Test the application of gates"""
        dev = plf.QVMDevice(device="3q-qvm",
                            shots=shots,
                            parametric_compilation=False)

        try:
            # get the equivalent pennylane operation class
            op = getattr(qml.ops, gate)
        except AttributeError:
            # get the equivalent pennylane-forest operation class
            op = getattr(plf, gate)

        # the list of wires to apply the operation to
        w = list(range(op.num_wires))

        if op.par_domain == "A":
            # the parameter is an array
            if gate == "QubitUnitary":
                p = np.array(U)
                w = [0]
                state = apply_unitary(U, 3)
            elif gate == "BasisState":
                p = np.array([1, 1, 1])
                state = np.array([0, 0, 0, 0, 0, 0, 0, 1])
                w = list(range(dev.num_wires))

            with qml.tape.QuantumTape() as tape:
                op(p, wires=w)
                obs = qml.expval(qml.PauliZ(0))
        else:
            p = [0.432_423, 2, 0.324][:op.num_params]
            fn = test_operation_map[gate]
            if callable(fn):
                # if the default.qubit is an operation accepting parameters,
                # initialise it using the parameters generated above.
                O = fn(*p)
            else:
                # otherwise, the operation is simply an array.
                O = fn

            # calculate the expected output
            state = apply_unitary(O, 3)
            # Creating the tape using a parametrized operation
            if p:
                with qml.tape.QuantumTape() as tape:
                    op(*p, wires=w)
                    obs = qml.expval(qml.PauliZ(0))

            # Creating the tape using an operation that take no parameters
            else:
                with qml.tape.QuantumTape() as tape:
                    op(wires=w)
                    obs = qml.expval(qml.PauliZ(0))

        dev.apply(tape.operations, rotations=tape.diagonalizing_gates)

        dev._samples = dev.generate_samples()

        res = dev.expval(obs.obs)
        expected = np.vdot(state, np.kron(np.kron(Z, I), I) @ state)

        # verify the device is now in the expected state
        # Note we have increased the tolerance here, since we are only
        # performing 1024 shots.
        self.assertAllAlmostEqual(res, expected, delta=3 / np.sqrt(shots))
Example #21
0
 def test_raise_error_if_shots_is_not_positive(self, shots):
     """Test that instantiating a QVMDevice if the number of shots is not a postivie
     integer raises an error"""
     with pytest.raises(ValueError, match="Number of shots must be a positive integer."):
         dev = plf.QVMDevice(device="2q-qvm", shots=shots)
Example #22
0
 def test_raise_error_if_analytic_true(self, shots):
     """Test that instantiating a QVMDevice in analytic=True mode raises an error"""
     with pytest.raises(
             ValueError,
             match="QVM device cannot be run in analytic=True mode."):
         dev = plf.QVMDevice(device="2q-qvm", shots=shots, analytic=True)
Example #23
0
 def test_raise_error_if_shots_is_none(self, shots):
     """Test that instantiating a QVMDevice to be used for analytic computations raises an error"""
     with pytest.raises(
             ValueError,
             match="QVM device cannot be used for analytic computations."):
         dev = plf.QVMDevice(device="2q-qvm", shots=None)