Exemplo n.º 1
0
def test_symbolic_hamiltonian_operator_add_and_sub(backend, nqubits, calcterms,
                                                   calcdense):
    """Test addition and subtraction between Trotter Hamiltonians."""
    local_ham1 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=1.0))
    local_ham2 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=0.5))
    if calcterms:
        _ = local_ham1.terms
        _ = local_ham2.terms
    if calcdense:
        _ = local_ham1.dense
        _ = local_ham2.dense
    local_ham = local_ham1 + local_ham2
    target_ham = (hamiltonians.TFIM(nqubits, h=1.0) +
                  hamiltonians.TFIM(nqubits, h=0.5))
    dense = local_ham.dense
    K.assert_allclose(dense.matrix, target_ham.matrix)

    local_ham1 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=1.0))
    local_ham2 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=0.5))
    if calcterms:
        _ = local_ham1.terms
        _ = local_ham2.terms
    if calcdense:
        _ = local_ham1.dense
        _ = local_ham2.dense
    local_ham = local_ham1 - local_ham2
    target_ham = (hamiltonians.TFIM(nqubits, h=1.0) -
                  hamiltonians.TFIM(nqubits, h=0.5))
    dense = local_ham.dense
    K.assert_allclose(dense.matrix, target_ham.matrix)
Exemplo n.º 2
0
def test_trotter_hamiltonian_operation_errors():
    """Test errors in ``SymbolicHamiltonian`` addition and subtraction."""
    h1 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(3, h=1.0))
    h2 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(4, h=1.0))
    with pytest.raises(RuntimeError):
        h = h1 + h2
    with pytest.raises(RuntimeError):
        h = h1 - h2
    with pytest.raises(NotImplementedError):
        h = h1 + "test"
    with pytest.raises(NotImplementedError):
        h = "test" + h1
    with pytest.raises(NotImplementedError):
        h = h1 - "test"
    with pytest.raises(NotImplementedError):
        h = "test" - h1
    with pytest.raises(NotImplementedError):
        h = h1 * "test"
    with pytest.raises(NotImplementedError):
        h = h1 @ "test"
    with pytest.raises(NotImplementedError):
        h = h1 @ np.ones((2, 2, 2, 2))
    h2 = hamiltonians.XXZ(3, dense=False)
    with pytest.raises(NotImplementedError):
        h = h1 @ h2
Exemplo n.º 3
0
def test_trotter_hamiltonian_three_qubit_term(backend):
    """Test creating ``TrotterHamiltonian`` with three qubit term."""
    from scipy.linalg import expm
    from qibo.core.terms import HamiltonianTerm
    m1 = random_hermitian(3)
    m2 = random_hermitian(2)
    m3 = random_hermitian(1)

    terms = [HamiltonianTerm(m1, 0, 1, 2), HamiltonianTerm(m2, 2, 3),
             HamiltonianTerm(m3, 1)]
    ham = hamiltonians.SymbolicHamiltonian()
    ham.terms = terms

    # Test that the `TrotterHamiltonian` dense matrix is correct
    eye = np.eye(2, dtype=m1.dtype)
    mm1 = np.kron(m1, eye)
    mm2 = np.kron(np.kron(eye, eye), m2)
    mm3 = np.kron(np.kron(eye, m3), np.kron(eye, eye))
    target_ham = hamiltonians.Hamiltonian(4, mm1 + mm2 + mm3)
    K.assert_allclose(ham.matrix, target_ham.matrix)

    dt = 1e-2
    initial_state = random_state(4)
    if K.op is not None:
        with pytest.raises(NotImplementedError):
            circuit = ham.circuit(dt=dt)
    else:
        circuit = ham.circuit(dt=dt)
        final_state = circuit(np.copy(initial_state))
        u = [expm(-0.5j * dt * (mm1 + mm3)), expm(-0.5j * dt * mm2)]
        target_state = u[1].dot(u[0].dot(initial_state))
        target_state = u[0].dot(u[1].dot(target_state))
        K.assert_allclose(final_state, target_state)
