def eit_simulation(graph, noise_model=None, show_graph=False, gamma=1, delta: float = 0): if show_graph: nx.draw(graph) plt.show() # Generate the driving and Rydberg Hamiltonians if noise_model == 'continuous': laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2), IS_subspace=True, graph=graph, code=rydberg) laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, code=rydberg) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=rydberg) if delta != 0: detuning = hamiltonian.HamiltonianEnergyShift(code=rydberg, IS_subspace=True, graph=graph, energies=[delta]) spontaneous_emission = lindblad_operators.SpontaneousEmission(graph=graph, transition=(1, 2), rates=[gamma], IS_subspace=True, code=rydberg) # Initialize adiabatic algorithm if delta != 0: simulation = SimulateAdiabatic(graph, hamiltonian=[laser1, laser2, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', code=rydberg, noise=[spontaneous_emission]) else: simulation = SimulateAdiabatic(graph, hamiltonian=[laser1, laser2], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', code=rydberg, noise=[spontaneous_emission]) return simulation elif noise_model == 'monte_carlo': laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2), IS_subspace=True, graph=graph, code=rydberg) laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, code=rydberg) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=rydberg) spontaneous_emission = lindblad_operators.SpontaneousEmission(graph=graph, transition=(1, 2), rates=[gamma], IS_subspace=True, code=rydberg) # Initialize adiabatic algorithm if delta != 0: detuning = hamiltonian.HamiltonianEnergyShift(code=rydberg, IS_subspace=True, graph=graph, energies=[delta]) simulation = SimulateAdiabatic(graph, hamiltonian=[laser1, laser2, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='monte_carlo', code=rydberg, noise=[spontaneous_emission]) else: simulation = SimulateAdiabatic(graph, hamiltonian=[laser1, laser2], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='monte_carlo', code=rydberg, noise=[spontaneous_emission]) return simulation
def plot_schedule(): laser = EffectiveOperatorHamiltonian(graph=line_graph(1), IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=line_graph(1), energies=(2.5, ), index=0) def schedule_exp_fixed_true_bright(t, tf): k = 50 a = .95 b = 3.1 x = t / tf max_omega_g = 1 / np.sqrt(2) max_omega_r = 1 / np.sqrt(2) amplitude = max_omega_g * max_omega_r * ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (tf - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (tf - a)))) ** b) + 1) # Now we need to figure out what the driver strengths should be for STIRAP ratio = max_omega_g / max_omega_r omega_g = np.sqrt(amplitude * ratio) omega_r = np.sqrt(amplitude / ratio) laser.omega_g = omega_g laser.omega_r = omega_r offset = -3 * 2 * (1 / 2 - t / tf) energy_shift.energies = (offset, ) schedule = schedule_exp_fixed_true_bright num = 1000 omega_gs = np.zeros(num) omega_rs = np.zeros(num) energy_shifts = np.zeros(num) i = 0 times = np.linspace(0, 1, num) for t in times: schedule(t, 1) omega_gs[i] = laser.energies[0] * laser.omega_g omega_rs[i] = laser.energies[0] * laser.omega_r energy_shifts[i] = energy_shift.energies[0] i += 1 plt.plot(times, omega_gs, label=r'$\Omega_g$') plt.plot(times, omega_rs, label=r'$\Omega_r$') plt.plot(times, energy_shifts, label=r'$\delta_r$') plt.legend() plt.show()
def imperfect_blockade_performance(): graph = line_graph(n=5, return_mis=False) phi = .02 laser = hamiltonian.HamiltonianDriver(pauli='X', energies=(np.cos(phi) * np.sin(phi),), graph=graph) energy_shift_r = hamiltonian.HamiltonianEnergyShift(index=0, energies=(np.sin(phi) ** 2,), graph=graph) energy_shift_g = hamiltonian.HamiltonianEnergyShift(index=1, energies=(np.cos(phi) ** 2,), graph=graph) dissipation = EffectiveOperatorDissipation(omega_g=np.cos(phi), omega_r=np.sin(phi), rates=(1,), graph=graph, IS_subspace=False) rydberg_hamiltonian = hamiltonian.HamiltonianMIS(graph, IS_subspace=False, code=qubit, energies=(0, 4,)) rydberg_hamiltonian_cost_IS = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=qubit) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=False, code=qubit, energies=(1, -4,)) eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift_g, energy_shift_r, rydberg_hamiltonian], jump_operators=[dissipation]) state = np.zeros(rydberg_hamiltonian_cost.hamiltonian.shape) state[graph.independent_sets[np.argmax(rydberg_hamiltonian_cost_IS.hamiltonian)][0], graph.independent_sets[np.argmax(rydberg_hamiltonian_cost_IS.hamiltonian)][0]] = 1 state = State(state, is_ket=False, graph=graph, IS_subspace=False) ss = eq.steady_state(state, k=80, use_initial_guess=True) print(ss[1].shape) ss = ss[1][0] print(np.diagonal(ss), rydberg_hamiltonian_cost.hamiltonian) state = State(ss, is_ket=False, graph=graph, IS_subspace=False) print(np.around(ss, decimals=3), rydberg_hamiltonian_cost.optimum_overlap(state)) layout = np.zeros((2, 2)) layout[0, 0] = 1 layout[1, 1] = 1 layout[0, 1] = 1 adjacent_energy = 4 diag_energy = adjacent_energy/8 second_nearest_energy = adjacent_energy/64 for i in range(layout.shape[0] - 1): for j in range(layout.shape[1] - 1): if layout[i, j] == 1: # There is a spin here pass
def k_beta(delta_r_bar, graph: Graph, verbose=False, mode='hybrid'): def schedule_hybrid(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (delta_r_bar * np.sin(phi) ** 2,) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = ((delta_r_bar+1) * np.sin(phi) ** 2-np.cos(phi) ** 2,) laser.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) laser.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) if mode == 'hybrid': schedule = schedule_hybrid elif mode=='adiabatic': schedule = schedule_adiabatic laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1,), omega_g=1, omega_r=1) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1,)) eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) dt = 0.001 overlap = 0 for time in [0, 1-2*dt]: def normalize_phase(eig): where_nonzero = np.argwhere(np.absolute(eig) > 1e-9)[0] eig = np.e**(-1j*np.angle(eig[where_nonzero[0], where_nonzero[1]])) * eig # We can take the eigenvalues to be real for this Hamiltonian eig = eig.real return eig / np.linalg.norm(eig) schedule(time, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy, ground_state = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() ground_state = normalize_phase(ground_state) ham = scipy.sparse.csr_matrix((-ground_energy * np.ones(graph.num_independent_sets), (range(graph.num_independent_sets), range(graph.num_independent_sets))), shape=(graph.num_independent_sets, graph.num_independent_sets)) for h in eq.hamiltonians: ham = ham + h.hamiltonian schedule(time+dt, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy_dt, ground_state_dt = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() ground_state_dt = normalize_phase(ground_state_dt) d_ground_state_dt = (ground_state_dt - ground_state) / dt # Construct a projector out of the ground subspace proj = np.identity(graph.num_independent_sets) proj = proj - tools.outer_product(ground_state, ground_state) if graph.degeneracy>1 and time == 0: # Project out of the ground subspace energies, states = SchrodingerEquation(hamiltonians=eq.hamiltonians).eig(k=graph.degeneracy) for i in range(graph.degeneracy-1): proj = proj - tools.outer_product(states[i+1, np.newaxis].T, states[i+1, np.newaxis].T) d_ground_state_dt = proj @ d_ground_state_dt # Multiply by 1/(H-E_0) # If at the end, remove the rows corresponding to degeneracies if time != 0: d_ground_state_dt = d_ground_state_dt[graph.degeneracy:] ham = ham[graph.degeneracy:, graph.degeneracy:] else: d_ground_state_dt = d_ground_state_dt[:-1] ham = ham[:-1, :-1] res = scipy.sparse.linalg.spsolve(ham, d_ground_state_dt).real overlap += np.linalg.norm(res)**2 return overlap
def leakage_vs_final_eigenenergy(times, graph=line_graph(n=2), mode='hybrid', angle=np.pi / 4, which='S'): """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus the final eigenenergy""" if which == 'S': index = 0 elif which == 'L': index = -1 else: index = which optimal_energy = graph.independent_sets[index][1] degeneracy = 0 bad = [] for IS in graph.independent_sets: if graph.independent_sets[IS][1] == optimal_energy: degeneracy += 1 else: bad.append(IS) if degeneracy == 1: bad = 'other' full_rates = np.zeros(graph.num_independent_sets - degeneracy) # Good is a list of good eigenvalues # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good' def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_reit(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.cos(angle) * np.sin(phi) * np.cos(phi) laser.omega_r = np.sin(angle) * np.sin(phi) * np.cos(phi) dissipation.omega_g = np.cos(angle) * np.cos(phi) * np.sin(phi) dissipation.omega_r = np.sin(angle) * np.cos(phi) * np.sin(phi) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) if mode == 'hybrid': schedule = schedule_hybrid elif mode == 'adiabatic': schedule = schedule_adiabatic elif mode == 'reit': schedule = schedule_reit if mode != 'reit': eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) else: eq = LindbladMasterEquation(hamiltonians=[laser], jump_operators=[dissipation]) def compute_rate(): if bad == 'other' and which == 'S': ground_energy, ground_state = eq.ground_state() overlap = 0 for op in dissipation.jump_operators: overlap = overlap - (np.abs(ground_state.conj().T @ op @ ground_state) ** 2)[0, 0] + \ (ground_state.conj().T @ op.conj().T @ op @ ground_state)[0, 0] return overlap.real else: # Construct the first order transition matrix energies, states = eq.eig(k='all') states = states.T rates = np.zeros(energies.shape[0]**2) for op in dissipation.jump_operators: rates = rates + (np.abs(states.conj().T @ op @ states)** 2).flatten() # Select the relevant rates from 'good' to 'bad' rates = np.reshape( rates.real, (int(np.sqrt(rates.shape[0])), int(np.sqrt(rates.shape[0])))) rate = 0 for i in bad: rate += rates[i, index] return rate return compute_first_alpha_order(eq, schedule, degeneracy, full_output=True)
def rate_vs_eigenenergy(times, graph=line_graph(n=2), mode='hybrid', which='S'): """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus the final eigenenergy""" if which == 'S': index = 0 elif which == 'L': index = -1 else: index = which # Good is a list of good eigenvalues # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good' def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_reit(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) laser.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) dissipation.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) dissipation.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) if mode == 'hybrid': schedule = schedule_hybrid elif mode == 'adiabatic': schedule = schedule_adiabatic elif mode == 'reit': schedule = schedule_reit if mode != 'reit': eq = SchrodingerEquation(hamiltonians=[laser, energy_shift]) else: eq = SchrodingerEquation(hamiltonians=[laser]) def compute_rate(): # Construct the first order transition matrix global full_rates energies, states = eq.eig(k='all') states = states.T rates = np.zeros(energies.shape[0]**2) for op in dissipation.jump_operators: rates = rates + (np.abs(states.conj().T @ op @ states)** 2).flatten() # Select the relevant rates from 'good' to 'bad' rates = np.reshape( rates.real, (graph.num_independent_sets, graph.num_independent_sets)) return rates[:, index].flatten() for i in range(len(times)): print(times[i]) schedule(times[i], 1) full_rates = compute_rate() eigval, eigvec = eq.eig(k='all') return full_rates, eigval
def optimize_schedule(times, bad, graph=line_graph(n=2), initial_guesses=10): # Good is a list of good eigenvalues # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good' def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) schedule = schedule_hybrid eq = SchrodingerEquation(hamiltonians=[laser, energy_shift]) def optimize_delta_r(delta_r): delta_r = delta_r[0] energy_shift.energies = (delta_r, ) if bad == 'other': ground_energy, ground_state = eq.ground_state() overlap = 0 for op in dissipation.jump_operators: overlap = overlap + (np.abs(ground_state.conj().T @ op @ ground_state) ** 2)[0, 0] - \ (ground_state.conj().T @ op.conj().T @ op @ ground_state)[0, 0] return overlap.real else: # Construct the first order transition matrix energies, states = eq.eig(k='all') states = states.T rates = np.zeros(energies.shape[0]**2) for op in dissipation.jump_operators: rates = rates + (np.abs(states.conj().T @ op @ states)** 2).flatten() # Select the relevant rates from 'good' to 'bad' rates = np.reshape( rates.real, (int(np.sqrt(rates.shape[0])), int(np.sqrt(rates.shape[0])))) rate = 0 for i in bad: rate += rates[i, 0] # print(time, rates, rate, delta_r) return rate delta_rs = [] rates = [] for time in times: print(time) schedule(time, 1) min_rate = np.inf min_delta_r = np.inf for i in range(initial_guesses): bounds = [-3, 3] rand = np.random.uniform(bounds[0], bounds[1], 1) delta_r = scipy.optimize.minimize(lambda dr: optimize_delta_r(dr), rand, bounds=[bounds]) print(time, delta_r.x[0], delta_r.fun) if delta_r.fun < min_rate: min_delta_r = delta_r.x[0] min_rate = delta_r.fun delta_rs.append(min_delta_r) rates.append(min_rate) return delta_rs, rates
def dissipation_over_time(times, delta_rs, graph=line_graph(n=2), mode='hybrid', which='S'): rates = np.zeros((len(delta_rs), len(times))) if which == 'S': index = 0 if which == 'L': index = graph.num_independent_sets - 1 optimal_energy = graph.independent_sets[index][1] degeneracy = 0 bad = [] for IS in graph.independent_sets: if graph.independent_sets[IS][1] == optimal_energy: degeneracy += 1 else: bad.append(IS) if degeneracy == 1: bad = 'other' # Good is a list of good eigenvalues # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good' def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) laser.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) dissipation.omega_g = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) dissipation.omega_r = np.sqrt(np.abs(np.sin(phi) * np.cos(phi))) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) if mode == 'hybrid': schedule = schedule_hybrid elif mode == 'adiabatic': schedule = schedule_adiabatic eq = SchrodingerEquation(hamiltonians=[laser, energy_shift]) def compute_rate(delta_r): energy_shift.energies = (delta_r, ) if bad == 'other' and which == 'S': ground_energy, ground_state = eq.ground_state() overlap = 0 for op in dissipation.jump_operators: overlap = overlap - (np.abs(ground_state.conj().T @ op @ ground_state) ** 2)[0, 0] + \ (ground_state.conj().T @ op.conj().T @ op @ ground_state)[0, 0] return overlap.real else: # Construct the first order transition matrix energies, states = eq.eig(k='all') states = states.T rates = np.zeros(energies.shape[0]**2) for op in dissipation.jump_operators: rates = rates + (np.abs(states.conj().T @ op @ states)** 2).flatten() # Select the relevant rates from 'good' to 'bad' rates = np.reshape( rates.real, (int(np.sqrt(rates.shape[0])), int(np.sqrt(rates.shape[0])))) rate = 0 for i in bad: rate += rates[i, index] return rate for i in range(len(times)): print(times[i]) schedule(times[i], 1) for j in range(len(delta_rs)): rates[j, i] = compute_rate(delta_rs[j]) return rates
def low_energy_leakage(graph, t): max_omega_r = 1 max_omega_g = 1 amplitude = np.sqrt(max_omega_r**2 + max_omega_g**2) max_omega_r /= amplitude max_omega_g /= amplitude k = 50 a = .95 b = 3.1 def schedule_exp_fixed_true_bright(t, tf): x = t / tf amplitude = max_omega_g * max_omega_r * ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (tf - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (tf - a)))) ** b) + 1) # Now we need to figure out what the driver strengths should be for STIRAP ratio = max_omega_g / max_omega_r omega_g = np.sqrt(amplitude * ratio) omega_r = np.sqrt(amplitude / ratio) laser.omega_g = omega_g laser.omega_r = omega_r offset = 3 * 2 * (1 / 2 - t / tf) energy_shift.energies = (offset, ) dissipation.omega_g = -omega_g dissipation.omega_r = omega_r def schedule_exp_fixed_true_dark(t, tf): x = t / tf amplitude = max_omega_g * max_omega_r * ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (tf - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (tf - a)))) ** b) + 1) # Now, choose the opposite of the STIRAP sequence ratio = max_omega_g / max_omega_r omega_g = np.sqrt(amplitude * ratio) omega_r = np.sqrt(amplitude / ratio) offset = 2 * ( 1 / 2 - t / tf ) #max_omega_g * max_omega_r * np.cos(x * np.pi) - (omega_r ** 2 - omega_g ** 2) energy_shift.energies = (offset, ) laser.omega_g = omega_g laser.omega_r = omega_r dissipation.omega_g = omega_g dissipation.omega_r = omega_r def schedule_exp_fixed(t, tf=1): x = t / tf * np.pi / 2 amplitude = np.abs(np.cos(x) * np.sin(x)) # Now we need to figure out what the driver strengths should be for STIRAP omega_g = np.sin(x) omega_r = np.cos(x) offset = omega_r**2 - omega_g**2 # Now, choose the opposite of the STIRAP sequence energy_shift.energies = (offset, ) laser.omega_g = np.sqrt(amplitude) laser.omega_r = np.sqrt(amplitude) dissipation.omega_g = np.sqrt(amplitude) dissipation.omega_r = np.sqrt(amplitude) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=1, omega_r=1) #laser = dill.load(open('laser.pickle', 'rb')) #dill.dump(laser, open('laser.pickle', 'wb')) #laser = dill.load(open('laser.pickle', 'rb')) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) #dill.dump(dissipation, open('dissipation.pickle', 'wb')) #dissipation = dill.load(open('dissipation.pickle', 'rb')) def k_alpha_rate(): # Construct the first order transition matrix eigvals, eigvecs = eigsh(laser.hamiltonian + energy_shift.hamiltonian, k=100, which='SA') return eigvals schedule_exp_fixed_true_dark(t, 1) energy = k_alpha_rate() #print(repr(list(energy))) #print() return energy
def expansion(graph=line_graph(n=3), mode='reit', full_output=False, alpha_order=1, beta_order=1): # Find the performance vs alpha ground_energy = graph.independent_sets[0][1] degeneracy = 0 for IS in graph.independent_sets: if graph.independent_sets[IS][1] == ground_energy: degeneracy += 1 num = 100 if mode == 'reit': laser = EffectiveOperatorHamiltonian(graph=graph, omega_r=1, omega_g=1, energies=(1, )) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=qubit) def schedule_EIT(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) schedule = schedule_EIT eq = LindbladMasterEquation(hamiltonians=[laser], jump_operators=[dissipation]) if mode == 'adiabatic': def schedule_adiabatic(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (4 * np.sin(phi)**2 - np.cos(phi)**2, ) laser.energies = (np.cos(phi) * np.sin(phi), ) dissipation.rates = (np.cos(phi) * np.sin(phi), ) # Now run the standard adiabatic algorithm """laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1,), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4))""" laser = hamiltonian.HamiltonianDriver(graph=graph, IS_subspace=True, energies=(1, )) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(1, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) schedule = schedule_adiabatic eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) if mode == 'hybrid': def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(phi)**2, ) # (- 1.35 * (t / tf - 1 / 2),) laser.omega_r = np.sin(phi) laser.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) schedule = schedule_hybrid eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) # Compute orders in alpha # rho[o,:] = compute_alpha_order(rho[o-1,:], eq, schedule) # print(rho[o,-1,0,0]) if alpha_order == 1: rates = compute_first_alpha_order(eq, schedule, degeneracy, full_output=full_output) return rates rates = rates[:, 0] print(np.sum(rates[1:])) if degeneracy > 1: return -np.sum(rates) else: return rates if beta_order == 1: print('rate', compute_first_beta_order(eq, schedule).real)
def expansion(mode='reit'): # Find the performance vs alpha graph = line_graph(n=2) num = 100 times = np.linspace(0, 1, 100) if mode == 'reit': laser = EffectiveOperatorHamiltonian(graph=graph, omega_r=1, omega_g=1, energies=(1, )) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=qubit) def schedule_EIT(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) """def compute_eigenenergies(t, y): schedule_EIT(t, 1) # Compute the Hamiltonian basis vectors eq = SchrodingerEquation(hamiltonians=[laser]) eigval, eigvec = eq.eig() return eigval """ #theta = \ # scipy.integrate.solve_ivp(compute_eigenenergies, (0, 1), np.zeros(eigval.shape), atol=1e-8, rtol=1e-6, # method='DOP853', t_eval=times)['y'].T schedule = schedule_EIT eq = LindbladMasterEquation(hamiltonians=[laser], jump_operators=[dissipation]) if mode == 'adiabatic': def schedule_adiabatic(t, tf): energy_shift.energies = (-5 * (t / tf - 1 / 2), ) laser.energies = (np.sin(t / tf * np.pi)**2, ) dissipation.rates = (np.sin(t / tf * np.pi)**2, ) # Now run the standard adiabatic algorithm laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) schedule = schedule_adiabatic eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) #rho = np.zeros((5, num, graph.num_independent_sets, graph.num_independent_sets), dtype=np.complex128) # Allow the integrator to allocate space. First get the zeroth order solution #psi0 = np.zeros((graph.num_independent_sets, graph.num_independent_sets)) #psi0[0, 0] = 1 # Convert results to density matrices #for i in range(num): # rho[0, i, :] = psi0 # Compute orders in alpha #rho[o,:] = compute_alpha_order(rho[o-1,:], eq, schedule) #print(rho[o,-1,0,0]) #print(compute_first_alpha_order(eq, schedule)) print(compute_first_beta_order(eq, schedule))
def leakage(graph, t): max_omega_r = 1 max_omega_g = 1 amplitude = np.sqrt(max_omega_r**2 + max_omega_g**2) max_omega_r /= amplitude max_omega_g /= amplitude k = 50 a = .95 b = 3.1 def schedule_exp_fixed_true_bright(t, tf): x = t / tf amplitude = max_omega_g * max_omega_r * ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (tf - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (tf - a)))) ** b) + 1) # Now we need to figure out what the driver strengths should be for STIRAP ratio = max_omega_g / max_omega_r omega_g = np.sqrt(amplitude * ratio) omega_r = np.sqrt(amplitude / ratio) laser.omega_g = omega_g laser.omega_r = omega_r offset = 3 * 2 * (1 / 2 - t / tf) energy_shift.energies = (offset, ) dissipation.omega_g = -omega_g dissipation.omega_r = omega_r def schedule_exp_fixed_true_dark(t, tf): x = t / tf amplitude = max_omega_g * max_omega_r * ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (tf - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (tf - a)))) ** b) + 1) # Now, choose the opposite of the STIRAP sequence ratio = max_omega_g / max_omega_r omega_g = np.sqrt(amplitude * ratio) omega_r = np.sqrt(amplitude / ratio) offset = 3 * 2 * ( 1 / 2 - t / tf ) #max_omega_g * max_omega_r * np.cos(x * np.pi) - (omega_r ** 2 - omega_g ** 2) energy_shift.energies = (offset, ) laser.omega_g = omega_g laser.omega_r = omega_r dissipation.omega_g = omega_g dissipation.omega_r = omega_r def schedule_exp_fixed(t, tf=1): x = t / tf * np.pi / 2 amplitude = np.abs(np.cos(x) * np.sin(x)) # Now we need to figure out what the driver strengths should be for STIRAP omega_g = np.sin(x) omega_r = np.cos(x) offset = omega_r**2 - omega_g**2 # Now, choose the opposite of the STIRAP sequence energy_shift.energies = (offset, ) laser.omega_g = np.sqrt(amplitude) laser.omega_r = np.sqrt(amplitude) dissipation.omega_g = np.sqrt(amplitude) dissipation.omega_r = np.sqrt(amplitude) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=1, omega_r=1) #laser = dill.load(open('laser.pickle', 'rb')) #dill.dump(laser, open('laser.pickle', 'wb')) #laser = dill.load(open('laser.pickle', 'rb')) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) #dill.dump(dissipation, open('dissipation.pickle', 'wb')) #dissipation = dill.load(open('dissipation.pickle', 'rb')) def k_alpha_rate(): # Construct the first order transition matrix eigvals, eigvecs = np.linalg.eigh( (laser.hamiltonian + energy_shift.hamiltonian).todense()) eigvecs = np.array(eigvecs) eigvals = np.array(eigvals) rates = np.zeros(graph.num_independent_sets) shape = eigvals.shape[0] for op in dissipation.jump_operators: jump_rates = np.zeros((shape, shape)) jump_rates = jump_rates + (np.abs(eigvecs.T @ op @ eigvecs)**2) rates = rates + jump_rates[:, 0].flatten().real return eigvals, rates schedule_exp_fixed_true_dark(t, 1) energy, rate = k_alpha_rate() print(repr(list(energy))) print() print(repr(rate.tolist())) return energy, rate
def k_alpha(delta_r_bar, graph: Graph, mode='hybrid', verbose=False, integrator = 'quad'): if not isinstance(delta_r_bar, float): delta_r_bar = delta_r_bar[0] def schedule_hybrid(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (delta_r_bar * np.sin(phi) ** 2,) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = ((delta_r_bar+1) * np.sin(phi) ** 2-np.cos(phi) ** 2,) laser.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) laser.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) if mode == 'hybrid': schedule = schedule_hybrid elif mode=='adiabatic': schedule = schedule_adiabatic laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1,), omega_g=1, omega_r=1) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1,)) eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) def k_alpha_rate(t, delta_r_bar=0): if verbose: print(t) schedule(t, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy, ground_state = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() overlap = 0 for op in eq.jump_operators[0].jump_operators: overlap = overlap - (np.abs(ground_state.conj().T @ op @ ground_state) ** 2)[0, 0] + \ (ground_state.conj().T @ op.conj().T @ op @ ground_state)[0, 0] if graph.degeneracy > 1: # Solve for the k lowest eigenvalues, where k=degeneracy energies, states = SchrodingerEquation(hamiltonians=eq.hamiltonians).eig(k=graph.degeneracy+1) states = states.T rates_into_degenerate = np.zeros(energies.shape[0] ** 2) for op in eq.jump_operators[0].jump_operators: rates_into_degenerate = rates_into_degenerate + (np.abs(states.conj().T @ op @ states) ** 2).flatten() rates_into_degenerate = np.reshape(rates_into_degenerate, (energies.shape[0], energies.shape[0])) rates_into_degenerate = rates_into_degenerate[:, 0].flatten().real rates_into_degenerate = rates_into_degenerate[1:graph.degeneracy] rates_into_degenerate = np.sum(rates_into_degenerate) overlap = overlap.real - rates_into_degenerate return overlap.real if integrator == 'quad': k_a, err_k_a = scipy.integrate.quad(lambda t: k_alpha_rate(t, delta_r_bar=delta_r_bar), 0, .95, limit=200) else: times = np.linspace(.001, .99, 100) rates = np.zeros(100) i = 0 for t in times: rates[i] = k_alpha_rate(t, delta_r_bar) i += 1 return np.sum(rates)*(times[-1]-times[0])/len(times) if verbose: print(delta_r_bar, k_a) return k_a
graph = ring_graph(14) #graph = line_graph(8) deg.append(graph.degeneracy) #res = scipy.optimize.minimize(lambda dr: k_alpha(dr, graph=graph, verbose=True), [1.], bounds=[(0, 3)]) #print(res) def schedule_hybrid(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (delta_r_bar * np.sin(phi) ** 2,) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) from qsim.graph_algorithms.adiabatic import SimulateAdiabatic laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1,), omega_g=1, omega_r=1) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1,)) eq = SimulateAdiabatic(graph=graph, hamiltonian=[laser, energy_shift], noise_model='continuous', noise=[dissipation], cost_hamiltonian=energy_shift) #eq.spectrum_vs_time(1, schedule_hybrid, num=500, plot=True) times = np.linspace(.01, .95, 500) eigvecs, indices = eq.groundstate_ordering_vs_time(times, schedule_hybrid, verbose=True) #rates_better_reit = np.zeros(len(times)) rates_self_reit = np.zeros(len(times)) rates_out_reit = np.zeros(len(times)) for i in range(len(times)): schedule_hybrid(times[i], 1) overlap = 0 overlap_self = 0 for op in dissipation.jump_operators:
def alpha_correction_ar(graph=line_graph(n=2), mode='hybrid', angle=np.pi / 4, which='S', verbose=False): """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus the final eigenenergy""" if which == 'S': index = 0 elif which == 'L': index = graph.num_independent_sets - 1 else: index = which energies = [] bad_indices = [] target_energy = graph.independent_sets[index][1] degeneracy = 0 # Compute maximum independent set size and "bad" energies for IS in graph.independent_sets: if graph.independent_sets[IS][1] != target_energy: energies.append(graph.independent_sets[IS][1]) bad_indices.append(IS) else: degeneracy += 1 energies = np.array(energies) energies = np.abs(target_energy - energies) # Good is a list of good eigenvalues # Bad is a list of bad eigenvalues. If 'other', defaults to all remaining eigenvalues outside of 'good' def schedule_hybrid(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_reit(t, tf): phi = (tf - t) / tf * np.pi / 2 laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (np.sin(2 * ((tf - t) / tf - 1 / 2) * np.pi), ) laser.omega_g = np.cos(angle) * np.sin(phi) * np.cos(phi) laser.omega_r = np.sin(angle) * np.sin(phi) * np.cos(phi) dissipation.omega_g = np.cos(angle) * np.cos(phi) * np.sin(phi) dissipation.omega_r = np.sin(angle) * np.cos(phi) * np.sin(phi) laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1, ), omega_g=np.cos(np.pi / 4), omega_r=np.sin(np.pi / 4)) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, energies=(2.5, ), index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1, )) if mode == 'hybrid': schedule = schedule_hybrid elif mode == 'adiabatic': schedule = schedule_adiabatic elif mode == 'reit': schedule = schedule_reit if mode != 'reit': eq = SchrodingerEquation(hamiltonians=[laser, energy_shift]) else: eq = SchrodingerEquation(hamiltonians=[laser]) def compute_rate(t): if verbose: print(t) schedule(t, 1) # Construct the first order transition matrix eigval, eigvec = eq.eig(k='all') eigvec = eigvec.T rates = np.zeros(eigval.shape[0]**2) for op in dissipation.jump_operators: rates = rates + ((eigvec.conj().T @ op @ eigvec)**2).flatten() # Select the relevant rates from 'good' to 'bad' rates = np.reshape( rates.real, (graph.num_independent_sets, graph.num_independent_sets)) bad_rates = np.zeros(len(bad_indices)) for i in range(len(bad_indices)): bad_rates[i] = bad_rates[i] + rates[bad_indices[i], index] return np.dot(bad_rates, energies) # Integrate to find the correction res, error = scipy.integrate.quad_vec(compute_rate, 1e-5, .9999) return res / target_energy, error
def adiabatic_simulation(graph, show_graph=False, approximate=False): if show_graph: nx.draw(graph) plt.show() if approximate: laser = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, energies=(Omega_g * Omega_r / delta, )) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) spontaneous_emission1 = lindblad_operators.SpontaneousEmission( graph=graph, transition=(1, 1), rates=[(Omega_g / delta)**2 * Gamma], IS_subspace=True) spontaneous_emission2 = lindblad_operators.SpontaneousEmission( graph=graph, transition=(0, 1), rates=[(Omega_r / delta)**2 * Gamma], IS_subspace=True) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) simulation = SimulateAdiabatic( graph, hamiltonian=[laser, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', noise=[spontaneous_emission1, spontaneous_emission2]) return simulation else: # Generate the driving and Rydberg Hamiltonians laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2), IS_subspace=True, graph=graph, code=rydberg) laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, code=rydberg) laser_detuning = hamiltonian.HamiltonianEnergyShift(index=1, IS_subspace=True, energies=[delta], graph=graph, code=rydberg) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=rydberg) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=rydberg) spontaneous_emission = lindblad_operators.SpontaneousEmission( graph=graph, transition=(1, 2), IS_subspace=True, code=rydberg, rates=[Gamma]) # Initialize adiabatic algorithm simulation = SimulateAdiabatic( graph, hamiltonian=[laser1, laser2, laser_detuning, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', code=rydberg, noise=[spontaneous_emission]) return simulation
def eit_simulation(graph, noise_model=None, show_graph=False, gamma=3.8, delta=0, approximate=False, Omega_g=1, Omega_r=1): if show_graph: nx.draw(graph) plt.show() # Generate the driving and Rydberg Hamiltonians if noise_model == 'continuous': if not approximate: laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2), IS_subspace=True, graph=graph, code=rydberg, energies=[Omega_g]) laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, code=rydberg, energies=[Omega_r]) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS( graph, IS_subspace=True, code=rydberg) detuning = hamiltonian.HamiltonianEnergyShift(code=rydberg, IS_subspace=True, graph=graph, energies=[delta]) spontaneous_emission = lindblad_operators.SpontaneousEmission( graph=graph, transition=(1, 2), rates=[gamma], IS_subspace=True, code=rydberg) # Initialize adiabatic algorithm simulation = SimulateAdiabatic( graph, hamiltonian=[laser1, laser2, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', code=rydberg, noise=[spontaneous_emission]) return simulation else: laser = hamiltonian.HamiltonianDriver( transition=(0, 1), IS_subspace=True, graph=graph, energies=[Omega_g * Omega_r / delta]) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) spontaneous_emission1 = lindblad_operators.SpontaneousEmission( graph=graph, transition=(1, 1), rates=[(Omega_g / delta)**2 * gamma], IS_subspace=True) spontaneous_emission2 = lindblad_operators.SpontaneousEmission( graph=graph, transition=(0, 1), rates=[(Omega_r / delta)**2 * gamma], IS_subspace=True) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS( graph, IS_subspace=True) simulation = SimulateAdiabatic( graph, hamiltonian=[laser, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', noise=[spontaneous_emission1, spontaneous_emission2]) return simulation elif noise_model == 'monte_carlo': laser1 = hamiltonian.HamiltonianDriver(transition=(1, 2), IS_subspace=True, graph=graph, code=rydberg) laser2 = hamiltonian.HamiltonianDriver(transition=(0, 1), IS_subspace=True, graph=graph, code=rydberg) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True, code=rydberg) detuning = hamiltonian.HamiltonianEnergyShift(code=rydberg, IS_subspace=True, graph=graph, energies=[delta]) spontaneous_emission = lindblad_operators.SpontaneousEmission( graph=graph, transition=(1, 2), rates=[gamma], IS_subspace=True, code=rydberg) # Initialize adiabatic algorithm simulation = SimulateAdiabatic( graph, hamiltonian=[laser1, laser2, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='monte_carlo', code=rydberg, noise=[spontaneous_emission]) return simulation
def fidelity_vs_alpha(): graph = line_graph(5) omega = 100 T = 100 delta_e = 1000 beta = delta_e / (omega**2 * T) print('beta = ' + str(beta)) gammas = 10**np.linspace(1.75, 3.25, 3) print(gammas * omega**2 * T / delta_e**2) dissipation = EffectiveOperatorDissipation(0, 0, graph=graph, IS_subspace=True, rates=(1 / delta_e**2, )) laser = EffectiveOperatorHamiltonian(0, 0, energies=(1 / delta_e, ), graph=graph, IS_subspace=True) energy_shift = hamiltonian.HamiltonianEnergyShift(graph=graph, IS_subspace=True) def schedule_exp_fixed(t, tf=T): x = t / tf * np.pi / 2 amplitude = np.abs(np.cos(x) * np.sin(x)) # Now we need to figure out what the driver strengths should be for STIRAP omega_g = np.sin(x) * omega omega_r = np.cos(x) * omega offset = omega_r**2 - omega_g**2 # Now, choose the opposite of the STIRAP sequence energy_shift.energies = (offset / 1000, ) laser.omega_g = np.sqrt(amplitude) * omega laser.omega_r = np.sqrt(amplitude) * omega dissipation.omega_g = np.sqrt(amplitude) * omega dissipation.omega_r = np.sqrt(amplitude) * omega def schedule_reit(t, tf=T): x = t / tf * np.pi / 2 omega_g = np.sin(x) * omega omega_r = np.cos(x) * omega energy_shift.energies = (0, ) laser.omega_g = omega_g laser.omega_r = omega_r dissipation.omega_g = omega_g dissipation.omega_r = omega_r eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) nonoise_eq = SchrodingerEquation(hamiltonians=[laser, energy_shift]) state = State(np.array([[0, 0], [0, 1]], dtype=np.complex128), IS_subspace=True, graph=graph, is_ket=False) state = State(np.array([[0, 0, 0], [0, 0, 0], [0, 0, 1]], dtype=np.complex128), IS_subspace=True, graph=graph, is_ket=False) state = State(np.array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 1]], dtype=np.complex128), IS_subspace=True, graph=graph, is_ket=False) state = State(np.zeros((13, 13), dtype=np.complex128), IS_subspace=True, graph=graph, is_ket=False) state[-1, -1] = 1 # nonoise_state = State(np.array([[0], [0], [1]], dtype=np.complex128), IS_subspace=True, graph=graph, is_ket=True) # print(np.abs(nonoise_eq.run_ode_solver(nonoise_state, 0, T, num=500, schedule=schedule_exp_fixed, method='odeint')[0][-1])**2) for a in [1]: delta_e = a * 1000 laser.energies = (1 / delta_e, ) fidelities = [] ars = [] for i in range(len(gammas)): dissipation.rates = (gammas[i] / delta_e**2, ) states = eq.run_ode_solver(state, 0, T, num=50, schedule=schedule_reit, make_valid_state=False, method='odeint') times = states[1]['t'] states = states[0] """print(gammas[i], i) for j in range(len(times)): for op in dissipation.jump_operators: print(np.trace(op.conj().T@op@states[j])-np.abs(np.trace(op@states[j]))**2)""" """print(times[25]) schedule_exp_fixed(times[25], tf=T) eigvals, eigvecs = nonoise_eq.eig(k='all') print(eigvals) print(eigvecs.conj()@states[25]@eigvecs.T)""" final_state = states[-1] #print(final_state) #print(final_state[0, 0], np.trace(final_state)) ar = (final_state[0, 0] + 2 / 3 * (final_state[1, 1] + final_state[2, 2] + final_state[3, 3] + final_state[6, 6] + final_state[5, 5] + final_state[8, 8]) + 1 / 2 * (final_state[7, 7] + final_state[4, 4] + final_state[9, 9] + final_state[10, 10] + final_state[11, 11])) print(ar) print(final_state[0, 0]) print(final_state.diagonal()) ars.append(ar) fidelities.append(final_state[0, 0]) fidelities = np.array(fidelities) ars = np.array(ars) plt.loglog() plt.ylabel(r'$1-$ fidelity') plt.xlabel(r'$\frac{\gamma \Omega^2 T}{\delta_e^2}$') plt.plot(gammas * omega**2 * T / delta_e**2, 1 - fidelities, label='fidelity') plt.plot(gammas * omega**2 * T / delta_e**2, 1 - ars, label='ar') res = np.polyfit(np.log(gammas * omega**2 * T / delta_e**2), np.log(1 - fidelities), 1) print(res) #plt.plot(gammas * omega ** 2 * T / delta_e ** 2, # 1 - np.e ** (-gammas * omega ** 2 * T / delta_e ** 2 * 0.033875094811638556), # label='bound') """if a == -1: plt.plot(gammas * omega ** 2 * T / delta_e ** 2, 0.28187096704733217 * gammas * omega ** 2 * T / delta_e ** 2, label='first order correction') else: plt.plot(gammas * omega ** 2 * T / delta_e ** 2, 0.033875094811638556 * gammas * omega ** 2 * T / delta_e ** 2, label='first order correction')""" plt.legend() plt.tight_layout() plt.show()
def find_optimal_schedules(graph: Graph, verbose=False, mode='hybrid'): def schedule_hybrid(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = (delta_r_bar * np.sin(phi) ** 2,) laser.omega_g = np.cos(phi) laser.omega_r = np.sin(phi) dissipation.omega_g = np.cos(phi) dissipation.omega_r = np.sin(phi) def schedule_adiabatic(t, tf, delta_r_bar=0): phi = (tf - t) / tf * np.pi / 2 energy_shift.energies = ((delta_r_bar+1) * np.sin(phi) ** 2-np.cos(phi) ** 2,) laser.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) laser.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_g = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) dissipation.omega_r = np.sqrt(np.abs(np.cos(phi)*np.sin(phi))) if mode == 'hybrid': schedule = schedule_hybrid elif mode=='adiabatic': schedule = schedule_adiabatic laser = EffectiveOperatorHamiltonian(graph=graph, IS_subspace=True, energies=(1,), omega_g=1, omega_r=1) energy_shift = hamiltonian.HamiltonianEnergyShift(IS_subspace=True, graph=graph, index=0) dissipation = EffectiveOperatorDissipation(graph=graph, omega_r=1, omega_g=1, rates=(1,)) eq = LindbladMasterEquation(hamiltonians=[laser, energy_shift], jump_operators=[dissipation]) def k_alpha_rate(t, delta_r_bar=0): schedule(t, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy, ground_state = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() overlap = 0 for op in eq.jump_operators[0].jump_operators: overlap = overlap - (np.abs(ground_state.conj().T @ op @ ground_state) ** 2)[0, 0] + \ (ground_state.conj().T @ op.conj().T @ op @ ground_state)[0, 0] if graph.degeneracy > 1: # Solve for the k lowest eigenvalues, where k=degeneracy energies, states = SchrodingerEquation(hamiltonians=eq.hamiltonians).eig(k=graph.degeneracy) states = states.T rates_into_degenerate = np.zeros(energies.shape[0] ** 2) for op in eq.jump_operators[0].jump_operators: rates_into_degenerate = rates_into_degenerate + (np.abs(states.conj().T @ op @ states) ** 2).flatten() rates_into_degenerate = np.reshape(rates_into_degenerate, (energies.shape[0], energies.shape[0])) rates_into_degenerate = rates_into_degenerate[:, 0].flatten().real rates_into_degenerate = rates_into_degenerate[1:graph.degeneracy] rates_into_degenerate = np.sum(rates_into_degenerate) overlap = overlap.real - rates_into_degenerate return overlap.real def k_alpha(delta_r_bar): k_a, err_k_a = scipy.integrate.quad(lambda t: k_alpha_rate(t, delta_r_bar=delta_r_bar), 0, 1, limit=200) return k_a def k_beta(delta_r_bar): dt = 0.001 overlap = 0 for time in [0, 1-2*dt]: def normalize_phase(eig): where_nonzero = np.argwhere(np.absolute(eig) > 1e-9)[0] eig = np.e**(-1j*np.angle(eig[where_nonzero[0], where_nonzero[1]])) * eig # We can take the eigenvalues to be real for this Hamiltonian eig = eig.real return eig / np.linalg.norm(eig) schedule(time, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy, ground_state = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() ground_state = normalize_phase(ground_state) ham = scipy.sparse.csr_matrix((-ground_energy * np.ones(graph.num_independent_sets), (range(graph.num_independent_sets), range(graph.num_independent_sets))), shape=(graph.num_independent_sets, graph.num_independent_sets)) for h in eq.hamiltonians: ham = ham + h.hamiltonian schedule(time+dt, 1, delta_r_bar=delta_r_bar) # Construct the first order transition matrix ground_energy_dt, ground_state_dt = SchrodingerEquation(hamiltonians=eq.hamiltonians).ground_state() ground_state_dt = normalize_phase(ground_state_dt) d_ground_state_dt = (ground_state_dt - ground_state) / dt # Construct a projector out of the ground subspace proj = np.identity(graph.num_independent_sets) proj = proj - tools.outer_product(ground_state, ground_state) if graph.degeneracy>1 and time == 0: # Project out of the ground subspace energies, states = SchrodingerEquation(hamiltonians=eq.hamiltonians).eig(k=graph.degeneracy) for i in range(graph.degeneracy-1): proj = proj - tools.outer_product(states[i+1, np.newaxis].T, states[i+1, np.newaxis].T) d_ground_state_dt = proj @ d_ground_state_dt # Multiply by 1/(H-E_0) # If at the end, remove the rows corresponding to degeneracies if time != 0: d_ground_state_dt = d_ground_state_dt[graph.degeneracy:] ham = ham[graph.degeneracy:, graph.degeneracy:] else: d_ground_state_dt = d_ground_state_dt[:-1] ham = ham[:-1, :-1] res = scipy.sparse.linalg.spsolve(ham, d_ground_state_dt).real overlap += np.linalg.norm(res)**2 return overlap def first_order_correction(delta_r_bar): delta_r_bar = delta_r_bar[0] beta = k_beta(delta_r_bar) alpha = k_alpha(delta_r_bar) res = beta*alpha if res <= 0: if verbose: print(delta_r_bar, alpha, beta, res) return 0 res = np.sqrt(res) if verbose: print(delta_r_bar, alpha, beta, res) return res