Exemplo n.º 1
0
def test_ugates_cirq():
    c1 = Circuit(3)
    c1.add(gates.RX(0, 0.1))
    c1.add(gates.RZ(1, 0.4))
    c1.add(gates.U2(2, 0.5, 0.6))
    final_state_c1 = c1()

    c2 = circuit_from_qasm(c1.to_qasm())
    c2depth = len(cirq.Circuit(c2.all_operations()))
    assert c1.depth == c2depth
    final_state_c2 = cirq.Simulator().simulate(c2).final_state
    np.testing.assert_allclose(final_state_c1, final_state_c2, atol=_atol)

    c3 = Circuit.from_qasm(c2.to_qasm())
    assert c3.depth == c2depth
    final_state_c3 = c3()
    np.testing.assert_allclose(final_state_c3, final_state_c2, atol=_atol)

    c1 = Circuit(3)
    c1.add(gates.RX(0, 0.1))
    c1.add(gates.RZ(1, 0.4))
    c1.add(gates.U2(2, 0.5, 0.6))
    c1.add(gates.CU3(2, 1, 0.2, 0.3, 0.4))
    # catches unknown gate "cu3"
    with pytest.raises(exception.QasmException):
        c2 = circuit_from_qasm(c1.to_qasm())
def test_set_parameters_with_gate_fusion(backend, accelerators):
    """Check updating parameters of fused circuit."""
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)

    params = np.random.random(9)
    c = Circuit(5, accelerators)
    c.add(gates.RX(0, theta=params[0]))
    c.add(gates.RY(1, theta=params[1]))
    c.add(gates.CZ(0, 1))
    c.add(gates.RX(2, theta=params[2]))
    c.add(gates.RY(3, theta=params[3]))
    c.add(gates.fSim(2, 3, theta=params[4], phi=params[5]))
    c.add(gates.RX(4, theta=params[6]))
    c.add(gates.RZ(0, theta=params[7]))
    c.add(gates.RZ(1, theta=params[8]))

    fused_c = c.fuse()
    np.testing.assert_allclose(c(), fused_c())

    new_params = np.random.random(9)
    new_params_list = list(new_params[:4])
    new_params_list.append((new_params[4], new_params[5]))
    new_params_list.extend(new_params[6:])
    c.set_parameters(new_params_list)
    fused_c.set_parameters(new_params_list)
    np.testing.assert_allclose(c(), fused_c())

    qibo.set_backend(original_backend)
Exemplo n.º 3
0
def test_ugates_cirq(backend):
    import qibo
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    c1 = Circuit(3)
    c1.add(gates.RX(0, 0.1))
    c1.add(gates.RZ(1, 0.4))
    c1.add(gates.U2(2, 0.5, 0.6))
    final_state_c1 = c1()

    c2 = circuit_from_qasm(c1.to_qasm())
    c2depth = len(cirq.Circuit(c2.all_operations()))
    assert c1.depth == c2depth
    final_state_c2 = cirq.Simulator().simulate(c2).final_state_vector  # pylint: disable=no-member
    np.testing.assert_allclose(final_state_c1, final_state_c2, atol=_atol)

    c3 = Circuit.from_qasm(c2.to_qasm())
    assert c3.depth == c2depth
    final_state_c3 = c3()
    np.testing.assert_allclose(final_state_c3, final_state_c2, atol=_atol)

    c1 = Circuit(3)
    c1.add(gates.RX(0, 0.1))
    c1.add(gates.RZ(1, 0.4))
    c1.add(gates.U2(2, 0.5, 0.6))
    c1.add(gates.CU3(2, 1, 0.2, 0.3, 0.4))
    # catches unknown gate "cu3"
    with pytest.raises(exception.QasmException):
        c2 = circuit_from_qasm(c1.to_qasm())
    qibo.set_backend(original_backend)
