示例#1
0
def test_adiabatic_evolution_execute_errors():
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)
    # Non-zero ``start_time``
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    with pytest.raises(NotImplementedError):
        final_state = adev(final_time=2, start_time=1)
    # execute without specifying variational parameters
    sp = lambda t, p: (1 - p) * np.sqrt(t) + p * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, dt=1e-1)
    with pytest.raises(RuntimeError):
        final_state = adevp(final_time=1)
示例#2
0
def test_adiabatic_evolution_schedule():
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    assert adev.schedule(0.2) == 0.2  # pylint: disable=E1102
    assert adev.schedule(0.8) == 0.8  # pylint: disable=E1102
    # s(0) != 0
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, lambda t: t + 1, dt=1e-2)
    # s(T) != 0
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, lambda t: t / 2, dt=1e-2)
示例#3
0
def test_set_scheduling_parameters():
    """Test ``AdiabaticEvolution.set_parameters``."""
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)
    sp = lambda t, p: (1 - p[0]) * np.sqrt(t) + p[0] * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, 1e-2)
    adevp.set_parameters([0.5, 1])
    final_psi = adevp(final_time=1)

    s = lambda t: 0.5 * np.sqrt(t) + 0.5 * t
    adev = models.AdiabaticEvolution(h0, h1, s, 1e-2)
    target_psi = adev(final_time=1)
    np.testing.assert_allclose(final_psi, target_psi)
示例#4
0
def test_trotter_hamiltonian_t(nqubits, h=1.0, dt=1e-3):
    """Test using ``TrotterHamiltonian`` in adiabatic evolution model."""
    dense_h0 = hamiltonians.X(nqubits)
    dense_h1 = hamiltonians.TFIM(nqubits, h=h)
    dense_adev = models.AdiabaticEvolution(dense_h0, dense_h1, lambda t: t, dt)

    local_h0 = hamiltonians.X(nqubits, trotter=True)
    local_h1 = hamiltonians.TFIM(nqubits, h=h, trotter=True)
    local_adev = models.AdiabaticEvolution(local_h0, local_h1, lambda t: t, dt)

    for t in np.random.random(10):
        local_matrix = local_adev.hamiltonian(t, total_time=1).dense.matrix
        target_matrix = dense_adev.hamiltonian(t, total_time=1).matrix
        np.testing.assert_allclose(local_matrix, target_matrix)
示例#5
0
def test_adiabatic_evolution_errors():
    """Test errors of ``AdiabaticEvolution`` model."""
    # Hamiltonians of bad type
    h0 = hamiltonians.X(3)
    s = lambda t: t
    with pytest.raises(TypeError):
        adev = models.AdiabaticEvolution(h0, lambda t: h0, s, dt=1e-2)
    h1 = hamiltonians.TFIM(2)
    with pytest.raises(TypeError):
        adev = models.AdiabaticEvolution(lambda t: h1, h1, s, dt=1e-2)
    # Hamiltonians with different number of qubits
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, s, dt=1e-2)
    # s with three arguments
    h0 = hamiltonians.X(2)
    s = lambda t, a, b: t + a + b
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, s, dt=1e-2)
    # s(0) != 0
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, lambda t: t + 1, dt=1e-2)
    # s(T) != 0
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, lambda t: t / 2, dt=1e-2)
    # Non-zero ``start_time``
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    with pytest.raises(NotImplementedError):
        final_state = adev(final_time=2, start_time=1)
    # execute without specifying variational parameters
    sp = lambda t, p: (1 - p) * np.sqrt(t) + p * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, dt=1e-1)
    with pytest.raises(ValueError):
        final_state = adevp(final_time=1)
