def test_nonzero_shots(self):
        """Test that the wavefunction plugin provides correct result for high shot number"""
        shots = 10**2
        dev = qml.device("forest.numpy_wavefunction", wires=1, shots=shots)

        a = 0.543
        b = 0.123
        c = 0.987

        @qml.qnode(dev)
        def circuit(x, y, z):
            """Test QNode"""
            qml.BasisState(np.array([1]), wires=0)
            qml.Hadamard(wires=0)
            qml.Rot(x, y, z, wires=0)
            return qml.expval(qml.PauliZ(0))

        runs = []
        for _ in range(100):
            runs.append(circuit(a, b, c))

        expected_var = np.sqrt(1 / shots)
        print(np.mean(runs), np.cos(a) * np.sin(b))
        self.assertAlmostEqual(np.mean(runs),
                               np.cos(a) * np.sin(b),
                               delta=expected_var)
示例#2
0
    def test_single_argument_step(self, cost_fn, mocker, monkeypatch):
        """Test that a simple QNode with a single argument correctly performs an optimization step,
        and that the single-shot gradients generated have the correct shape"""

        opt = qml.ShotAdaptiveOptimizer(min_shots=10)
        spy_single_shot_expval = mocker.spy(opt,
                                            "_single_shot_expval_gradients")
        spy_single_shot_qnodes = mocker.spy(opt,
                                            "_single_shot_qnode_gradients")
        spy_grad = mocker.spy(opt, "compute_grad")

        x_init = 0.5
        new_x = opt.step(cost_fn, x_init)

        assert isinstance(new_x, float)
        assert new_x != x_init

        spy_grad.assert_called_once()

        if isinstance(cost_fn, qml.ExpvalCost):
            spy_single_shot_expval.assert_called_once()
            single_shot_grads = opt._single_shot_expval_gradients(
                cost_fn, [x_init], {})
        else:
            spy_single_shot_qnodes.assert_called_once()
            single_shot_grads = opt._single_shot_qnode_gradients(
                cost_fn, [x_init], {})

        # assert single shot gradients are computed correctly
        assert len(single_shot_grads) == 1
        assert single_shot_grads[0].shape == (10, )

        # monkeypatch the optimizer to use the same single shot gradients
        # as previously
        monkeypatch.setattr(opt, "_single_shot_qnode_gradients",
                            lambda *args, **kwargs: single_shot_grads)
        monkeypatch.setattr(opt, "_single_shot_expval_gradients",
                            lambda *args, **kwargs: single_shot_grads)

        # reset the shot budget
        opt.s = [np.array(10)]

        # check that the gradient and variance are computed correctly
        grad, grad_variance = opt.compute_grad(cost_fn, [x_init], {})
        assert len(grad) == 1
        assert len(grad_variance) == 1
        assert np.allclose(grad, np.mean(single_shot_grads))
        assert np.allclose(grad_variance, np.var(single_shot_grads, ddof=1))

        # check that the gradient and variance are computed correctly
        # with a different shot budget
        opt.s = [np.array(5)]
        grad, grad_variance = opt.compute_grad(cost_fn, [x_init], {})
        assert len(grad) == 1
        assert len(grad_variance) == 1
        assert np.allclose(grad, np.mean(single_shot_grads[0][:5]))
        assert np.allclose(grad_variance,
                           np.var(single_shot_grads[0][:5], ddof=1))