def test_tfim_hamiltonian_from_symbols(nqubits, hamtype, calcterms):
    """Check creating TFIM Hamiltonian using sympy."""
    if hamtype == "symbolic":
        from qibo.symbols import X, Z
        h = 0.5
        symham = sum(Z(i) * Z(i + 1) for i in range(nqubits - 1))
        symham += Z(0) * Z(nqubits - 1)
        symham += h * sum(X(i) for i in range(nqubits))
        ham = hamiltonians.SymbolicHamiltonian(-symham)
    else:
        h = 0.5
        z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(nqubits))))
        x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits))))

        symham = sum(z_symbols[i] * z_symbols[i + 1] for i in range(nqubits - 1))
        symham += z_symbols[0] * z_symbols[-1]
        symham += h * sum(x_symbols)
        symmap = {z: (i, matrices.Z) for i, z in enumerate(z_symbols)}
        symmap.update({x: (i, matrices.X) for i, x in enumerate(x_symbols)})
        ham = hamiltonians.Hamiltonian.from_symbolic(-symham, symmap)

    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    target_matrix = hamiltonians.TFIM(nqubits, h=h).matrix
    K.assert_allclose(final_matrix, target_matrix)
def test_from_symbolic_with_power(hamtype, calcterms):
    """Check ``from_symbolic`` when the expression contains powers."""
    if hamtype == "symbolic":
        from qibo.symbols import Symbol
        matrix = random_hermitian(1)
        symham =  (Symbol(0, matrix) ** 2 - Symbol(1, matrix) ** 2 +
                   3 * Symbol(1, matrix) - 2 * Symbol(0, matrix) * Symbol(2, matrix) + 1)
        ham = hamiltonians.SymbolicHamiltonian(symham)
    else:
        z = sympy.symbols(" ".join((f"Z{i}" for i in range(3))))
        symham =  z[0] ** 2 - z[1] ** 2 + 3 * z[1] - 2 * z[0] * z[2] + 1
        matrix = random_hermitian(1)
        symmap = {x: (i, matrix) for i, x in enumerate(z)}
        ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap)

    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    matrix2 = matrix.dot(matrix)
    eye = np.eye(2, dtype=matrix.dtype)
    target_matrix = np.kron(np.kron(matrix2, eye), eye)
    target_matrix -= np.kron(np.kron(eye, matrix2), eye)
    target_matrix += 3 * np.kron(np.kron(eye, matrix), eye)
    target_matrix -= 2 * np.kron(np.kron(matrix, eye), matrix)
    target_matrix += np.eye(8, dtype=matrix.dtype)
    K.assert_allclose(final_matrix, target_matrix)
Exemplo n.º 6
0
def test_symbolic_hamiltonian_hamiltonianmatmul(backend, nqubits, calcterms,
                                                calcdense):
    local_ham1 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=1.0))
    local_ham2 = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                                h=0.5))
    dense_ham1 = hamiltonians.TFIM(nqubits, h=1.0)
    dense_ham2 = hamiltonians.TFIM(nqubits, h=0.5)
    if calcterms:
        _ = local_ham1.terms
        _ = local_ham2.terms
    if calcdense:
        _ = local_ham1.dense
        _ = local_ham2.dense
    local_matmul = local_ham1 @ local_ham2
    target_matmul = dense_ham1 @ dense_ham2
    K.assert_allclose(local_matmul.matrix, target_matmul.matrix)
Exemplo n.º 7
0
def test_symbolic_hamiltonian_errors():
    # Wrong type of Symbol matrix
    from qibo.symbols import Symbol
    with pytest.raises(TypeError):
        s = Symbol(0, "test")
    # Wrong type of symbolic expression
    with pytest.raises(TypeError):
        ham = hamiltonians.SymbolicHamiltonian("test")
    # Passing form with symbol that is not in ``symbol_map``
    from qibo import matrices
    Z, X = sympy.Symbol("Z"), sympy.Symbol("X")
    symbol_map = {Z: (0, matrices.Z)}
    with pytest.raises(ValueError):
        ham = hamiltonians.SymbolicHamiltonian(Z * X, symbol_map)
    # Invalid operation in Hamiltonian expresion
    ham = hamiltonians.SymbolicHamiltonian(sympy.cos(Z), symbol_map)
    with pytest.raises(TypeError):
        dense = ham.dense
Exemplo n.º 8
0
def test_symbolic_hamiltonian_scalar_add(backend, nqubits, calcterms,
                                         calcdense):
    """Test addition of Trotter Hamiltonian with scalar."""
    local_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0))
    target_ham = 2 + hamiltonians.TFIM(nqubits, h=1.0)
    if calcterms:
        _ = local_ham.terms
    if calcdense:
        _ = local_ham.dense
    local_dense = (2 + local_ham).dense
    K.assert_allclose(local_dense.matrix, target_ham.matrix)

    local_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0))
    if calcterms:
        _ = local_ham.terms
    if calcdense:
        _ = local_ham.dense
    local_dense = (local_ham + 2).dense
    K.assert_allclose(local_dense.matrix, target_ham.matrix)