def test_circuit_set_parameters_with_dictionary(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.X(0))
    c.add(gates.X(2))
    c.add(gates.U1(0, theta=0))
    c.add(gates.RZ(1, theta=0))
    c.add(gates.CZ(1, 2))
    c.add(gates.CU1(0, 2, theta=0))
    c.add(gates.H(2))
    c.add(gates.Unitary(np.eye(2), 1))
    final_state = c()

    params = [0.123, 0.456, 0.789, np.random.random((2, 2))]
    target_c = Circuit(3, accelerators)
    target_c.add(gates.X(0))
    target_c.add(gates.X(2))
    target_c.add(gates.U1(0, theta=params[0]))
    target_c.add(gates.RZ(1, theta=params[1]))
    target_c.add(gates.CZ(1, 2))
    target_c.add(gates.CU1(0, 2, theta=params[2]))
    target_c.add(gates.H(2))
    target_c.add(gates.Unitary(params[3], 1))

    param_dict = {c.queue[i]: p for i, p in zip([2, 3, 5, 7], params)}
    c.set_parameters(param_dict)
    np.testing.assert_allclose(c(), target_c())
    qibo.set_backend(original_backend)
def ansatz_Fourier_2D(layers, qubits=1):
    """
    3 parameters per layer: Ry(wx + a), Rz(b)
    """
    circuit = models.Circuit(qubits)
    for _ in range(layers):
        circuit.add(gates.RY(0, theta=0))
        circuit.add(gates.RZ(0, theta=0))
        circuit.add(gates.RY(0, theta=0))
        circuit.add(gates.RZ(0, theta=0))

    def rotation(theta, x):
        p = circuit.get_parameters()
        i = 0
        j = 0
        for l in range(layers):
            p[i] = theta[j]
            p[i + 1] = theta[j + 1] + theta[j + 2:j + 4] @ x
            p[i + 2] = theta[j + 4]
            p[i + 3] = theta[j + 5]
            i += 4
            j += 6

        return p

    nparams = 6 * (layers)
    return circuit, rotation, nparams
Exemplo n.º 6
0
def test_set_parameters_with_gate_fusion(backend, trainable):
    """Check updating parameters of fused circuit."""
    params = np.random.random(9)
    c = Circuit(5)
    c.add(gates.RX(0, theta=params[0], trainable=trainable))
    c.add(gates.RY(1, theta=params[1]))
    c.add(gates.CZ(0, 1))
    c.add(gates.RX(2, theta=params[2]))
    c.add(gates.RY(3, theta=params[3], trainable=trainable))
    c.add(gates.fSim(2, 3, theta=params[4], phi=params[5]))
    c.add(gates.RX(4, theta=params[6]))
    c.add(gates.RZ(0, theta=params[7], trainable=trainable))
    c.add(gates.RZ(1, theta=params[8]))

    fused_c = c.fuse()
    final_state = fused_c()
    target_state = c()
    K.assert_allclose(final_state, target_state)

    if trainable:
        new_params = np.random.random(9)
        new_params_list = list(new_params[:4])
        new_params_list.append((new_params[4], new_params[5]))
        new_params_list.extend(new_params[6:])
    else:
        new_params = np.random.random(9)
        new_params_list = list(new_params[1:3])
        new_params_list.append((new_params[4], new_params[5]))
        new_params_list.append(new_params[6])
        new_params_list.append(new_params[8])

    c.set_parameters(new_params_list)
    fused_c.set_parameters(new_params_list)
    K.assert_allclose(c(), fused_c())