示例#3
0
    def test_multiple_argument_step(self, mocker, monkeypatch):
        """Test that a simple QNode with multiple scalar arguments correctly performs an optimization step,
        and that the single-shot gradients generated have the correct shape"""
        dev = qml.device("default.qubit", wires=1, shots=100)

        @qml.qnode(dev)
        def circuit(x, y):
            qml.RX(x, wires=0)
            qml.RY(y, wires=0)
            return qml.expval(qml.PauliZ(0))

        opt = qml.ShotAdaptiveOptimizer(min_shots=10)
        spy_single_shot = mocker.spy(opt, "_single_shot_qnode_gradients")
        spy_grad = mocker.spy(opt, "compute_grad")

        args = [0.1, 0.2]
        new_x = opt.step(circuit, *args)

        assert isinstance(new_x, list)
        assert len(new_x) == 2

        spy_single_shot.assert_called_once()
        spy_grad.assert_called_once()

        # assert single shot gradients are computed correctly
        single_shot_grads = opt._single_shot_qnode_gradients(circuit, args, {})
        assert len(single_shot_grads) == 2
        assert single_shot_grads[0].shape == (10, )

        # monkeypatch the optimizer to use the same single shot gradients
        # as previously
        monkeypatch.setattr(opt, "_single_shot_qnode_gradients",
                            lambda *args, **kwargs: single_shot_grads)

        # reset the shot budget
        opt.s = [np.array(10), np.array(10)]

        # check that the gradient and variance are computed correctly
        grad, grad_variance = opt.compute_grad(circuit, args, {})
        assert len(grad) == 2
        assert len(grad_variance) == 2
        assert np.allclose(grad, np.mean(single_shot_grads, axis=1))
        assert np.allclose(grad_variance,
                           np.var(single_shot_grads, ddof=1, axis=1))

        # check that the gradient and variance are computed correctly
        # with a different shot budget
        opt.s = [np.array(5), np.array(7)]
        grad, grad_variance = opt.compute_grad(circuit, args, {})
        assert len(grad) == 2
        assert len(grad_variance) == 2

        for p, s in zip(range(2), opt.s):
            assert np.allclose(grad[p], np.mean(single_shot_grads[p][:s]))
            assert np.allclose(grad_variance[p],
                               np.var(single_shot_grads[p][:s], ddof=1))
示例#4
0
    def test_sample_values_projector_multi_qubit(self, device, tol):
        """Tests if the samples of a multi-qubit Projector observable returned by sample have
        the correct values
        """
        n_wires = 2
        dev = device(n_wires)

        if dev.shots is None:
            pytest.skip("Device is in analytic mode, cannot test sampling.")

        if "Projector" not in dev.observables:
            pytest.skip(
                "Skipped because device does not support the Projector observable."
            )

        theta = 0.543

        @qml.qnode(dev)
        def circuit(basis_state):
            qml.RX(theta, wires=[0])
            qml.RY(2 * theta, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.sample(qml.Projector(basis_state, wires=[0, 1]))

        res = circuit([0, 0]).flatten()
        # res should only contain 0 or 1, the eigenvalues of the projector
        assert np.allclose(sorted(list(set(res.tolist()))), [0, 1],
                           atol=tol(dev.shots))
        expected = (np.cos(theta / 2) * np.cos(theta))**2
        assert np.allclose(np.mean(res), expected, atol=tol(dev.shots))

        res = circuit([0, 1]).flatten()
        assert np.allclose(sorted(list(set(res.tolist()))), [0, 1],
                           atol=tol(dev.shots))
        expected = (np.cos(theta / 2) * np.sin(theta))**2
        assert np.allclose(np.mean(res), expected, atol=tol(dev.shots))

        res = circuit([1, 0]).flatten()
        assert np.allclose(sorted(list(set(res.tolist()))), [0, 1],
                           atol=tol(dev.shots))
        expected = (np.sin(theta / 2) * np.sin(theta))**2
        assert np.allclose(np.mean(res), expected, atol=tol(dev.shots))

        res = circuit([1, 1]).flatten()
        assert np.allclose(sorted(list(set(res.tolist()))), [0, 1],
                           atol=tol(dev.shots))
        expected = (np.sin(theta / 2) * np.cos(theta))**2
        assert np.allclose(np.mean(res), expected, atol=tol(dev.shots))
    def test_gradient_integration(self, tol):
        """Test that temporarily setting the shots works
        for gradient computations"""
        dev = qml.device("default.qubit", wires=2, shots=None)
        a, b = np.array([0.543, -0.654], requires_grad=True)

        def cost_fn(a, b, shots):
            with qml.tape.JacobianTape() as tape:
                qml.RY(a, wires=0)
                qml.RX(b, wires=1)
                qml.CNOT(wires=[0, 1])
                qml.expval(qml.PauliY(1))

            return execute([tape],
                           dev,
                           gradient_fn=param_shift,
                           override_shots=shots)[0]

        res = qml.jacobian(cost_fn)(a, b, shots=[10000, 10000, 10000])
        assert dev.shots is None
        assert isinstance(res, tuple) and len(res) == 2
        assert res[0].shape == (3, )
        assert res[1].shape == (3, )

        expected = [np.sin(a) * np.sin(b), -np.cos(a) * np.cos(b)]
        assert all(
            np.allclose(np.mean(r, axis=0), e, atol=0.1, rtol=0)
            for r, e in zip(res, expected))
示例#6
0
    def test_sample_values_hermitian(self, tol):
        """Tests if the samples of a Hermitian observable returned by sample have
        the correct values
        """
        dev = plf.WavefunctionDevice(wires=1, shots=1_000_000)
        theta = 0.543

        A = np.array([[1, 2j], [-2j, 0]])

        with qml.tape.QuantumTape() as tape:
            qml.RX(theta, wires=[0])
            O = qml.sample(qml.Hermitian(A, wires=[0]))

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

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O.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)

        # 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
        )
