def test_gap(trotter): """Check gap callback for adiabatic evolution model.""" from qibo import hamiltonians h0 = hamiltonians.X(3, trotter=trotter) h1 = hamiltonians.TFIM(3, h=1.0, trotter=trotter) ham = lambda t: ((1 - t) * h0.matrix + t * h1.matrix).numpy() targets = {"ground": [], "excited": [], "gap": []} for t in np.linspace(0, 1, 11): eigvals = np.linalg.eigvalsh(ham(t)).real targets["ground"].append(eigvals[0]) targets["excited"].append(eigvals[1]) targets["gap"].append(eigvals[1] - eigvals[0]) gap = callbacks.Gap() ground = callbacks.Gap(0) excited = callbacks.Gap(1) evolution = AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-1, callbacks=[gap, ground, excited]) final_state = evolution(final_time=1.0) np.testing.assert_allclose(ground[:], targets["ground"]) np.testing.assert_allclose(excited[:], targets["excited"]) np.testing.assert_allclose(gap[:], targets["gap"]) # check not implemented for density matrices with pytest.raises(NotImplementedError): gap(np.zeros(8), is_density_matrix=True)
def test_gap(backend, dense, check_degenerate): from qibo import hamiltonians h0 = hamiltonians.X(4, dense=dense) if check_degenerate: # use h=0 to make this Hamiltonian degenerate h1 = hamiltonians.TFIM(4, h=0, dense=dense) else: h1 = hamiltonians.TFIM(4, h=1, dense=dense) ham = lambda t: (1 - t) * h0.matrix + t * h1.matrix targets = {"ground": [], "excited": [], "gap": []} for t in np.linspace(0, 1, 11): eigvals = np.linalg.eigvalsh(ham(t)).real targets["ground"].append(eigvals[0]) targets["excited"].append(eigvals[1]) targets["gap"].append(eigvals[1] - eigvals[0]) if check_degenerate: targets["gap"][-1] = eigvals[3] - eigvals[0] gap = callbacks.Gap(check_degenerate=check_degenerate) ground = callbacks.Gap(0) excited = callbacks.Gap(1) evolution = AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-1, callbacks=[gap, ground, excited]) final_state = evolution(final_time=1.0) targets = {k: K.stack(v) for k, v in targets.items()} K.assert_allclose(ground[:], targets["ground"]) K.assert_allclose(excited[:], targets["excited"]) K.assert_allclose(gap[:], targets["gap"])
def test_gap(backend, trotter, check_degenerate): original_backend = qibo.get_backend() qibo.set_backend(backend) from qibo import hamiltonians h0 = hamiltonians.X(4, trotter=trotter) if check_degenerate: # use h=0 to make this Hamiltonian degenerate h1 = hamiltonians.TFIM(4, h=0, trotter=trotter) else: h1 = hamiltonians.TFIM(4, h=1, trotter=trotter) ham = lambda t: (1 - t) * h0.matrix + t * h1.matrix targets = {"ground": [], "excited": [], "gap": []} for t in np.linspace(0, 1, 11): eigvals = np.linalg.eigvalsh(ham(t)).real targets["ground"].append(eigvals[0]) targets["excited"].append(eigvals[1]) targets["gap"].append(eigvals[1] - eigvals[0]) if check_degenerate: targets["gap"][-1] = eigvals[3] - eigvals[0] gap = callbacks.Gap(check_degenerate=check_degenerate) ground = callbacks.Gap(0) excited = callbacks.Gap(1) evolution = AdiabaticEvolution(h0, h1, lambda t: t, dt=1e-1, callbacks=[gap, ground, excited]) final_state = evolution(final_time=1.0) np.testing.assert_allclose(ground[:], targets["ground"]) np.testing.assert_allclose(excited[:], targets["excited"]) np.testing.assert_allclose(gap[:], targets["gap"]) qibo.set_backend(original_backend)
def test_gap_errors(): """Check errors in gap callback instantiation.""" # invalid string ``mode`` with pytest.raises(ValueError): gap = callbacks.Gap("test") # invalid ``mode`` type with pytest.raises(TypeError): gap = callbacks.Gap([]) # invalid evolution model type with pytest.raises(TypeError): gap = callbacks.Gap() gap.evolution = "test" # call before setting evolution model with pytest.raises(ValueError): gap = callbacks.Gap() gap(np.ones(4))
def test_gap_errors(): """Check errors in gap callback instantiation.""" # invalid string ``mode`` with pytest.raises(ValueError): gap = callbacks.Gap("test") # invalid ``mode`` type with pytest.raises(TypeError): gap = callbacks.Gap([]) gap = callbacks.Gap() # invalid evolution model type with pytest.raises(TypeError): gap.evolution = "test" # call before setting evolution model with pytest.raises(ValueError): gap(np.ones(4)) # not implemented for density matrices gap.density_matrix = True with pytest.raises(NotImplementedError): gap(np.zeros(8)) # for coverage _ = gap.density_matrix gap.density_matrix = False
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')