def test_circuit_set_parameters_ungates(backend, accelerators, trainable): """Check updating parameters of circuit with list.""" original_backend = qibo.get_backend() qibo.set_backend(backend) params = [0.1, 0.2, 0.3, (0.4, 0.5), (0.6, 0.7, 0.8)] if trainable: trainable_params = list(params) else: trainable_params = [0.1, 0.3, (0.4, 0.5)] c = Circuit(3, accelerators) c.add(gates.RX(0, theta=0)) if trainable: c.add(gates.CRY(0, 1, theta=0, trainable=trainable)) else: c.add(gates.CRY(0, 1, theta=params[1], trainable=trainable)) c.add(gates.CZ(1, 2)) c.add(gates.U1(2, theta=0)) c.add(gates.CU2(0, 2, phi=0, lam=0)) if trainable: c.add(gates.U3(1, theta=0, phi=0, lam=0, trainable=trainable)) else: c.add(gates.U3(1, *params[4], trainable=trainable)) # execute once final_state = c() target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3])) target_c.add(gates.U3(1, *params[4])) c.set_parameters(trainable_params) np.testing.assert_allclose(c(), target_c()) # Attempt using a flat list npparams = np.random.random(8) if trainable: trainable_params = np.copy(npparams) else: npparams[1] = params[1] npparams[5:] = params[4] trainable_params = np.delete(npparams, [1, 5, 6, 7]) target_c = Circuit(3) target_c.add(gates.RX(0, theta=npparams[0])) target_c.add(gates.CRY(0, 1, theta=npparams[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=npparams[2])) target_c.add(gates.CU2(0, 2, *npparams[3:5])) target_c.add(gates.U3(1, *npparams[5:])) c.set_parameters(trainable_params) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_circuit_set_parameters_ungates(backend, accelerators): """Check updating parameters of circuit with list.""" original_backend = qibo.get_backend() qibo.set_backend(backend) c = Circuit(3, accelerators) c.add(gates.RX(0, theta=0)) c.add(gates.CRY(0, 1, theta=0)) c.add(gates.CZ(1, 2)) c.add(gates.U1(2, theta=0)) c.add(gates.CU2(0, 2, phi=0, lam=0)) c.add(gates.U3(1, theta=0, phi=0, lam=0)) # execute once final_state = c() params = [0.1, 0.2, 0.3, (0.4, 0.5), (0.6, 0.7, 0.8)] target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3])) target_c.add(gates.U3(1, *params[4])) c.set_parameters(params) np.testing.assert_allclose(c(), target_c()) # Attempt using a flat list params = np.random.random(8) target_c = Circuit(3) target_c.add(gates.RX(0, theta=params[0])) target_c.add(gates.CRY(0, 1, theta=params[1])) target_c.add(gates.CZ(1, 2)) target_c.add(gates.U1(2, theta=params[2])) target_c.add(gates.CU2(0, 2, *params[3:5])) target_c.add(gates.U3(1, *params[5:])) c.set_parameters(params) np.testing.assert_allclose(c(), target_c()) qibo.set_backend(original_backend)
def test_from_qasm_crotations(): import numpy as np target = """OPENQASM 2.0; qreg q[2]; crx(0.1) q[0],q[1]; crz(0.3) q[1],q[0]; cry(0.2) q[0],q[1];""" c = Circuit.from_qasm(target) assert c.depth == 3 assert isinstance(c.queue[0], gates.CRX) assert isinstance(c.queue[1], gates.CRZ) assert isinstance(c.queue[2], gates.CRY) c2 = Circuit(2) c2.add([gates.CRX(0, 1, 0.1), gates.CRZ(1, 0, 0.3), gates.CRY(0, 1, 0.2)]) np.testing.assert_allclose(c2().numpy(), c().numpy())
def fit(self, reference, initial_params=None, batch_samples=128, n_epochs=20000, lr=0.5, save=True): """Execute qGAN training. Args: reference (array): samples from the reference input distribution. initial_parameters (array): initial parameters for the quantum generator. If not provided, the default initial parameters will be used. discriminator (:class:`tensorflow.keras.models`): custom classical discriminator. If not provided, the default classical discriminator will be used. batch_samples (int): number of training examples utilized in one iteration. n_epochs (int): number of training iterations. lr (float): initial learning rate for the quantum generator. It controls how much to change the model each time the weights are updated. save (bool): If ``True`` the results of training (trained parameters and losses) will be saved on disk. Default is ``True``. """ if initial_params is None and self.circuit is not None: raise_error( ValueError, "Set the initial parameters for your custom quantum generator." ) elif initial_params is not None and self.circuit is None: raise_error( ValueError, "Define the custom quantum generator to use custom initial parameters." ) self.reference = reference self.nqubits = reference.shape[1] self.training_samples = reference.shape[0] self.initial_params = initial_params self.batch_samples = batch_samples self.n_epochs = n_epochs self.lr = lr # create classical discriminator if self.discriminator is None: discriminator = self.define_discriminator() else: discriminator = self.discriminator if discriminator.input_shape[1] is not self.nqubits: raise_error( ValueError, "The number of input neurons in the discriminator has to be equal to " "the number of qubits in the circuit (dimension of the input reference distribution)." ) # create quantum generator if self.circuit is None: circuit = models.Circuit(self.nqubits) for l in range(self.layers): for q in range(self.nqubits): circuit.add(gates.RY(q, 0)) circuit.add(gates.RZ(q, 0)) circuit.add(gates.RY(q, 0)) circuit.add(gates.RZ(q, 0)) for i in range(0, self.nqubits - 1): circuit.add(gates.CRY(i, i + 1, 0)) circuit.add(gates.CRY(self.nqubits - 1, 0, 0)) for q in range(self.nqubits): circuit.add(gates.RY(q, 0)) else: circuit = self.circuit if circuit.nqubits != self.nqubits: raise_error( ValueError, "The number of qubits in the circuit has to be equal to " "the number of dimensions in the reference distribution.") # define hamiltonian to generate fake samples def hamiltonian(nqubits, position): identity = [[1, 0], [0, 1]] m0 = hamiltonians.Z(1).matrix kron = [] for i in range(nqubits): if i == position: kron.append(m0) else: kron.append(identity) for i in range(nqubits - 1): if i == 0: ham = np.kron(kron[i + 1], kron[i]) else: ham = np.kron(kron[i + 1], ham) ham = hamiltonians.Hamiltonian(nqubits, ham) return ham hamiltonians_list = [] for i in range(self.nqubits): hamiltonians_list.append(hamiltonian(self.nqubits, i)) # train model self.train(discriminator, circuit, hamiltonians_list, save)