示例#7
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 = 1000_000
        A = np.array([[1, 2j], [-2j, 0]])

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

        dev.apply('RX', wires=[0], par=[theta])
        dev._obs_queue = [qml.Hermitian(A, wires=[0], do_queue=False)]
        dev.pre_measure()

        s1 = dev.sample('Hermitian', [0], [A])

        # 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)
示例#8
0
    def test_no_readout_correction(self):
        """Test the QPU plugin with no readout correction"""
        device = np.random.choice(VALID_QPU_LATTICES)
        dev_qpu = qml.device(
            "forest.qpu",
            device=device,
            load_qc=False,
            readout_error=[0.9, 0.75],
            symmetrize_readout=None,
            calibrate_readout=None,
        )
        qubit = 0  # just run program on the first qubit

        @qml.qnode(dev_qpu)
        def circuit_Xpl():
            qml.RY(np.pi / 2, wires=qubit)
            return qml.expval(qml.PauliX(qubit))

        @qml.qnode(dev_qpu)
        def circuit_Xmi():
            qml.RY(-np.pi / 2, wires=qubit)
            return qml.expval(qml.PauliX(qubit))

        @qml.qnode(dev_qpu)
        def circuit_Ypl():
            qml.RX(-np.pi / 2, wires=qubit)
            return qml.expval(qml.PauliY(qubit))

        @qml.qnode(dev_qpu)
        def circuit_Ymi():
            qml.RX(np.pi / 2, wires=qubit)
            return qml.expval(qml.PauliY(qubit))

        @qml.qnode(dev_qpu)
        def circuit_Zpl():
            qml.RX(0.0, wires=qubit)
            return qml.expval(qml.PauliZ(qubit))

        @qml.qnode(dev_qpu)
        def circuit_Zmi():
            qml.RX(np.pi, wires=qubit)
            return qml.expval(qml.PauliZ(qubit))

        num_expts = 10
        results_unavged = np.zeros((num_expts, 6))

        for i in range(num_expts):
            results_unavged[i, :] = [
                circuit_Xpl(),
                circuit_Ypl(),
                circuit_Zpl(),
                circuit_Xmi(),
                circuit_Ymi(),
                circuit_Zmi(),
            ]

        results = np.mean(results_unavged, axis=0)

        assert np.allclose(results[:3], 0.8, atol=2e-2)
        assert np.allclose(results[3:], -0.5, atol=2e-2)