Exemplo n.º 7
0
def test_circuit_set_parameters_with_dictionary(backend, accelerators,
                                                trainable):
    """Check updating parameters of circuit with list."""
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)

    params = [0.123, 0.456, 0.789, np.random.random((2, 2))]

    c1 = Circuit(3, accelerators)
    c1.add(gates.X(0))
    c1.add(gates.X(2))
    if trainable:
        c1.add(gates.U1(0, theta=0, trainable=trainable))
    else:
        c1.add(gates.U1(0, theta=params[0], trainable=trainable))
    c2 = Circuit(3, accelerators)
    c2.add(gates.RZ(1, theta=0))
    c2.add(gates.CZ(1, 2))
    c2.add(gates.CU1(0, 2, theta=0))
    c2.add(gates.H(2))
    if trainable:
        c2.add(gates.Unitary(np.eye(2), 1, trainable=trainable))
    else:
        c2.add(gates.Unitary(params[3], 1, trainable=trainable))
    c = c1 + c2
    final_state = c()

    target_c = Circuit(3, accelerators)
    target_c.add(gates.X(0))
    target_c.add(gates.X(2))
    target_c.add(gates.U1(0, theta=params[0]))
    target_c.add(gates.RZ(1, theta=params[1]))
    target_c.add(gates.CZ(1, 2))
    target_c.add(gates.CU1(0, 2, theta=params[2]))
    target_c.add(gates.H(2))
    target_c.add(gates.Unitary(params[3], 1))

    if trainable:
        params_dict = {c.queue[i]: p for i, p in zip([2, 3, 5, 7], params)}
    else:
        params_dict = {c.queue[3]: params[1], c.queue[5]: params[2]}
    c.set_parameters(params_dict)
    np.testing.assert_allclose(c(), target_c())

    # test not passing all parametrized gates
    target_c = Circuit(3, accelerators)
    target_c.add(gates.X(0))
    target_c.add(gates.X(2))
    target_c.add(gates.U1(0, theta=params[0]))
    target_c.add(gates.RZ(1, theta=params[1]))
    target_c.add(gates.CZ(1, 2))
    target_c.add(gates.CU1(0, 2, theta=0.7891))
    target_c.add(gates.H(2))
    target_c.add(gates.Unitary(params[3], 1))
    c.set_parameters({c.queue[5]: 0.7891})
    np.testing.assert_allclose(c(), target_c())
    qibo.set_backend(original_backend)
Exemplo n.º 8
0
 def _initialize_circuit(self):
     """Creates variational circuit."""
     C = Circuit(1)
     for l in range(self.layers):
         C.add(gates.RY(0, theta=0))
         C.add(gates.RZ(0, theta=0))
     return C
Exemplo n.º 9
0
def test_qgan_circuit_error():
    if not K.check_availability("tensorflow"):  # pragma: no cover
        pytest.skip("Skipping StyleQGAN test because tensorflow backend is not available.")

    original_backend = qibo.get_backend()
    qibo.set_backend("tensorflow")
    reference_distribution = generate_distribution(10)
    # use wrong number of qubits so that we capture the error
    nqubits = reference_distribution.shape[1] + 1
    nlayers = 1
    circuit = models.Circuit(nqubits)
    for l in range(nlayers):
        for q in range(nqubits):
            circuit.add(gates.RY(q, 0))
            circuit.add(gates.RZ(q, 0))
        for i in range(0, nqubits - 1):
            circuit.add(gates.CZ(i, i + 1))
        circuit.add(gates.CZ(nqubits - 1, 0))
    for q in range(nqubits):
        circuit.add(gates.RY(q, 0))

    initial_params = np.random.uniform(-0.15, 0.15, 18)
    qgan = models.StyleQGAN(
            latent_dim=2,
            circuit=circuit,
            set_parameters=lambda x: x
        )
    with pytest.raises(ValueError):
        qgan.fit(reference_distribution, initial_params=initial_params, n_epochs=1, save=False)
    qibo.set_backend(original_backend)
