def test_stronglyentanglinglayers_uniform_dimensions( self, n_subsystems, n_layers): """Confirm that the pennylane.init.strong_ent_layers_uniform() returns an array with the right dimensions.""" a = (n_layers, n_subsystems, 3) p = strong_ent_layers_uniform(n_layers=n_layers, n_wires=n_subsystems, seed=0) dims = [p_.shape for p_ in p] assert dims == [a]
def test_stronglyentanglinglayers_uniform_edgecase(self, seed, tol): """Test sampling edge case of pennylane.init.strong_ent_layers_uniform().""" n_layers = 3 p = strong_ent_layers_uniform(n_layers=n_layers, n_wires=10, low=1, high=1, seed=seed) p_mean = np.mean(np.array([np.mean(pp) for p_ in p for pp in p_])) assert np.allclose(p_mean, 1, atol=tol, rtol=0.)
def test_stronglyentanglinglayers_uniform_interval(self, seed): """Confirm that no uniform sample in pennylane.init.strong_ent_layers_uniform() lies outside of interval.""" low = -2 high = 1 n_layers = 3 p = strong_ent_layers_uniform(n_layers=n_layers, n_wires=10, low=low, high=high, seed=seed) assert all([(p_ <= high).all() and (p_ >= low).all() for p_ in p])
def benchmark(self, n=3): # n is the number of layers in the circuit if self.verbose: print("circuit: {} layers, {} wires".format(n, self.n_wires)) features = np.arange(self.n_wires) init_weights = strong_ent_layers_uniform(n_layers=n, n_wires=self.n_wires) qnode = bu.create_qnode(circuit, self.device, mutable=True) qnode(init_weights, features=features) qnode.jacobian((init_weights, ), {"features": features}) return True
def test_stronglyentanglinglayers_uniform_seed(self, seed, tol): """Confirm that pennylane.init.strong_ent_layers_uniform() invokes the correct np.random sampling function for a given seed.""" low = -2 high = 1 n_wires = 3 n_layers = 3 p = strong_ent_layers_uniform(n_layers=n_layers, n_wires=n_wires, low=low, high=high, seed=seed) np.random.seed(seed) p_target = np.random.uniform(low=low, high=high, size=(n_layers, n_wires, 3)) assert np.allclose(p[0], p_target, atol=tol, rtol=0.)
H = np.array([[8, 4, 0, -6], [4, 0, 4, 0], [0, 4, 8, 0], [-6, 0, 0, 0]]) def circuit(params): StronglyEntanglingLayers(weights=params, wires=[0, 1]) return expval(qml.Hermitian(H, wires=[0, 1])) ############################################################################## # Now, we create three QNodes, each corresponding to a device above, # and optimize them using gradient descent via the parameter-shift rule. qnode_analytic = qml.QNode(circuit, dev_analytic) qnode_stochastic = qml.QNode(circuit, dev_stochastic) init_params = strong_ent_layers_uniform(num_layers, num_wires) # Optimizing using exact gradient descent cost_GD = [] params_GD = init_params opt = qml.GradientDescentOptimizer(eta) for _ in range(steps): cost_GD.append(qnode_analytic(params_GD)) params_GD = opt.step(qnode_analytic, params_GD) # Optimizing using stochastic gradient descent with shots=1 dev_stochastic.shots = 1 cost_SGD1 = []
class TestInitializationIntegration: """Tests integration with the parameter initialization functions from pennylane.init""" # TODO: Combine CV and Qubit tests, since the only difference is the device def make_n_features(self, n): """Helper to prepare dummy feature inputs for templates that have as many features as number of wires.""" return [i for i in range(n)] QUBIT_INIT = [(StronglyEntanglingLayers, {'weights': strong_ent_layers_uniform(n_layers=3, n_wires=2), 'wires': range(2)}), (StronglyEntanglingLayers, {'weights': strong_ent_layers_uniform(n_layers=2, n_wires=3), 'wires': range(3)}), (StronglyEntanglingLayers, {'weights': strong_ent_layers_normal(n_layers=3, n_wires=2), 'wires': range(2)}), (StronglyEntanglingLayers, {'weights': strong_ent_layers_normal(n_layers=2, n_wires=3), 'wires': range(3)}), (RandomLayers, {'weights': random_layers_uniform(n_layers=3, n_rots=2, n_wires=2), 'wires': range(2)}), (RandomLayers, {'weights': random_layers_uniform(n_layers=3, n_rots=2, n_wires=2), 'wires': range(2)}), (RandomLayers, {'weights': random_layers_normal(n_layers=2, n_rots=2, n_wires=3), 'wires': range(3)}), (RandomLayers, {'weights': random_layers_normal(n_layers=2, n_rots=2, n_wires=3), 'wires': range(3)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_uniform(n_layers=3, n_wires=2), 'wires': range(2)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_uniform(n_layers=3, n_wires=2), 'wires': range(2)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_normal(n_layers=2, n_wires=3), 'wires': range(3)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_normal(n_layers=2, n_wires=3), 'wires': range(3)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_normal(n_layers=2, n_wires=1), 'wires': range(1)}), (QAOAEmbedding, {'features': [1., 2.], 'weights': qaoa_embedding_uniform(n_layers=2, n_wires=1), 'wires': range(1)}) ] CV_INIT = [(CVNeuralNetLayers, {'theta_1': cvqnn_layers_theta_uniform(n_layers=3, n_wires=2), 'phi_1': cvqnn_layers_phi_uniform(n_layers=3, n_wires=2), 'varphi_1': cvqnn_layers_varphi_uniform(n_layers=3, n_wires=2), 'r': cvqnn_layers_r_uniform(n_layers=3, n_wires=2), 'phi_r': cvqnn_layers_phi_r_uniform(n_layers=3, n_wires=2), 'theta_2': cvqnn_layers_theta_uniform(n_layers=3, n_wires=2), 'phi_2': cvqnn_layers_phi_uniform(n_layers=3, n_wires=2), 'varphi_2': cvqnn_layers_varphi_uniform(n_layers=3, n_wires=2), 'a': cvqnn_layers_a_uniform(n_layers=3, n_wires=2), 'phi_a': cvqnn_layers_phi_a_uniform(n_layers=3, n_wires=2), 'k': cvqnn_layers_kappa_uniform(n_layers=3, n_wires=2), 'wires': range(2)}), (CVNeuralNetLayers, {'theta_1': cvqnn_layers_theta_normal(n_layers=3, n_wires=2), 'phi_1': cvqnn_layers_phi_normal(n_layers=3, n_wires=2), 'varphi_1': cvqnn_layers_varphi_normal(n_layers=3, n_wires=2), 'r': cvqnn_layers_r_normal(n_layers=3, n_wires=2), 'phi_r': cvqnn_layers_phi_r_normal(n_layers=3, n_wires=2), 'theta_2': cvqnn_layers_theta_normal(n_layers=3, n_wires=2), 'phi_2': cvqnn_layers_phi_normal(n_layers=3, n_wires=2), 'varphi_2': cvqnn_layers_varphi_normal(n_layers=3, n_wires=2), 'a': cvqnn_layers_a_normal(n_layers=3, n_wires=2), 'phi_a': cvqnn_layers_phi_a_normal(n_layers=3, n_wires=2), 'k': cvqnn_layers_kappa_normal(n_layers=3, n_wires=2), 'wires': range(2)}), (Interferometer, {'phi': interferometer_phi_uniform(n_wires=2), 'varphi': interferometer_varphi_uniform(n_wires=2), 'theta': interferometer_theta_uniform(n_wires=2), 'wires': range(2)}), (Interferometer, {'phi': interferometer_phi_normal(n_wires=2), 'varphi': interferometer_varphi_normal(n_wires=2), 'theta': interferometer_theta_normal(n_wires=2), 'wires': range(2)}), (Interferometer, {'phi': interferometer_phi_uniform(n_wires=3), 'varphi': interferometer_varphi_uniform(n_wires=3), 'theta': interferometer_theta_uniform(n_wires=3), 'wires': range(3)}), (Interferometer, {'phi': interferometer_phi_normal(n_wires=3), 'varphi': interferometer_varphi_normal(n_wires=3), 'theta': interferometer_theta_normal(n_wires=3), 'wires': range(3)}) ] @pytest.mark.parametrize("template, dict", QUBIT_INIT) def test_integration_qubit_init(self, template, dict): """Checks parameter initialization compatible with qubit templates.""" n_wires = len(dict['wires']) dev = qml.device('default.qubit', wires=n_wires) @qml.qnode(dev) def circuit(): template(**dict) return qml.expval(qml.Identity(0)) # Check that execution does not throw error circuit() @pytest.mark.parametrize("template, dict", CV_INIT) def test_integration_qubit_init(self, template, dict, gaussian_dummy): """Checks parameter initialization compatible with qubit templates.""" n_wires = len(dict['wires']) dev = gaussian_dummy(n_wires) @qml.qnode(dev) def circuit(): template(**dict) return qml.expval(qml.Identity(0)) # Check that execution does not throw error circuit()
def emmbedding_layer(x): for i in range(NUM_WIRES): qml.RY(x[i] * np.pi, wires=i) @qml.qnode(dev, interface="torch", diff_method='adjoint') def circuit(inputs, weights): for k in range(0, 15, 3): qml.templates.AngleEmbedding(inputs[k:k + 3], wires=range(NUM_WIRES)) StronglyEntanglingLayers(init_weights, wires=[k for k in range(NUM_WIRES)]) return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)), qml.expval( qml.PauliZ(2)) init_weights = Variable(torch.from_numpy( strong_ent_layers_uniform(n_layers=EMBEDDING_LAYERS, n_wires=NUM_WIRES)).float().cuda(), requires_grad=True) weights_shape = {"weights": [EMBEDDING_LAYERS, NUM_WIRES, 3]} ''' Lignes to comment for benchmarking simulators speeds ''' qlayer = qml.qnn.TorchLayer(circuit, weights_shape) class Model(nn.Module): def __init__(self, channels: int = 8, n_classes: int = 3) -> None: super(Model, self).__init__() self.features = nn.Sequential( nn.Conv1d(channels, 64, kernel_size=3, stride=1), nn.ReLU(), nn.Dropout(0.4), nn.Conv1d(64, 128, kernel_size=2, stride=2),
# convert classes to expectations: 0 to -1, 1 to +1 e_train = np.empty_like(y_train) e_train[y_train == 0] = -1 e_train[y_train == 1] = +1 # select learning batch size batch_size = 5 # calculate number of batches batches = len(X_train) // batch_size # select number of epochs n_epochs = 5 # draw random quantum node weights theta = strong_ent_layers_uniform(n_layers, n_qubits, seed=15) # train the variational classifier # start of main learning loop # build the optimizer object pennylane_opt = NesterovMomentumOptimizer() log = [] # split training data into batches X_batches = np.array_split(np.arange(len(X_train)), batches) for it, batch_index in enumerate(chain(*(n_epochs * [X_batches]))): # Update the weights by one optimizer step batch_cost = \ lambda t: cost(t, X_train[batch_index], e_train[batch_index]) theta = pennylane_opt.step(batch_cost, theta)
import pennylane as qml from pennylane.templates.embeddings import AngleEmbedding from pennylane.templates.layers import StronglyEntanglingLayers from pennylane.init import strong_ent_layers_uniform dev = qml.device('default.qubit', wires=2) @qml.qnode(dev) def circuit(weights, x=None): AngleEmbedding(x, [0, 1]) StronglyEntanglingLayers(weights, wires=[0, 1]) return qml.expval(qml.PauliZ(0)) init_weights = strong_ent_layers_uniform(n_layers=3, n_wires=2) print(circuit(init_weights, x=[1., 2.]))