Exemplo n.º 9
0
def test_symbolicxxz_hamiltonian_to_dense(backend, nqubits, calcterms):
    from qibo.symbols import X, Y, Z
    sham = sum(X(i) * X(i + 1) for i in range(nqubits - 1))
    sham += sum(Y(i) * Y(i + 1) for i in range(nqubits - 1))
    sham += 0.5 * sum(Z(i) * Z(i + 1) for i in range(nqubits - 1))
    sham += X(0) * X(nqubits - 1) + Y(0) * Y(nqubits -
                                             1) + 0.5 * Z(0) * Z(nqubits - 1)
    final_ham = hamiltonians.SymbolicHamiltonian(sham)
    target_ham = hamiltonians.XXZ(nqubits)
    if calcterms:
        _ = final_ham.terms
    K.assert_allclose(final_ham.matrix, target_ham.matrix, atol=1e-15)
def test_from_symbolic_application_hamiltonian(calcterms):
    """Check ``from_symbolic`` for a specific four-qubit Hamiltonian."""
    z1, z2, z3, z4 = sympy.symbols("z1 z2 z3 z4")
    symmap = {z: (i, matrices.Z) for i, z in enumerate([z1, z2, z3, z4])}
    symham = (z1 * z2 - 0.5 * z1 * z3 + 2 * z2 * z3 + 0.35 * z2
              + 0.25 * z3 * z4 + 0.5 * z3 + z4 - z1)
    # Check that Trotter dense matrix agrees will full Hamiltonian matrix
    fham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap)
    from qibo.symbols import Z
    symham = (Z(0) * Z(1) - 0.5 * Z(0) * Z(2) + 2 * Z(1) * Z(2) + 0.35 * Z(1)
              + 0.25 * Z(2) * Z(3) + 0.5 * Z(2) + Z(3) - Z(0))
    sham = hamiltonians.SymbolicHamiltonian(symham)
    if calcterms:
        _ = sham.terms
    K.assert_allclose(sham.matrix, fham.matrix)
Exemplo n.º 11
0
def test_symbolic_hamiltonian_abstract_symbol_ev(backend, density_matrix,
                                                 calcterms):
    from qibo.symbols import X, Symbol
    matrix = np.random.random((2, 2))
    form = X(0) * Symbol(1, matrix) + Symbol(0, matrix) * X(1)
    local_ham = hamiltonians.SymbolicHamiltonian(form)
    if calcterms:
        _ = local_ham.terms
    if density_matrix:
        state = K.cast(random_complex((4, 4)))
    else:
        state = K.cast(random_complex((4, )))
    local_ev = local_ham.expectation(state)
    target_ev = local_ham.dense.expectation(state)
    K.assert_allclose(local_ev, target_ev)
def test_hamiltonian_with_identity_symbol(calcterms):
    """Check creating Hamiltonian from expression which contains the identity symbol."""
    from qibo.symbols import I, X, Y, Z
    symham = X(0) * I(1) * Z(2) + 0.5 * Y(0) * Z(1) * I(3) + Z(0) * I(1) * X(2)
    ham = hamiltonians.SymbolicHamiltonian(symham)
    
    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    target_matrix = np.kron(np.kron(matrices.X, matrices.I),
                            np.kron(matrices.Z, matrices.I))
    target_matrix += 0.5 * np.kron(np.kron(matrices.Y, matrices.Z),
                                   np.kron(matrices.I, matrices.I))
    target_matrix += np.kron(np.kron(matrices.Z, matrices.I),
                             np.kron(matrices.X, matrices.I))
    K.assert_allclose(final_matrix, target_matrix)
def test_x_hamiltonian_from_symbols(nqubits, hamtype, calcterms):
    """Check creating sum(X) Hamiltonian using sympy."""
    if hamtype == "symbolic":
        from qibo.symbols import X
        symham = -sum(X(i) for i in range(nqubits))
        ham = hamiltonians.SymbolicHamiltonian(symham)
    else:
        x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(nqubits))))
        symham =  -sum(x_symbols)
        symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)}
        ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap)
    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    target_matrix = hamiltonians.X(nqubits).matrix
    K.assert_allclose(final_matrix, target_matrix)
Exemplo n.º 14
0
def test_symbolic_hamiltonian_matmul(backend, nqubits, density_matrix,
                                     calcterms):
    if density_matrix:
        from qibo.core.states import MatrixState
        shape = (2**nqubits, 2**nqubits)
        state = MatrixState.from_tensor(random_complex(shape))
    else:
        from qibo.core.states import VectorState
        shape = (2**nqubits, )
        state = VectorState.from_tensor(random_complex(shape))
    local_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0))
    dense_ham = hamiltonians.TFIM(nqubits, h=1.0)
    if calcterms:
        _ = local_ham.terms
    local_matmul = local_ham @ state
    target_matmul = dense_ham @ state
    K.assert_allclose(local_matmul, target_matmul)