Exemplo n.º 10
0
def test_variable_backpropagation(backend):
    if backend == "custom":
        pytest.skip("Custom gates do not support automatic differentiation.")
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    if K.name != "tensorflow":
        qibo.set_backend(original_backend)
        pytest.skip("Backpropagation is not supported by {}.".format(K.name))

    theta = K.optimization.Variable(0.1234, dtype=K.dtypes('DTYPE'))
    # TODO: Fix parametrized gates so that `Circuit` can be defined outside
    # of the gradient tape
    with K.optimization.GradientTape() as tape:
        c = Circuit(1)
        c.add(gates.X(0))
        c.add(gates.RZ(0, theta))
        loss = K.real(c()[-1])
    grad = tape.gradient(loss, theta)

    target_loss = np.cos(theta / 2.0)
    np.testing.assert_allclose(loss, target_loss)

    target_grad = -np.sin(theta / 2.0) / 2.0
    np.testing.assert_allclose(grad, target_grad)
    qibo.set_backend(original_backend)
Exemplo n.º 11
0
def test_cu1_cirq():
    c1 = Circuit(2)
    c1.add(gates.RX(0, 0.1234))
    c1.add(gates.RZ(1, 0.4321))
    c1.add(gates.CU1(0, 1, 0.567))
    # catches unknown gate "cu1"
    with pytest.raises(exception.QasmException):
        c2 = circuit_from_qasm(c1.to_qasm())
Exemplo n.º 12
0
def test_crotations_cirq():
    c1 = Circuit(3)
    c1.add(gates.RX(0, 0.1))
    c1.add(gates.RZ(1, 0.4))
    c1.add(gates.CRX(0, 2, 0.5))
    c1.add(gates.RY(1, 0.3).controlled_by(2))
    # catches unknown gate "crx"
    with pytest.raises(exception.QasmException):
        c2 = circuit_from_qasm(c1.to_qasm())
Exemplo n.º 13
0
def test_circuit_on_qubits_controlled_by_execution(backend, accelerators):
    smallc = Circuit(3)
    smallc.add(gates.RX(0, theta=0.1).controlled_by(1, 2))
    smallc.add(gates.RY(1, theta=0.2).controlled_by(0))
    smallc.add(gates.RX(2, theta=0.3).controlled_by(1, 0))
    smallc.add(gates.RZ(1, theta=0.4).controlled_by(0, 2))

    largec = Circuit(6, accelerators=accelerators)
    largec.add(gates.H(i) for i in range(6))
    largec.add(smallc.on_qubits(1, 4, 3))

    targetc = Circuit(6)
    targetc.add(gates.H(i) for i in range(6))
    targetc.add(gates.RX(1, theta=0.1).controlled_by(3, 4))
    targetc.add(gates.RY(4, theta=0.2).controlled_by(1))
    targetc.add(gates.RX(3, theta=0.3).controlled_by(1, 4))
    targetc.add(gates.RZ(4, theta=0.4).controlled_by(1, 3))

    assert largec.depth == targetc.depth
    K.assert_allclose(largec(), targetc())
Exemplo n.º 14
0
def test_rz(backend, applyx):
    theta = 0.1234
    if applyx:
        gatelist = [gates.X(0)]
    else:
        gatelist = []
    gatelist.append(gates.RZ(0, theta))
    final_state = apply_gates(gatelist, nqubits=1)
    target_state = np.zeros_like(final_state)
    p = int(applyx)
    target_state[p] = np.exp((2 * p - 1) * 1j * theta / 2.0)
    K.assert_allclose(final_state, target_state)
Exemplo n.º 15
0
def ansatz(p=0):
    """Ansatz for driving a random state into its up-tp-phases canonical form.

      Args:
        p (float): probability of occuring a single-qubit depolarizing error

      Returns:
        Qibo circuit implementing the variational ansatz.
    """
    C = Circuit(3)
    for i in range(3):
        C.add(gates.RZ(i, theta=0))
        C.add(gates.RY(i, theta=0))
        C.add(gates.RZ(i, theta=0))
        if p > 0:
            C.add(gates.NoiseChannel(i, px=p / 3, py=p / 3, pz=p / 3))
    for i in range(3):
        if p > 0:
            C.add(gates.NoiseChannel(i, px=10 * p))
        C.add(gates.M(i))
    return C
