Beispiel #1
0
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)
Beispiel #3
0
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())
Beispiel #4
0
    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)