示例#6
0
def main(nqubits_list, dt, solver, trotter=False, accelerators=None):
    """Performs adiabatic evolution with critical TFIM as the "hard" Hamiltonian."""
    if accelerators is not None:
        trotter = True
        solver = "exp"

    print(f"Using {solver} solver and dt = {dt}.")
    print(f"Accelerators: {accelerators}")

    for nqubits in nqubits_list:
        start_time = time.time()
        h0 = hamiltonians.X(nqubits, trotter=trotter)
        h1 = hamiltonians.TFIM(nqubits, h=1.0, trotter=trotter)
        ham_creation_time = time.time() - start_time
        print(f"\nnqubits = {nqubits}, solver = {solver}")
        print(f"trotter = {trotter}, accelerators = {accelerators}")
        print("Hamiltonians created in:", ham_creation_time)

        start_time = time.time()
        evolution = models.AdiabaticEvolution(h0,
                                              h1,
                                              lambda t: t,
                                              dt=dt,
                                              solver=solver,
                                              accelerators=accelerators)
        creation_time = time.time() - start_time
        print("Evolution model created in:", creation_time)

        start_time = time.time()
        final_psi = evolution(final_time=1.0)
        simulation_time = time.time() - start_time
        print("Simulation time:", simulation_time)
示例#7
0
def test_energy_callback(solver, dt, atol):
    """Test using energy callback in adiabatic evolution."""
    h0 = hamiltonians.X(2)
    h1 = hamiltonians.TFIM(2)
    energy = callbacks.Energy(h1)
    adev = models.AdiabaticEvolution(h0,
                                     h1,
                                     lambda t: t,
                                     dt=dt,
                                     callbacks=[energy],
                                     solver=solver)
    final_psi = adev(final_time=1)

    target_psi = np.ones(4) / 2
    calc_energy = lambda psi: psi.conj().dot(K.to_numpy(h1.matrix).dot(psi))
    target_energies = [calc_energy(target_psi)]
    ham = lambda t: h0 * (1 - t) + h1 * t
    for n in range(int(1 / dt)):
        prop = K.to_numpy(ham(n * dt).exp(dt))
        target_psi = prop.dot(target_psi)
        target_energies.append(calc_energy(target_psi))

    assert_states_equal(final_psi, target_psi, atol=atol)
    target_energies = K.cast(target_energies)
    K.assert_allclose(energy[:], target_energies, atol=atol)
示例#8
0
def test_adiabatic_evolution_hamiltonian(backend, dense):
    """Test adiabatic evolution hamiltonian as a function of time."""
    h0 = hamiltonians.X(2, dense=dense)
    h1 = hamiltonians.TFIM(2, dense=dense)
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    # try accessing hamiltonian before setting it
    with pytest.raises(RuntimeError):
        adev.hamiltonian(0.1)

    m1 = np.array([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]])
    m2 = np.diag([2, -2, -2, 2])
    ham = lambda t, T: -(1 - t / T) * m1 - (t / T) * m2

    adev.hamiltonian.total_time = 1
    for t in [0, 0.3, 0.7, 1.0]:
        if dense:
            matrix = adev.hamiltonian(t).matrix
        else:
            matrix = adev.hamiltonian(t).dense.matrix
        K.assert_allclose(matrix, ham(t, 1))

    #try using a different total time
    adev.hamiltonian.total_time = 2
    for t in [0, 0.3, 0.7, 1.0]:
        if dense:
            matrix = adev.hamiltonian(t).matrix
        else:
            matrix = adev.hamiltonian(t).dense.matrix
        K.assert_allclose(matrix, ham(t, 2))
示例#9
0
def test_initial_state():
    """Test that adiabatic evolution initial state is the ground state of H0."""
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    target_psi = np.ones(8) / np.sqrt(8)
    init_psi = adev.get_initial_state()
    assert_states_equal(init_psi, target_psi)