Exemplo n.º 16
0
def test_construct_unitary(backend):
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    target_matrix = np.array([[1, 1], [1, -1]]) / np.sqrt(2)
    np.testing.assert_allclose(gates.H(0).unitary, target_matrix)
    target_matrix = np.array([[0, 1], [1, 0]])
    np.testing.assert_allclose(gates.X(0).unitary, target_matrix)
    target_matrix = np.array([[0, -1j], [1j, 0]])
    np.testing.assert_allclose(gates.Y(0).unitary, target_matrix)
    target_matrix = np.array([[1, 0], [0, -1]])
    np.testing.assert_allclose(gates.Z(1).unitary, target_matrix)

    target_matrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1],
                              [0, 0, 1, 0]])
    np.testing.assert_allclose(gates.CNOT(0, 1).unitary, target_matrix)
    target_matrix = np.diag([1, 1, 1, -1])
    np.testing.assert_allclose(gates.CZ(1, 3).unitary, target_matrix)
    target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0],
                              [0, 0, 0, 1]])
    np.testing.assert_allclose(gates.SWAP(2, 4).unitary, target_matrix)
    target_matrix = np.array([[1, 0, 0, 0, 0, 0, 0,
                               0], [0, 1, 0, 0, 0, 0, 0, 0],
                              [0, 0, 1, 0, 0, 0, 0,
                               0], [0, 0, 0, 1, 0, 0, 0, 0],
                              [0, 0, 0, 0, 1, 0, 0,
                               0], [0, 0, 0, 0, 0, 1, 0, 0],
                              [0, 0, 0, 0, 0, 0, 0, 1],
                              [0, 0, 0, 0, 0, 0, 1, 0]])
    np.testing.assert_allclose(gates.TOFFOLI(1, 2, 3).unitary, target_matrix)

    theta = 0.1234
    target_matrix = np.array([[np.cos(theta / 2.0), -1j * np.sin(theta / 2.0)],
                              [-1j * np.sin(theta / 2.0),
                               np.cos(theta / 2.0)]])
    np.testing.assert_allclose(gates.RX(0, theta).unitary, target_matrix)
    target_matrix = np.array([[np.cos(theta / 2.0), -np.sin(theta / 2.0)],
                              [np.sin(theta / 2.0),
                               np.cos(theta / 2.0)]])
    np.testing.assert_allclose(gates.RY(0, theta).unitary, target_matrix)
    target_matrix = np.diag(
        [np.exp(-1j * theta / 2.0),
         np.exp(1j * theta / 2.0)])
    np.testing.assert_allclose(gates.RZ(0, theta).unitary, target_matrix)
    target_matrix = np.diag([1, np.exp(1j * theta)])
    np.testing.assert_allclose(gates.U1(0, theta).unitary, target_matrix)
    target_matrix = np.diag([1, 1, 1, np.exp(1j * theta)])
    np.testing.assert_allclose(gates.CU1(0, 1, theta).unitary, target_matrix)
    from qibo import matrices
    target_matrix = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0],
                              [0, 0, 0, 1]])
    np.testing.assert_allclose(matrices.SWAP, target_matrix)
    qibo.set_backend(original_backend)
Exemplo n.º 17
0
def test_czpow():
    c = Circuit(2)
    c.add(gates.RX(0, 0.1234))
    c.add(gates.RZ(1, 0.4321))
    c.add(gates.CZPow(0, 1, 0.567))
    target = f"""// Generated by QIBO {__version__}
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
rx(0.1234) q[0];
rz(0.4321) q[1];
crz(0.567) q[0],q[1];"""
    assert_strings_equal(c.to_qasm(), target)