示例#9
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 = 100000

        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)

        dev.apply('RX', wires=[0], par=[theta])
        dev.apply('RY', wires=[1], par=[2 * theta])
        dev.apply('CNOT', wires=[0, 1], par=[])
        dev._obs_queue = [qml.Hermitian(A, wires=[0, 1], do_queue=False)]
        dev.pre_measure()

        s1 = dev.sample('Hermitian', [0, 1], [A])

        # 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)
示例#10
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
        )
示例#11
0
    def test_sample_values_hermitian(self, device, tol):
        """Tests if the samples of a Hermitian observable returned by sample have
        the correct values
        """
        n_wires = 1
        dev = device(n_wires)

        if dev.shots is None:
            pytest.skip("Device is in analytic mode, cannot test sampling.")

        if "Hermitian" not in dev.observables:
            pytest.skip("Skipped because device does not support the Hermitian observable.")

        A_ = np.array([[1, 2j], [-2j, 0]])
        theta = 0.543

        @qml.qnode(dev)
        def circuit():
            qml.RX(theta, wires=[0])
            return qml.sample(qml.Hermitian(A_, wires=0))

        res = circuit().flatten()

        # res should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A_)
        assert np.allclose(sorted(list(set(res.tolist()))), sorted(eigvals), atol=tol(dev.shots))
        # the analytic mean is 2*sin(theta)+0.5*cos(theta)+0.5
        assert np.allclose(
            np.mean(res), 2 * np.sin(theta) + 0.5 * np.cos(theta) + 0.5, atol=tol(False)
        )
        # the analytic variance is 0.25*(sin(theta)-4*cos(theta))^2
        assert np.allclose(
            np.var(res), 0.25 * (np.sin(theta) - 4 * np.cos(theta)) ** 2, atol=tol(False)
        )
def full_plotting(_fileTitle, _trainingLength, _currentRewardList):
    scores = []  # list containing scores from each episode
    scores_std = []  # List containing the std dev of the last 100 episodes
    scores_avg = []  # List containing the mean of the last 100 episodes
    scores_window = deque(maxlen=100)  # last 100 scores

    reward_list = _currentRewardList
    for i_episode in range(_trainingLength):
        score = reward_list[i_episode]

        scores_window.append(score)  # save most recent score
        scores.append(score)  # save most recent score
        scores_std.append(np.std(scores_window))  # save most recent std dev
        scores_avg.append(np.mean(scores_window))  # save most recent std dev

    na_raw = np.array(scores)
    na_mu = np.array(scores_avg)
    na_sigma = np.array(scores_std)

    # plot the scores
    f, (ax1, ax2) = plt.subplots(1,
                                 2,
                                 figsize=(12, 5),
                                 sharex=True,
                                 sharey=True)

    # plot the sores by episode
    ax1.plot(np.arange(len(na_raw)), na_raw, label='Raw Score')
    leg1 = ax1.legend()
    ax1.set_xlim(0, len(na_raw) + 1)
    ax1.set_ylabel('Score')
    ax1.set_xlabel('Episode #')
    ax1.set_title('raw scores')

    # plot the average of these scores
    ax2.axhline(y=100.,
                xmin=0.0,
                xmax=1.0,
                color='r',
                linestyle='--',
                linewidth=0.7,
                alpha=0.9,
                label='Solved')
    ax2.plot(np.arange(len(na_mu)), na_mu, label='Average Score')
    leg2 = ax2.legend()
    ax2.fill_between(np.arange(len(na_mu)),
                     na_mu + na_sigma,
                     na_mu - na_sigma,
                     facecolor='gray',
                     alpha=0.1)
    ax2.set_ylabel('Average Score')
    ax2.set_xlabel('Episode #')
    ax2.set_title('average scores')

    f.tight_layout()

    # f.savefig(fig_prefix + 'dqn.eps', format='eps', dpi=1200)
    f.savefig(_fileTitle + '_full.pdf', format='pdf')