示例#10
0
def main(nqubits, hfield, T, dt, solver, save):
    """Performs adiabatic evolution with critical TFIM as the "hard" Hamiltonian.

    Plots how the <H1> energy and the overlap with the actual ground state
    changes during the evolution.
    Linear scheduling is used.

    Args:
        nqubits (int): Number of qubits in the system.
        hfield (float): Transverse field Ising model h-field h value.
        T (float): Total time of the adiabatic evolution.
        dt (float): Time step used for integration.
        solver (str): Solver used for integration.
        save (bool): Whether to save the plots.
    """
    h0 = hamiltonians.X(nqubits)
    h1 = hamiltonians.TFIM(nqubits, h=hfield)

    # Calculate target values (H1 ground state)
    target_state = h1.ground_state()
    target_energy = h1.eigenvalues()[0].numpy().real

    # Check ground state
    state_energy = callbacks.Energy(h1)(target_state).numpy()
    np.testing.assert_allclose(state_energy.real, target_energy)

    energy = callbacks.Energy(h1)
    overlap = callbacks.Overlap(target_state)
    evolution = models.AdiabaticEvolution(h0,
                                          h1,
                                          lambda t: t,
                                          dt=dt,
                                          solver=solver,
                                          callbacks=[energy, overlap])
    final_psi = evolution(final_time=T)

    # Plots
    tt = np.linspace(0, T, int(T / dt) + 1)
    plt.figure(figsize=(12, 4))
    plt.subplot(121)
    plt.plot(tt, energy[:], linewidth=2.0, label="Evolved state")
    plt.axhline(y=target_energy,
                color="red",
                linewidth=2.0,
                label="Ground state")
    plt.xlabel("$t$")
    plt.ylabel("$H_1$")
    plt.legend()

    plt.subplot(122)
    plt.plot(tt, overlap[:], linewidth=2.0)
    plt.xlabel("$t$")
    plt.ylabel("Overlap")

    if save:
        plt.savefig(f"images/dynamics_n{nqubits}T{T}.png", bbox_inches="tight")
    else:
        plt.show()
示例#11
0
def test_adiabatic_evolution_init():
    # Hamiltonians of bad type
    h0 = hamiltonians.X(3)
    s = lambda t: t
    with pytest.raises(TypeError):
        adev = models.AdiabaticEvolution(h0, lambda t: h0, s, dt=1e-2)
    h1 = hamiltonians.TFIM(2)
    with pytest.raises(TypeError):
        adev = models.AdiabaticEvolution(lambda t: h1, h1, s, dt=1e-2)
    # Hamiltonians with different number of qubits
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, s, dt=1e-2)
    # Adiabatic Hamiltonian with bad hamiltonian types
    from qibo.core.adiabatic import AdiabaticHamiltonian
    with pytest.raises(TypeError):
        h = AdiabaticHamiltonian("a", "b")  # pylint: disable=E0110
    # s with three arguments
    h0 = hamiltonians.X(2)
    s = lambda t, a, b: t + a + b
    with pytest.raises(ValueError):
        adev = models.AdiabaticEvolution(h0, h1, s, dt=1e-2)
示例#12
0
def main(nqubits, hfield, params, dt, solver, method, maxiter, save):
    """Optimizes the scheduling of the adiabatic evolution.

    The ansatz for s(t) is a polynomial whose order is defined by the length of
    ``params`` given.

    Args:
        nqubits (int): Number of qubits in the system.
        hfield (float): Transverse field Ising model h-field h value.
        params (str): Initial guess for the free parameters.
        dt (float): Time step used for integration.
        solver (str): Solver used for integration.
        method (str): Which scipy optimizer to use.
        maxiter (int): Maximum iterations for scipy optimizer.
        save (str): Name to use for saving optimization history.
            If ``None`` history will not be saved.
    """
    h0 = hamiltonians.X(nqubits)
    h1 = hamiltonians.TFIM(nqubits, h=hfield)

    # Calculate target values (H1 ground state)
    target_state = h1.ground_state()
    target_energy = h1.eigenvalues()[0].numpy().real

    # Check ground state
    state_energy = callbacks.Energy(h1)(target_state).numpy()
    np.testing.assert_allclose(state_energy.real, target_energy)

    evolution = models.AdiabaticEvolution(h0,
                                          h1,
                                          spolynomial,
                                          dt=dt,
                                          solver=solver)
    options = {"maxiter": maxiter, "disp": True}
    energy, parameters, _ = evolution.minimize(params,
                                               method=method,
                                               options=options,
                                               messages=True)

    print("\nBest energy found:", energy)
    print("Final parameters:", parameters)

    final_state = evolution(parameters[-1])
    overlap = callbacks.Overlap(target_state)(final_state).numpy()
    print("Target energy:", target_energy)
    print("Overlap:", overlap)

    if save:
        evolution.opt_history["loss"].append(target_energy)
        np.save(f"optparams/{save}_n{nqubits}_loss.npy",
                evolution.opt_history["loss"])
        np.save(f"optparams/{save}_n{nqubits}_params.npy",
                evolution.opt_history["params"])