Exemplo n.º 18
0
def test_custom_qgan():
    if not K.check_availability("tensorflow"):  # pragma: no cover
        pytest.skip("Skipping StyleQGAN test because tensorflow backend is not available.")

    original_backend = qibo.get_backend()
    qibo.set_backend("tensorflow")
    def set_params(circuit, params, x_input, i):
        """Set the parameters for the quantum generator circuit."""
        p = []
        index = 0
        noise = 0
        for l in range(1):
            for q in range(3):
                p.append(params[index]*x_input[noise][i] + params[index+1])
                index+=2
                noise=(noise+1)%2
                p.append(params[index]*x_input[noise][i] + params[index+1])
                index+=2
                noise=(noise+1)%2
        for q in range(3):
            p.append(params[index]*x_input[noise][i] + params[index+1])
            index+=2
            noise=(noise+1)%2
        circuit.set_parameters(p)

    nqubits = 3
    nlayers = 1
    reference_distribution = generate_distribution(10)
    circuit = models.Circuit(nqubits)
    for l in range(nlayers):
        for q in range(nqubits):
            circuit.add(gates.RY(q, 0))
            circuit.add(gates.RZ(q, 0))
        for i in range(0, nqubits - 1):
            circuit.add(gates.CZ(i, i + 1))
        circuit.add(gates.CZ(nqubits - 1, 0))
    for q in range(nqubits):
        circuit.add(gates.RY(q, 0))

    initial_params = np.random.uniform(-0.15, 0.15, 18)
    qgan = models.StyleQGAN(
            latent_dim=2,
            circuit=circuit,
            set_parameters=set_params
        )
    qgan.fit(reference_distribution, initial_params=initial_params, n_epochs=1, save=False)
    assert qgan.latent_dim == 2
    assert qgan.batch_samples == 128
    assert qgan.n_epochs == 1
    assert qgan.lr == 0.5
    qibo.set_backend(original_backend)
Exemplo n.º 19
0
def test_rz_phase0(backend):
    """Check RZ gate is working properly when qubit is on |0>."""
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    theta = 0.1234

    c = Circuit(2)
    c.add(gates.RZ(0, theta))
    final_state = c.execute().numpy()

    target_state = np.zeros_like(final_state)
    target_state[0] = np.exp(-1j * theta / 2.0)
    np.testing.assert_allclose(final_state, target_state)
    qibo.set_backend(original_backend)
Exemplo n.º 20
0
def test_from_qasm_parametrized_gates():
    import numpy as np
    target = """OPENQASM 2.0;
qreg q[2];
rx(0.1234) q[0];
rz(0.4321) q[1];
cu1(0.567) q[0],q[1];"""
    c = Circuit.from_qasm(target)
    assert c.depth == 2
    assert isinstance(c.queue[0], gates.RX)
    assert isinstance(c.queue[1], gates.RZ)
    assert isinstance(c.queue[2], gates.CU1)

    c2 = Circuit(2)
    c2.add([gates.RX(0, 0.1234), gates.RZ(1, 0.4321), gates.CU1(0, 1, 0.567)])
    np.testing.assert_allclose(c2().numpy(), c().numpy())
Exemplo n.º 21
0
def test_variable_backpropagation(backend):
    if not K.supports_gradients:
        pytest.skip("Backpropagation is not supported by {}.".format(K.name))

    theta = K.optimization.Variable(0.1234, dtype=K.dtypes('DTYPE'))
    # TODO: Fix parametrized gates so that `Circuit` can be defined outside
    # of the gradient tape
    with K.optimization.GradientTape() as tape:
        c = Circuit(1)
        c.add(gates.X(0))
        c.add(gates.RZ(0, theta))
        loss = K.real(c()[-1])
    grad = tape.gradient(loss, theta)

    target_loss = np.cos(theta / 2.0)
    K.assert_allclose(loss, target_loss)

    target_grad = -np.sin(theta / 2.0) / 2.0
    K.assert_allclose(grad, target_grad)
Exemplo n.º 22
0
def test_crotations():
    c = Circuit(3)
    c.add(gates.RX(0, 0.1))
    c.add(gates.RZ(1, 0.4))
    c.add(gates.CRX(0, 2, 0.5))
    c.add(gates.RY(1, 0.3).controlled_by(2))
    target = f"""// Generated by QIBO {__version__}
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
rx(0.1) q[0];
rz(0.4) q[1];
crx(0.5) q[0],q[2];
cry(0.3) q[2],q[1];"""
    assert_strings_equal(c.to_qasm(), target)

    c = Circuit(2)
    c.add(gates.CU2(0, 1, 0.1, 0.2))
    with pytest.raises(ValueError):
        target = c.to_qasm()