示例#13
0
def mitigate_depolarizing_noise(K, num_wires, method, use_entries=None):
    r"""Estimate depolarizing noise rate(s) using on the diagonal entries of a kernel
    matrix and mitigate the noise, assuming a global depolarizing noise model.

    Args:
        K (array[float]): Noisy kernel matrix.
        num_wires (int): Number of wires/qubits of the quantum embedding kernel.
        method (``'single'`` | ``'average'`` | ``'split_channel'``): Strategy for mitigation

            * ``'single'``: An alias for ``'average'`` with ``len(use_entries)=1``.
            * ``'average'``: Estimate a global noise rate based on the average of the diagonal
              entries in ``use_entries``, which need to be measured on the quantum computer.
            * ``'split_channel'``: Estimate individual noise rates per embedding, requiring
              all diagonal entries to be measured on the quantum computer.
        use_entries (array[int]): Diagonal entries to use if method in ``['single', 'average']``.
            If ``None``, defaults to ``[0]`` (``'single'``) or ``range(len(K))`` (``'average'``).

    Returns:
        array[float]: Mitigated kernel matrix.

    Reference:
        This method is introduced in Section V in
        `arXiv:2105.02276 <https://arxiv.org/abs/2105.02276>`_.

    **Example:**

    For an example usage of ``mitigate_depolarizing_noise`` please refer to the
    `PennyLane demo on the kernel module <https://github.com/PennyLaneAI/qml/tree/master/demonstrations/tutorial_kernel_module.py>`_ or `the postprocessing demo for arXiv:2105.02276 <https://github.com/thubregtsen/qhack/blob/master/paper/post_processing_demo.py>`_.
    """
    dim = 2**num_wires

    if method == "single":
        if use_entries is None:
            use_entries = (0, )
        diagonal_element = K[use_entries[0], use_entries[0]]
        noise_rate = (1 - diagonal_element) * dim / (dim - 1)
        mitigated_matrix = (K - noise_rate / dim) / (1 - noise_rate)

    elif method == "average":
        if use_entries is None:
            diagonal_elements = np.diag(K)
        else:
            diagonal_elements = np.diag(K)[np.array(use_entries)]
        noise_rates = (1 - diagonal_elements) * dim / (dim - 1)
        mean_noise_rate = np.mean(noise_rates)
        mitigated_matrix = (K - mean_noise_rate / dim) / (1 - mean_noise_rate)

    elif method == "split_channel":
        eff_noise_rates = np.clip((1 - np.diag(K)) * dim / (dim - 1), 0.0, 1.0)
        noise_rates = 1 - np.sqrt(1 - eff_noise_rates)
        inverse_noise = (-np.outer(noise_rates, noise_rates) +
                         noise_rates.reshape(
                             (1, len(K))) + noise_rates.reshape((len(K), 1)))
        mitigated_matrix = (K - inverse_noise / dim) / (1 - inverse_noise)

    return mitigated_matrix
