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)
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))
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))
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))
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 )
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)
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)
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)
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 )
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')
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
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)
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
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))
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)
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
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)
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)
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)
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
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))
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)
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)
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)
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))
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)