Exemplo n.º 15
0
def test_symbolic_hamiltonian_state_ev(backend, nqubits, normalize, calcterms,
                                       calcdense):
    local_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                               h=1.0)) + 2
    if calcterms:
        _ = local_ham.terms
    if calcdense:
        _ = local_ham.dense
    dense_ham = hamiltonians.TFIM(nqubits, h=1.0) + 2

    state = K.cast(random_complex((2**nqubits, )))
    local_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(local_ev, target_ev)

    state = random_complex((2**nqubits, ))
    local_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(local_ev, target_ev)
def test_three_qubit_term_hamiltonian_from_symbols(hamtype, calcterms):
    """Check creating Hamiltonian with three-qubit interaction using sympy."""
    if hamtype == "symbolic":
        from qibo.symbols import X, Y, Z
        symham = X(0) * Y(1) * Z(2) + 0.5 * Y(0) * Z(1) * X(3) + Z(0) * X(2)
        symham += Y(2) + 1.5 * Z(1) - 2 - 3 * X(1) * Y(3)
        ham = hamiltonians.SymbolicHamiltonian(symham)
    else:
        x_symbols = sympy.symbols(" ".join((f"X{i}" for i in range(4))))
        y_symbols = sympy.symbols(" ".join((f"Y{i}" for i in range(4))))
        z_symbols = sympy.symbols(" ".join((f"Z{i}" for i in range(4))))
        symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)}
        symmap.update({x: (i, matrices.Y) for i, x in enumerate(y_symbols)})
        symmap.update({x: (i, matrices.Z) for i, x in enumerate(z_symbols)})

        symham = x_symbols[0] * y_symbols[1] * z_symbols[2]
        symham += 0.5 * y_symbols[0] * z_symbols[1] * x_symbols[3]
        symham += z_symbols[0] * x_symbols[2]
        symham += -3 * x_symbols[1] * y_symbols[3]
        symham += y_symbols[2]
        symham += 1.5 * z_symbols[1]
        symham -= 2
        ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap)

    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    target_matrix = np.kron(np.kron(matrices.X, matrices.Y),
                            np.kron(matrices.Z, matrices.I))
    target_matrix += 0.5 * np.kron(np.kron(matrices.Y, matrices.Z),
                                   np.kron(matrices.I, matrices.X))
    target_matrix += np.kron(np.kron(matrices.Z, matrices.I),
                             np.kron(matrices.X, matrices.I))
    target_matrix += -3 * np.kron(np.kron(matrices.I, matrices.X),
                             np.kron(matrices.I, matrices.Y))
    target_matrix += np.kron(np.kron(matrices.I, matrices.I),
                             np.kron(matrices.Y, matrices.I))
    target_matrix += 1.5 * np.kron(np.kron(matrices.I, matrices.Z),
                                   np.kron(matrices.I, matrices.I))
    target_matrix -= 2 * np.eye(2**4, dtype=target_matrix.dtype)
    K.assert_allclose(final_matrix, target_matrix)
def test_from_symbolic_with_complex_numbers(hamtype, calcterms):
    """Check ``from_symbolic`` when the expression contains imaginary unit."""
    if hamtype == "symbolic":
        from qibo.symbols import X, Y
        symham = (1 + 2j) * X(0) * X(1) + 2 * Y(0) * Y(1) - 3j * X(0) * Y(1) + 1j * Y(0) * X(1)
        ham = hamiltonians.SymbolicHamiltonian(symham)
    else:
        x = sympy.symbols(" ".join((f"X{i}" for i in range(2))))
        y = sympy.symbols(" ".join((f"Y{i}" for i in range(2))))
        symham = (1 + 2j) * x[0] * x[1] + 2 * y[0] * y[1] - 3j * x[0] * y[1] + 1j * y[0] * x[1]
        symmap = {s: (i, matrices.X) for i, s in enumerate(x)}
        symmap.update({s: (i, matrices.Y) for i, s in enumerate(y)})
        ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap)

    if calcterms:
        _ = ham.terms
    final_matrix = ham.matrix
    target_matrix = (1 + 2j) * np.kron(matrices.X, matrices.X)
    target_matrix += 2 * np.kron(matrices.Y, matrices.Y)
    target_matrix -= 3j * np.kron(matrices.X, matrices.Y)
    target_matrix += 1j * np.kron(matrices.Y, matrices.X)
    K.assert_allclose(final_matrix, target_matrix)