示例#14
0
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  random_layer() picks random wires."""
        n_rots = 500
        weights = np.random.randn(n_rots)

        with qml.utils.OperationRecorder() as rec:
            random_layer(weights=weights, wires=range(n_subsystems), ratio_imprim=0.3,
                         imprimitive=qml.CNOT, rotations=[RX, RY, RZ], seed=42)

        wires = [q._wires for q in rec.queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)
示例#15
0
def get_cell_centers(cells):
    """Get average coordinates per cell
    Args:
        cells (ndarray<int>): Cells as computed by `get_cells`
    Returns:
        centers (dict): Map from cell labels to mean coordinates of cells
        
    """
    centers = {}
    for _id in np.unique(cells):
        wheres = np.where(cells == _id)
        centers[_id] = np.array(
            [np.mean(where.astype(float)) for where in wheres])
    return centers
示例#16
0
    def test_sample_values_hermitian_multi_qubit(self, device, tol):
        """Tests if the samples of a multi-qubit Hermitian observable returned by sample have
        the correct values
        """
        n_wires = 2
        dev = device(n_wires)

        if dev.shots is None:
            pytest.skip("Device is in analytic mode, cannot test sampling.")

        if "Hermitian" not in dev.observables:
            pytest.skip("Skipped because device does not support the Hermitian observable.")

        theta = 0.543
        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],
            ]
        )

        @qml.qnode(dev)
        def circuit():
            qml.RX(theta, wires=[0])
            qml.RY(2 * theta, wires=[1])
            qml.CNOT(wires=[0, 1])
            return qml.sample(qml.Hermitian(A_, wires=[0, 1]))

        res = circuit().flatten()

        # res should only contain the eigenvalues of
        # the hermitian matrix
        eigvals = np.linalg.eigvalsh(A_)
        assert np.allclose(sorted(list(set(res.tolist()))), sorted(eigvals), atol=tol(dev.shots))

        # 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(res), expected, atol=tol(dev.shots))
示例#17
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)

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

        circuit_graph = CircuitGraph(
            [qml.RX(theta, wires=[0]), qml.RY(2 * theta, wires=[1]), qml.CNOT(wires=[0, 1])] + [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)

        # 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)
    def test_sample_values_hermitian_multi_qubit(self, tol):
        """Tests if the samples of a multi-qubit Hermitian observable returned by sample have
        the correct values
        """
        shots = 1_000_000
        dev = plf.NumpyWavefunctionDevice(wires=2, shots=shots)
        theta = 0.543

        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],
            ]
        )

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

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

        dev._samples = dev.generate_samples()

        s1 = dev.sample(O.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)
示例#19
0
    def compute_grad(
        self, objective_fn, args, kwargs
    ):  # pylint: disable=signature-differs,arguments-differ
        r"""Compute gradient of the objective function, as well as the variance of the gradient,
        at the given point.

        Args:
            objective_fn (function): the objective function for optimization
            args: arguments to the objective function
            kwargs: keyword arguments to the objective function

        Returns:
            tuple[array[float], array[float]]: a tuple of NumPy arrays containing the gradient
            :math:`\nabla f(x^{(t)})` and the variance of the gradient
        """
        if isinstance(objective_fn, qml.ExpvalCost):
            grads = self._single_shot_expval_gradients(objective_fn, args, kwargs)
        elif isinstance(objective_fn, qml.QNode) or hasattr(objective_fn, "device"):
            grads = self._single_shot_qnode_gradients(objective_fn, args, kwargs)
        else:
            raise ValueError(
                "The objective function must either be encoded as a single QNode or "
                "an ExpvalCost object for the Shot adaptive optimizer. "
            )

        # grads will have dimension [max(self.s), *params.shape]
        # For each parameter, we want to truncate the number of shots to self.s[idx],
        # and take the mean and the variance.
        gradients = []
        gradient_variances = []

        for i, grad in enumerate(grads):
            p_ind = np.ndindex(*grad.shape[1:])

            g = np.zeros_like(grad[0])
            s = np.zeros_like(grad[0])

            for idx in p_ind:
                grad_slice = grad[(slice(0, self.s[i][idx]),) + idx]
                g[idx] = np.mean(grad_slice)
                s[idx] = np.var(grad_slice, ddof=1)

            gradients.append(g)
            gradient_variances.append(s)

        return gradients, gradient_variances
示例#20
0
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  pennylane.templates.layers._random_layer() picks random wires."""
        np.random.seed(12)
        n_rots = 500
        dev = qml.device('default.qubit', wires=n_subsystems)
        weights = np.random.randn(n_rots)

        def circuit(weights):
            _random_layer(weights=weights, wires=range(n_subsystems))
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        qnode(weights)
        queue = qnode.queue
        wires = [q._wires for q in queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)