Exemplo n.º 23
0
def test_ugates():
    c = Circuit(3)
    c.add(gates.RX(0, 0.1))
    c.add(gates.RZ(1, 0.4))
    c.add(gates.U2(2, 0.5, 0.6))
    c.add(gates.CU1(0, 1, 0.7))
    c.add(gates.CU3(2, 1, 0.2, 0.3, 0.4))
    target = f"""// Generated by QIBO {__version__}
OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
rx(0.1) q[0];
rz(0.4) q[1];
u2(0.5, 0.6) q[2];
cu1(0.7) q[0],q[1];
cu3(0.2, 0.3, 0.4) q[2],q[1];"""
    assert_strings_equal(c.to_qasm(), target)

    c = Circuit(2)
    c.add(gates.CU2(0, 1, 0.1, 0.2))
    with pytest.raises(ValueError):
        target = c.to_qasm()
Exemplo n.º 24
0
def test_variable_backpropagation(backend):
    """Check that backpropagation works when using `tf.Variable` parameters."""
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    import tensorflow as tf
    from qibo.config import DTYPES
    theta = tf.Variable(0.1234, dtype=DTYPES.get('DTYPE'))

    # TODO: Fix parametrized gates so that `Circuit` can be defined outside
    # of the gradient tape
    with tf.GradientTape() as tape:
        c = Circuit(1)
        c.add(gates.X(0))
        c.add(gates.RZ(0, theta))
        loss = tf.math.real(c()[-1])
    grad = tape.gradient(loss, theta)

    target_loss = np.cos(theta.numpy() / 2.0)
    np.testing.assert_allclose(loss.numpy(), target_loss)

    target_grad = -np.sin(theta.numpy() / 2.0) / 2.0
    np.testing.assert_allclose(grad.numpy(), target_grad)
    qibo.set_backend(original_backend)
def ansatz_Weighted_2D(layers, qubits=1):
    """
    3 parameters per layer: Ry(wx + a), Rz(b)
    """
    circuit = models.Circuit(qubits)
    circuit.add(gates.H(0))
    for _ in range(layers):
        circuit.add(gates.RZ(0, theta=0))
        circuit.add(gates.RY(0, theta=0))

    def rotation(theta, x):
        p = circuit.get_parameters()
        i = 0
        j = 0
        for l in range(layers):
            p[i] = theta[j] + theta[j + 1:j + 3] @ x
            p[i + 1] = theta[j + 3]
            i += 2
            j += 4

        return p

    nparams = 4 * layers
    return circuit, rotation, nparams
Exemplo n.º 26
0
def ansatz_Weighted(layers, qubits=1):
    """Fourier Ansatz implementation. 4 parameters per layer and
    qubit: Ry(wx + a), Rz(v log(x) + b)

    Args:
        layers (int): number of layers.
        qubits (int): number of qubits.

    Returns:
        The circuit, the rotation function and the total number of
        parameters.
    """
    circuit = models.Circuit(qubits)
    for _ in range(layers - 1):
        for q in range(qubits):
            circuit.add(gates.RY(q, theta=0))
            circuit.add(gates.RZ(q, theta=0))
        if qubits > 1:
            for q in range(0, qubits, 2):
                circuit.add(gates.CZPow(q, (q + 1) % qubits, theta=0))
        if qubits > 2:
            for q in range(1, qubits + 1, 2):
                circuit.add(gates.CZPow(q, (q + 1) % qubits, theta=0))
    for q in range(qubits):
        circuit.add(gates.RY(q, theta=0))
        circuit.add(gates.RZ(q, theta=0))

    def rotation(theta, x):
        p = circuit.get_parameters()
        i = 0
        j = 0
        for l in range(layers - 1):
            for q in range(qubits):
                p[i] = theta[j] + theta[j + 1] * map_to(x)
                p[i + 1] = theta[j + 2] + theta[j + 3] * maplog_to(x)
                i += 2
                j += 4

            if qubits > 1:
                for q in range(0, qubits, 2):
                    p[i] = theta[j]
                    i += 1
                    j += 1
            if qubits > 2:
                for q in range(1, qubits + 1, 2):
                    p[i] = theta[j]
                    i += 1
                    j += 1

        for q in range(qubits):
            p[i] = theta[j] + theta[j + 1] * map_to(x)
            p[i + 1] = theta[j + 2] + theta[j + 3] * maplog_to(x)
            i += 2
            j += 4

        return p

    nparams = 4 * layers * qubits + \
        (layers - 1) * int(np.ceil(qubits / 2)) * \
        (int(qubits > 1) + int(qubits > 2))
    return circuit, rotation, nparams