Exemplo n.º 18
0
def main(nqubits, instance, T, dt, solver, plot, dense, params, method,
         maxiter):
    """Adiabatic evoluition to find the solution of an exact cover instance.

    Args:
        nqubits (int): number of qubits for the file that contains the
            information of an Exact Cover instance.
        instance (int): intance used for the desired number of qubits.
        T (float): maximum schedule time. The larger T, better final results.
        dt (float): time interval for the evolution.
        solver (str): solver used for the adiabatic evolution.
        plot (bool): decides if plots of the energy and gap will be returned.
        dense (bool): decides if the full Hamiltonian matrix will be used.
        params (list): list of polynomial coefficients for scheduling function.
            Default is linear scheduling.
        method (str): Method to use for scheduling optimization (optional).
        maxiter (bool): Maximum iterations for scheduling optimization (optional).

    Returns:
        Result of the most probable outcome after the adiabatic evolution.
        Plots of the ground and excited state energies and the underlying gap
        during the adiabatic evolution. The plots are created only if the
        ``--plot`` option is enabled.
    """
    # Read 3SAT clauses from file
    control, solution, clauses = functions.read_file(nqubits, instance)
    nqubits = int(control[0])
    # Define "easy" and "problem" Hamiltonians
    times = functions.times(nqubits, clauses)
    sh0 = functions.h_initial(nqubits, times)
    sh1 = functions.h_problem(nqubits, clauses)
    gs = lambda: functions.ground_state(nqubits)
    H0 = hamiltonians.SymbolicHamiltonian(sh0, ground_state=gs)
    H1 = hamiltonians.SymbolicHamiltonian(sh1)
    if dense:
        print('Using the full Hamiltonian evolution\n')
        H0, H1 = H0.dense, H1.dense
    else:
        print('Using Trotter decomposition for the Hamiltonian\n')

    print('-' * 20 + '\n')
    if plot and nqubits >= 14:
        print('Currently not possible to calculate gap energy for {} qubits.'
              '\n Proceeding to adiabatic evolution without plotting data.\n'
              ''.format(nqubits))
        plot = False
    if plot and method is not None:
        print('Not possible to calculate gap energy during optimization.')
        plot = False

    # Define scheduling according to given params
    if params is None:
        # default is linear scheduling
        s = lambda t: t
    else:
        if method is None:
            s = lambda t: functions.spolynomial(t, params)
        else:
            s = functions.spolynomial

    # Define evolution model and (optionally) callbacks
    if plot:
        ground = callbacks.Gap(0)
        excited = callbacks.Gap(1)
        gap = callbacks.Gap()
        evolve = models.AdiabaticEvolution(H0,
                                           H1,
                                           s,
                                           dt,
                                           solver=solver,
                                           callbacks=[gap, ground, excited])
    else:
        evolve = models.AdiabaticEvolution(H0, H1, s, dt, solver=solver)

    if method is not None:
        print(f'Optimizing scheduling using {method}.\n')
        if params is None:
            params = [T]
        else:
            params.append(T)
        if method == "sgd":
            options = {"nepochs": maxiter}
        else:
            options = {"maxiter": maxiter, "disp": True}
        energy, params, _ = evolve.minimize(params,
                                            method=method,
                                            options=options)
        T = params[-1]

    # Perform evolution
    initial_state = np.ones(2**nqubits) / np.sqrt(2**nqubits)
    final_state = evolve(final_time=T, initial_state=initial_state)
    output_dec = (np.abs(K.to_numpy(final_state))**2).argmax()
    max_output = "{0:0{bits}b}".format(output_dec, bits=nqubits)
    max_prob = (np.abs(K.to_numpy(final_state))**2).max()
    print("Exact cover instance with {} qubits.\n".format(nqubits))
    if solution:
        print('Known solution: {}\n'.format(''.join(solution)))
    print('-' * 20 + '\n')
    print(f'Adiabatic evolution with total time {T}, evolution step {dt} and '
          f'solver {solver}.\n')
    print(f'Most common solution after adiabatic evolution: {max_output}.\n')
    print(f'Found with probability: {max_prob}.\n')
    if plot:
        print('-' * 20 + '\n')
        functions.plot(nqubits, ground[:], excited[:], gap[:], dt, T)
        print('Plots finished.\n')
Exemplo n.º 19
0
def test_symbolictfim_hamiltonian_to_dense(backend, nqubits, calcterms):
    final_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits, h=1))
    target_ham = hamiltonians.TFIM(nqubits, h=1)
    if calcterms:
        _ = final_ham.terms
    K.assert_allclose(final_ham.matrix, target_ham.matrix, atol=1e-15)