示例#21
0
    def test_nonzero_shots(self):
        """Test that the fock plugin provides correct result for high shot number"""
        shots = 10**2
        dev = qml.device("strawberryfields.fock", wires=1, cutoff_dim=10, shots=shots)

        @qml.qnode(dev)
        def circuit(x):
            qml.Displacement(x, 0, wires=0)
            return qml.expval(qml.NumberOperator(0))

        x = 1

        runs = []
        for _ in range(100):
            runs.append(circuit(x))

        expected_var = np.sqrt(1 / shots)
        assert np.allclose(np.mean(runs), x, atol=expected_var)
示例#22
0
    def test_nonzero_shots(self, tol):
        """Test that the default qubit plugin provides correct result for high shot number"""

        shots = 10 ** 5
        dev = qml.device("default.qubit", wires=1, shots=shots)

        p = 0.543

        @qml.qnode(dev)
        def circuit(x):
            """Test quantum function"""
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliY(0))

        runs = []
        for _ in range(100):
            runs.append(circuit(p))

        assert np.isclose(np.mean(runs), -np.sin(p), atol=tol, rtol=0)
示例#23
0
    def cost(self, var, features, labels):
        """Cost to be optimized during training.

        Args:
            var (list):weights of the model
            features (array):obervations to be evalueated by the model
            labels (array):labels associated to features

        Returns:
            loss: float
                loss of the model given x
        """
        model_output = \
            [self.neural_network(var, features=x_) for x_ in features]

        # if the interface is autograd, call custom losses
        if self.interface == "autograd":
            if self.type_problem == "regression":
                loss = square_loss(labels, model_output)
            elif self.type_problem == "classification":
                loss = square_loss(labels, model_output)
            elif self.type_problem == "multiclassification":
                model_output = np.array(model_output)
                preds = np.exp(model_output) / \
                        np.sum(np.exp(model_output), axis=1)[:, None]
                loss = cross_entropy(labels, preds)
            elif self.type_problem == "reinforcement_learning":
                loss = np.mean(square_loss(labels, model_output))

        # if the interface if tensorflow, call tensorflow losses
        elif self.interface == "tf":
            if self.type_problem == "regression":
                loss = tf.math.reduce_mean(tf.losses.MSE(labels, model_output))
            elif self.type_problem == "classification":
                loss = tf.math.reduce_mean(tf.losses.MSE(labels, model_output))
            elif self.type_problem == "multiclassification":
                loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
                    labels, model_output),
                                      keepdims=True)
            elif self.type_problem == "reinforcement_learning":
                loss = tf.math.reduce_mean(tf.losses.MSE(labels, model_output))
        return loss
示例#24
0
    def test_pauliz_hadamard(self, device, tol, skip_if):
        """Test that a tensor product involving PauliZ and PauliY and hadamard works correctly"""
        n_wires = 3
        dev = device(n_wires)

        if dev.shots is None:
            pytest.skip("Device is in analytic mode, cannot test sampling.")

        skip_if(dev, {"supports_tensor_observables": False})

        theta = 0.432
        phi = 0.123
        varphi = -0.543

        @qml.qnode(dev)
        def circuit():
            qml.RX(theta, wires=[0])
            qml.RX(phi, wires=[1])
            qml.RX(varphi, wires=[2])
            qml.CNOT(wires=[0, 1])
            qml.CNOT(wires=[1, 2])
            return qml.sample(
                qml.PauliZ(wires=[0]) @ qml.Hadamard(wires=[1]) @ qml.PauliY(wires=[2])
            )

        res = circuit()

        # s1 should only contain 1 and -1
        assert np.allclose(res ** 2, 1, atol=tol(False))

        mean = np.mean(res)
        expected = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2)
        assert np.allclose(mean, expected, atol=tol(False))

        var = np.var(res)
        expected = (
            3
            + np.cos(2 * phi) * np.cos(varphi) ** 2
            - np.cos(2 * theta) * np.sin(varphi) ** 2
            - 2 * np.cos(theta) * np.sin(phi) * np.sin(2 * varphi)
        ) / 4
        assert np.allclose(var, expected, atol=tol(False))