示例#13
0
def test_scheduling_optimization(method, options, messages, trotter, filename):
    """Test optimization of s(t)."""
    h0 = hamiltonians.X(3, trotter=trotter)
    h1 = hamiltonians.TFIM(3, trotter=trotter)
    sp = lambda t, p: (1 - p) * np.sqrt(t) + p * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, dt=1e-1)
    best, params = adevp.minimize([0.5, 1],
                                  method=method,
                                  options=options,
                                  messages=messages)
    if filename is not None:
        utils.assert_regression_fixture(params, filename)
示例#14
0
def main(nqubits,
         dt,
         solver,
         backend,
         dense=False,
         accelerators=None,
         filename=None):
    """Performs adiabatic evolution with critical TFIM as the "hard" Hamiltonian."""
    qibo.set_backend(backend)
    if accelerators is not None:
        dense = False
        solver = "exp"

    logs = BenchmarkLogger(filename)
    logs.append({
        "nqubits": nqubits,
        "dt": dt,
        "solver": solver,
        "dense": dense,
        "backend": qibo.get_backend(),
        "precision": qibo.get_precision(),
        "device": qibo.get_device(),
        "threads": qibo.get_threads(),
        "accelerators": accelerators
    })
    print(f"Using {solver} solver and dt = {dt}.")
    print(f"Accelerators: {accelerators}")
    print("Backend:", logs[-1]["backend"])

    start_time = time.time()
    h0 = hamiltonians.X(nqubits, dense=dense)
    h1 = hamiltonians.TFIM(nqubits, h=1.0, dense=dense)
    logs[-1]["hamiltonian_creation_time"] = time.time() - start_time
    print(f"\nnqubits = {nqubits}, solver = {solver}")
    print(f"dense = {dense}, accelerators = {accelerators}")
    print("Hamiltonians created in:", logs[-1]["hamiltonian_creation_time"])

    start_time = time.time()
    evolution = models.AdiabaticEvolution(h0,
                                          h1,
                                          lambda t: t,
                                          dt=dt,
                                          solver=solver,
                                          accelerators=accelerators)
    logs[-1]["creation_time"] = time.time() - start_time
    print("Evolution model created in:", logs[-1]["creation_time"])

    start_time = time.time()
    final_psi = evolution(final_time=1.0)
    logs[-1]["simulation_time"] = time.time() - start_time
    print("Simulation time:", logs[-1]["simulation_time"])
    logs.dump()
示例#15
0
def test_set_scheduling_parameters():
    """Test ``AdiabaticEvolution.set_parameters``."""
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)
    sp = lambda t, p: (1 - p[0]) * np.sqrt(t) + p[0] * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, 1e-2)
    # access parametrized scheduling before setting parameters
    with pytest.raises(ValueError):
        s = adevp.schedule

    adevp.set_parameters([0.5, 1])

    target_s = lambda t: 0.5 * np.sqrt(t) + 0.5 * t
    for t in np.random.random(10):
        assert adevp.schedule(t) == target_s(t)  # pylint: disable=E1102
示例#16
0
def test_adiabatic_evolution(dt):
    """Test adiabatic evolution with exponential solver."""
    h0 = hamiltonians.X(2)
    h1 = hamiltonians.TFIM(2)
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=dt)

    m1 = np.array([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]])
    m2 = np.diag([2, -2, -2, 2])
    ham = lambda t: -(1 - t) * m1 - t * m2

    target_psi = np.ones(4) / 2
    nsteps = int(1 / dt)
    for n in range(nsteps):
        target_psi = expm(-1j * dt * ham(n * dt)).dot(target_psi)
    final_psi = adev(final_time=1)
    assert_states_equal(final_psi, target_psi)
示例#17
0
def test_rk4_evolution(solver, dt=1e-3):
    """Test adiabatic evolution with Runge-Kutta solver."""
    h0 = hamiltonians.X(3)
    h1 = hamiltonians.TFIM(3)

    target_psi = [np.ones(8) / np.sqrt(8)]
    ham = lambda t: h0 * (1 - t) + h1 * t
    for n in range(int(1 / dt)):
        prop = ham(n * dt).exp(dt).numpy()
        target_psi.append(prop.dot(target_psi[-1]))

    checker = TimeStepChecker(target_psi, atol=dt)
    adev = models.AdiabaticEvolution(h0,
                                     h1,
                                     lambda t: t,
                                     dt,
                                     solver="rk4",
                                     callbacks=[checker])
    final_psi = adev(final_time=1, initial_state=np.copy(target_psi[0]))
