def test_state_evolution_trotter_hamiltonian(backend, accelerators, nqubits, solver, dt, atol): if accelerators is not None and solver != "exp": pytest.skip("Distributed evolution is supported only with exp solver.") h = 1.0 target_psi = [np.ones(2**nqubits) / np.sqrt(2**nqubits)] ham_matrix = K.to_numpy(hamiltonians.TFIM(nqubits, h=h).matrix) prop = expm(-1j * dt * ham_matrix) for n in range(int(1 / dt)): target_psi.append(prop.dot(target_psi[-1])) ham = hamiltonians.TFIM(nqubits, h=h, dense=False) checker = TimeStepChecker(target_psi, atol=atol) evolution = models.StateEvolution(ham, dt, solver=solver, callbacks=[checker], accelerators=accelerators) final_psi = evolution(final_time=1, initial_state=np.copy(target_psi[0])) # Change dt if solver == "exp": evolution = models.StateEvolution(ham, dt / 10, accelerators=accelerators) final_psi = evolution(final_time=1, initial_state=np.copy(target_psi[0])) assert_states_equal(final_psi.tensor, target_psi[-1], atol=atol)
def main(nqubits, hfield, T, save): """Compares exact with Trotterized state evolution. Plots the overlap between the exact final state and the state from the Trotterized evolution as a function of the number of time steps used for the discretization of time. The transverse field Ising model (TFIM) is used as a toy model for this experiment. 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. save (bool): Whether to save the plots. """ dense_h = hamiltonians.TFIM(nqubits, h=hfield) trotter_h = hamiltonians.TFIM(nqubits, h=hfield, trotter=True) initial_state = np.ones(2 ** nqubits) / np.sqrt(2 ** nqubits) nsteps_list = np.arange(50, 550, 50) overlaps = [] for nsteps in nsteps_list: exact_ev = models.StateEvolution(dense_h, dt=T/nsteps) trotter_ev = models.StateEvolution(trotter_h, dt=T/nsteps) exact_state = exact_ev(final_time=T, initial_state=np.copy(initial_state)) trotter_state = trotter_ev(final_time=T, initial_state=np.copy(initial_state)) overlaps.append(callbacks.Overlap(exact_state)(trotter_state).numpy()) dt_list = T / nsteps_list overlaps = 1 - np.array(overlaps) exponent = int(linregress(np.log(dt_list), np.log(overlaps))[0]) err = [overlaps[0] * (dt_list / dt_list[0])**(exponent - 1), overlaps[0] * (dt_list / dt_list[0])**exponent, overlaps[0] * (dt_list / dt_list[0])**(exponent + 1)] alphas = [1.0, 0.7, 0.4] labels = [r"$\delta t ^{}$".format(exponent - 1), r"$\delta t ^{}$".format(exponent), r"$\delta t ^{}$".format(exponent + 1)] plt.figure(figsize=(7, 4)) plt.semilogy(nsteps_list, overlaps, marker="o", markersize=8, linewidth=2.0, label="Error") for e, a, l in zip(err, alphas, labels): plt.semilogy(nsteps_list, e, color="red", alpha=a, linestyle="--", linewidth=2.0, label=l) plt.xlabel("Number of steps") plt.ylabel("$1 -$ Overlap") plt.legend() if save: plt.savefig(f"images/trotter_error_n{nqubits}T{T}.png", bbox_inches="tight") else: plt.show()
def test_state_evolution_init(): ham = hamiltonians.Z(2) evolution = models.StateEvolution(ham, dt=1) assert evolution.nqubits == 2 # time-dependent Hamiltonian bad type with pytest.raises(TypeError): evol = models.StateEvolution(lambda t: "abc", dt=1e-2) # dt < 0 with pytest.raises(ValueError): adev = models.StateEvolution(ham, dt=-1e-2) # pass accelerators without trotter Hamiltonian with pytest.raises(NotImplementedError): adev = models.StateEvolution(ham, dt=1e-2, accelerators={"/GPU:0": 2})
def test_state_evolution_errors(): """Test ``ValueError``s for ``StateEvolution`` model.""" ham = hamiltonians.Z(2) evolution = models.StateEvolution(ham, dt=1) # time-dependent Hamiltonian bad type with pytest.raises(TypeError): evol = models.StateEvolution(lambda t: "abc", dt=1e-2) # execute without initial state with pytest.raises(ValueError): final_state = evolution(final_time=1) # dt < 0 with pytest.raises(ValueError): adev = models.StateEvolution(ham, dt=-1e-2) # pass accelerators without trotter Hamiltonian with pytest.raises(NotImplementedError): adev = models.StateEvolution(ham, dt=1e-2, accelerators={"/GPU:0": 2})
def test_state_evolution_final_state(): """Check time-independent Hamiltonian state evolution.""" evolution = models.StateEvolution(hamiltonians.Z(2), dt=1) # Analytical solution phase = np.exp(2j) initial_psi = np.ones(4) / 2 target_psi = np.array([phase, 1, 1, phase.conj()]) final_psi = evolution(final_time=1, initial_state=initial_psi) assert_states_equal(final_psi, target_psi)
def test_trotterized_evolution(nqubits, accelerators, dt, h=1.0): """Test state evolution using trotterization of ``TrotterHamiltonian``.""" target_psi = [np.ones(2**nqubits) / np.sqrt(2**nqubits)] ham_matrix = np.array(hamiltonians.TFIM(nqubits, h=h).matrix) prop = expm(-1j * dt * ham_matrix) for n in range(int(1 / dt)): target_psi.append(prop.dot(target_psi[-1])) ham = hamiltonians.TFIM(nqubits, h=h, trotter=True) checker = TimeStepChecker(target_psi, atol=1e-4) evolution = models.StateEvolution(ham, dt, callbacks=[checker], accelerators=accelerators) final_psi = evolution(final_time=1, initial_state=np.copy(target_psi[0])) # Change dt evolution = models.StateEvolution(ham, dt / 10, accelerators=accelerators) final_psi = evolution(final_time=1, initial_state=np.copy(target_psi[0])) assert_states_equal(final_psi, target_psi[-1], atol=1e-4)
def test_state_evolution_time_dependent_hamiltonian(backend, nqubits, dt): ham = lambda t: np.cos(t) * hamiltonians.Z(nqubits) # Analytical solution target_psi = [np.ones(2**nqubits) / np.sqrt(2**nqubits)] for n in range(int(1 / dt)): prop = expm(-1j * dt * K.to_numpy(ham(n * dt).matrix)) target_psi.append(prop.dot(target_psi[-1])) checker = TimeStepChecker(target_psi, atol=1e-8) evolution = models.StateEvolution(ham, dt=dt, callbacks=[checker]) final_psi = evolution(final_time=1, initial_state=np.copy(target_psi[0]))
def test_state_evolution_constant_hamiltonian(backend, solver, atol): nsteps = 200 t = np.linspace(0, 1, nsteps + 1) phase = np.exp(2j * t)[:, np.newaxis] ones = np.ones((nsteps + 1, 2)) target_psi = np.concatenate([phase, ones, phase.conj()], axis=1) dt = t[1] - t[0] checker = TimeStepChecker(target_psi, atol=atol) evolution = models.StateEvolution(hamiltonians.Z(2), dt=dt, solver=solver, callbacks=[checker]) final_psi = evolution(final_time=1, initial_state=target_psi[0])
def test_state_evolution(solver, atol): """Check state evolution under H = Z1 + Z2.""" # Analytical solution t = np.linspace(0, 1, 1001) phase = np.exp(2j * t)[:, np.newaxis] ones = np.ones((1001, 2)) target_psi = np.concatenate([phase, ones, phase.conj()], axis=1) dt = t[1] - t[0] checker = TimeStepChecker(target_psi, atol=atol) evolution = models.StateEvolution(hamiltonians.Z(2), dt=dt, solver=solver, callbacks=[checker]) final_psi = evolution(final_time=1, initial_state=target_psi[0])
def test_state_evolution_get_initial_state(): ham = hamiltonians.Z(2) evolution = models.StateEvolution(ham, dt=1) # execute without initial state with pytest.raises(ValueError): final_state = evolution(final_time=1)