示例#25
0
    def test_nonzero_shots(self):
        """Test that the default gaussian plugin provides correct result for high shot number"""
        self.logTestName()

        shots = 10**4
        dev = qml.device('default.gaussian', wires=1, shots=shots)

        p = 0.543

        @qml.qnode(dev)
        def circuit(x):
            """Test quantum function"""
            qml.Displacement(x, 0, wires=0)
            return qml.expval.X(0)

        runs = []
        for _ in range(100):
            runs.append(circuit(p))

        self.assertAlmostEqual(np.mean(runs), p*np.sqrt(2*hbar), delta=0.01)
示例#26
0
    def test_nonzero_shots(self):
        """Test that the default qubit plugin provides correct result for high shot number"""
        self.logTestName()

        shots = 10**4
        dev = qml.device("default.qubit", wires=1, shots=shots)

        p = 0.543

        @qml.qnode(dev)
        def circuit(x):
            """Test quantum function"""
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliY(0))

        runs = []
        for _ in range(100):
            runs.append(circuit(p))

        self.assertAlmostEqual(np.mean(runs), -np.sin(p), delta=0.01)
示例#27
0
    def test_nonzero_shots(self):
        """Test that the gaussian plugin provides correct result for high shot number"""
        self.logTestName()

        shots = 10**2
        dev = qml.device('strawberryfields.gaussian', wires=1, shots=shots)

        @qml.qnode(dev)
        def circuit(x):
            qml.Displacement(x, 0, wires=0)
            return qml.expval(qml.NumberOperator(0))

        x = 1

        runs = []
        for _ in range(100):
            runs.append(circuit(x))

        expected_var = np.sqrt(1 / shots)
        self.assertAlmostEqual(np.mean(runs), x, delta=expected_var)
示例#28
0
    def test_reps_per_factor_not_1(self, mocker):
        """Tests if mitigation proceeds as expected when reps_per_factor is not 1 (default)"""
        scale_factors = [1, 2, -4]
        spy_fold = mocker.spy(self, "folding")
        spy_extrapolate = mocker.spy(self, "extrapolate")
        tapes, fn = mitigate_with_zne(
            tape, scale_factors, self.folding, self.extrapolate, reps_per_factor=2
        )
        random_results = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]

        args = spy_fold.call_args_list
        for i in range(6):
            same_tape(args[i][0][0], tape_base)
        assert [args[i][0][1] for i in range(6)] == [1, 1, 2, 2, -4, -4]

        fn(random_results)

        args = spy_extrapolate.call_args
        assert args[0][0] == scale_factors
        assert np.allclose(args[0][1], np.mean(np.reshape(random_results, (3, 2)), axis=1))
示例#29
0
def compute_K(generator):
    """Compute the K hyperparameter controlling # iterations of amplification.

    Args:
        generator: An initialized circuit generator (one of the ones above)
    """
    np.random.seed(0)
    N = 50
    target_prob_list = [
        generator.target_prob([
            np.random.uniform(low=0, high=2 * np.pi)
            for j in range(generator.num_qubits)
        ]) for _ in range(N)
    ]
    cosphi_list = [2 * p - 1 for p in target_prob_list]
    cosPhi, cosPhi_error = np.mean(
        cosphi_list), np.std(cosphi_list) / np.sqrt(N)
    Phi = np.arccos(cosPhi)

    K = int(np.pi / (2 * (np.pi - Phi)))
    return K
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  _random_layer() picks random wires."""
        n_rots = 500
        dev = qml.device('default.qubit', wires=n_subsystems)
        weights = np.random.randn(n_rots)

        def circuit(weights):
            _random_layer(weights=weights,
                          wires=range(n_subsystems),
                          ratio_imprim=0.3,
                          imprimitive=qml.CNOT,
                          rotations=[RX, RY, RZ],
                          seed=42)
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        qnode(weights)
        queue = qnode.queue
        wires = [q._wires for q in queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)