示例#18
0
def test_trotterized_adiabatic_evolution(nqubits, accelerators, dt):
    """Test adiabatic evolution using trotterization of ``TrotterHamiltonian``."""
    dense_h0 = hamiltonians.X(nqubits)
    dense_h1 = hamiltonians.TFIM(nqubits)

    target_psi = [np.ones(2**nqubits) / np.sqrt(2**nqubits)]
    ham = lambda t: dense_h0 * (1 - t) + dense_h1 * t
    for n in range(int(1 / dt)):
        prop = ham(n * dt).exp(dt).numpy()
        target_psi.append(prop.dot(target_psi[-1]))

    local_h0 = hamiltonians.X(nqubits, trotter=True)
    local_h1 = hamiltonians.TFIM(nqubits, trotter=True)
    checker = TimeStepChecker(target_psi, atol=dt)
    adev = models.AdiabaticEvolution(local_h0,
                                     local_h1,
                                     lambda t: t,
                                     dt,
                                     callbacks=[checker],
                                     accelerators=accelerators)
    final_psi = adev(final_time=1)
示例#19
0
def test_hamiltonian_t():
    """Test adiabatic evolution hamiltonian as a function of time."""
    h0 = hamiltonians.X(2)
    h1 = hamiltonians.TFIM(2)
    adev = models.AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-2)
    # try accessing hamiltonian before setting it
    with pytest.raises(RuntimeError):
        adev.hamiltonian()

    m1 = np.array([[0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 1, 0]])
    m2 = np.diag([2, -2, -2, 2])
    ham = lambda t, T: -(1 - t / T) * m1 - (t / T) * m2

    adev.set_hamiltonian(total_time=1)
    for t in [0, 0.3, 0.7, 1.0]:
        matrix = adev.hamiltonian(t).matrix
        np.testing.assert_allclose(matrix, ham(t, 1))
    #try using a different total time
    for t in [0, 0.3, 0.7, 1.0]:
        matrix = adev.hamiltonian(t, total_time=2).matrix
        np.testing.assert_allclose(matrix, ham(t, 2))
示例#20
0
def test_scheduling_optimization(method, options, messages, dense, filename):
    """Test optimization of s(t)."""
    from qibo.tests.test_models_variational import assert_regression_fixture
    h0 = hamiltonians.X(3, dense=dense)
    h1 = hamiltonians.TFIM(3, dense=dense)
    sp = lambda t, p: (1 - p) * np.sqrt(t) + p * t
    adevp = models.AdiabaticEvolution(h0, h1, sp, dt=1e-1)

    if method == "sgd":
        from qibo import K
        if not K.supports_gradients:
            with pytest.raises(RuntimeError):
                best, params, _ = adevp.minimize([0.5, 1],
                                                 method=method,
                                                 options=options,
                                                 messages=messages)
    else:
        best, params, _ = adevp.minimize([0.5, 1],
                                         method=method,
                                         options=options,
                                         messages=messages)

    if filename is not None:
        assert_regression_fixture(params, filename)
示例#21
0
def main(nqubits, instance, T, dt, solver, plot, trotter, 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.
        trotter (bool): decides if a Trotter Hamiltonian 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, smap0 = functions.h_initial(nqubits, times)
    sh1, smap1 = functions.h_problem(nqubits, clauses)
    if trotter:
        print('Using Trotter decomposition for the Hamiltonian\n')
        gs = lambda: functions.ground_state(nqubits)
        H0 = hamiltonians.TrotterHamiltonian.from_symbolic(sh0,
                                                           smap0,
                                                           ground_state=gs)
        H1 = hamiltonians.TrotterHamiltonian.from_symbolic(sh1, smap1)
    else:
        print('Using the full Hamiltonian evolution\n')
        H0 = hamiltonians.Hamiltonian.from_symbolic(sh0, smap0)
        H1 = hamiltonians.Hamiltonian.from_symbolic(sh1, smap1)

    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(final_state.numpy())**2).argmax()
    max_output = "{0:0{bits}b}".format(output_dec, bits=nqubits)
    max_prob = (np.abs(final_state.numpy())**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')