Exemplo n.º 27
0
def ansatz_Fourier(layers, qubits=1):
    """Fourier Ansatz implementation. It is composed by 3 parameters per layer
    and qubit: U3(a, b, c) Ry(x) || U3(a, b, c) Ry(log x).

    Args:
        layers (int): number of layers.
        qubits (int): number of qubits.

    Returns:
        The circuit, the rotation function and the total number of parameters.
    """
    circuit = models.Circuit(qubits)
    for l in range(layers - 1):
        for q in range(qubits):
            for _ in range(2):
                circuit.add(gates.RY(q, theta=0))
                circuit.add(gates.RZ(q, theta=0))
                circuit.add(gates.RY(q, theta=0))

        if qubits > 1:
            for q in range(0, qubits, 2):
                circuit.add(gates.CZPow(q, q + 1, theta=0))
        if qubits > 2:
            for q in range(1, qubits + 1, 2):
                circuit.add(gates.CZPow(q, (q + 1) % qubits, theta=0))

    for q in range(qubits):
        for _ in range(2):
            circuit.add(gates.RY(q, theta=0))
            circuit.add(gates.RZ(q, theta=0))
            circuit.add(gates.RY(q, theta=0))

    def rotation(theta, x):
        p = circuit.get_parameters()
        i = 0
        j = 0
        for l in range(layers - 1):
            for q in range(qubits):
                p[i] = map_to(x)
                p[i + 1:i + 3] = theta[j:j + 2]
                i += 3
                j += 2

                p[i] = .5 * maplog_to(x)
                p[i + 1:i + 3] = theta[j:j + 2]
                i += 3
                j += 2
            if qubits > 1:
                for q in range(0, qubits, 2):
                    p[i] = theta[j]
                    i += 1
                    j += 1
            if qubits > 2:
                for q in range(1, qubits + 1, 2):
                    p[i] = theta[j]
                    i += 1
                    j += 1
        for q in range(qubits):
            p[i] = .5 * map_to(x)
            p[i + 1:i + 3] = theta[j:j + 2]
            i += 3
            j += 2

            p[i] = .5 * maplog_to(x)
            p[i + 1:i + 3] = theta[j:j + 2]
            i += 3
            j += 2
        return p

    nparams = 4 * layers * qubits + \
        (layers - 1) * int(np.ceil(qubits / 2)) * \
        (int(qubits > 1) + int(qubits > 2))

    return circuit, rotation, nparams
Exemplo n.º 28
0
def last_rotation(circuit, nqubits):
    for k in range(nqubits):
        circuit.add(gates.RZ(k, np.random.rand()))
        circuit.add(gates.RX(k, np.random.rand()))
Exemplo n.º 29
0
 def rotations():
     for q in range(self.nqubits):
         yield gates.RX(q, theta=0)
         yield gates.RZ(q, theta=0)
         yield gates.RX(q, theta=0)
Exemplo n.º 30
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)