def ARvstime_EIT(tf=10, graph=None, mis=None, show_graph=False, n=3): schedule = lambda t, tf: [[t / tf, (tf - t) / tf, 1], [1]] if graph is None: graph, mis = line_graph(n=n) graph = Graph(graph) if show_graph: nx.draw(graph) plt.show() rabi1 = 3 rabi2 = 3 # Generate the driving laser1 = hamiltonian.HamiltonianDriver(transition=(0, 1), energy=rabi1, code=rydberg, IS_subspace=True, graph=graph) laser2 = hamiltonian.HamiltonianDriver(transition=(1, 2), energy=rabi2, code=rydberg, IS_subspace=True, graph=graph) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, code=rydberg, detuning=1, energy=0, IS_subspace=True) # Initialize spontaneous emission spontaneous_emission_rate = 1 spontaneous_emission = lindblad_operators.SpontaneousEmission( transition=(1, 2), rate=spontaneous_emission_rate, code=rydberg, IS_subspace=True, graph=graph) # Initialize master equation master_equation = LindbladMasterEquation( hamiltonians=[laser2, laser1], jump_operators=[spontaneous_emission]) # Begin with all qubits in the ground codes psi = np.zeros((rydberg_hamiltonian_cost.hamiltonian.shape[0], 1), dtype=np.complex128) psi[-1, -1] = 1 psi = tools.outer_product(psi, psi) # Generate annealing schedule results = master_equation.run_ode_solver( psi, 0, tf, num_from_time(tf), schedule=lambda t: schedule(t, tf)) cost_function = [ rydberg_hamiltonian_cost.cost_function(results[i], is_ket=False) / mis for i in range(results.shape[0]) ] print(cost_function[-1]) plt.scatter(np.linspace(0, tf, num_from_time(tf)), cost_function, c='teal', label='approximation ratio') plt.legend() plt.xlabel(r'Approximation ratio') plt.ylabel(r'Time $t$') plt.show()
def test_hamiltonian_driver(self): N = 6 hl_qubit = hamiltonian.HamiltonianDriver(graph=tools_test.sample_graph()) psi0 = State(np.zeros((2 ** N, 1))) psi0[0, 0] = 1 psi1 = State(tools.outer_product(psi0, psi0)) # Evolve by e^{-i (\pi/2) \sum_i X_i} psi0 = hl_qubit.evolve(psi0, np.pi / 2) # Should get (-1j)^N |111111> self.assertTrue(np.vdot(psi0, psi0) == 1) self.assertTrue(psi0[-1, 0] == (-1j) ** N) # Evolve by e^{-i (\pi/2) \sum_i X_i} psi1 = hl_qubit.evolve(psi1, np.pi / 2) # Should get (-1j)^N |111111> self.assertTrue(tools.is_valid_state(psi1)) self.assertAlmostEqual(psi1[-1, -1], 1) psi0 = State(np.zeros((2 ** N, 1))) psi0[0, 0] = 1 psi0 = hl_qubit.left_multiply(psi0) psi1 = np.zeros((2 ** N, 1), dtype=np.complex128) for i in range(N): psi1[2 ** i, 0] = 1 self.assertTrue(np.allclose(psi0, psi1)) psi2 = State(np.zeros((2 ** N, 1))) psi2[0, 0] = 1 psi2 = hl_qubit.hamiltonian @ psi2 self.assertTrue(np.allclose(psi0, psi2)) N = 3 hl = hamiltonian.HamiltonianDriver(transition=(0, 1), code=rydberg) psi0 = State(np.zeros((rydberg.d ** N, 1)), code=rydberg) psi0[5, 0] = 1 psi1 = State(tools.outer_product(psi0, psi0), code=rydberg) psi0 = hl.left_multiply(psi0) self.assertTrue(psi0[2, 0] == 1) self.assertTrue(psi0[14, 0] == 1) psi1 = hl.left_multiply(psi1) self.assertTrue(psi1[2, 5] == 1) self.assertTrue(psi1[14, 5] == 1) psi0 = State(np.zeros((rydberg.d ** N, 1)), code=rydberg) psi0[5, 0] = 1 psi0 = hl.evolve(psi0, np.pi / 2) self.assertTrue(np.isclose(psi0[11, 0], -1)) # IS subspace hl = hamiltonian.HamiltonianDriver(transition=(0, 2), code=rydberg, IS_subspace=True, graph=line_graph(2)) psi0 = State(np.zeros((8, 1)), code=rydberg) psi0[-1,0] = 1 psi0 = State(tools.outer_product(psi0, psi0), code=rydberg) self.assertTrue(tools.is_hermitian(hl.evolve(psi0, 1)))
def find_critical_time(graph, critical_optimum_overlap): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (3 * 2 * (1 / 2 - x), ) driver.energies = (amplitude, ) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) def compute_final_state(T): final_state = ad.run(T, schedule, method='odeint')[0][-1] cost.energies = (1, ) optimum_overlap = cost.optimum_overlap(final_state) return final_state, optimum_overlap def cost_function(T): final_state, optimum_overlap = compute_final_state(T) print(T, optimum_overlap) return optimum_overlap - critical_optimum_overlap #return basinhopping(cost_function, 35, niter=3, minimizer_kwargs={'bounds':[(20,50)]})['x'] return brentq(cost_function, 20, 50, xtol=1e-5)
def find_fidelity(graph, critical_time): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (3 * 2 * (1 / 2 - x), ) driver.energies = (amplitude, ) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) final_state = ad.run(critical_time, schedule, method='odeint')[0][-1] cost.energies = (1, ) optimum_indices = np.argwhere( cost._diagonal_hamiltonian == cost.optimum).T[0] # Construct an operator that is zero everywhere except at the optimum optimum = np.zeros(cost._diagonal_hamiltonian.shape) optimum[optimum_indices] = 1 optimum_overlap = cost.optimum_overlap(final_state) return final_state, optimum, optimum_overlap
def eit_steady_state(graph, show_graph=False, gamma=1): if show_graph: nx.draw(graph) plt.show() # 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) 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 simulation = SimulateAdiabatic(graph, hamiltonian=[laser1, laser2], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=True, noise_model='continuous', code=rydberg, noise=[spontaneous_emission]) master_equation = LindbladMasterEquation( hamiltonians=[laser1, laser2], jump_operators=[spontaneous_emission]) initial_state = State(tools.outer_product( np.array([[0, 0, 0, 0, 0, 0, 0, 1]]).T, np.array([[0, 0, 0, 0, 0, 0, 0, 1]]).T), code=rydberg, IS_subspace=True, is_ket=False) print(master_equation.steady_state(initial_state)) return simulation
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 adiabatic_simulation(graph, show_graph=False, IS_subspace=False, noisy=False, trotterize=True): if show_graph: nx.draw(graph) plt.show() # Generate the driving and Rydberg Hamiltonians if not noisy: laser = hamiltonian.HamiltonianDriver(IS_subspace=IS_subspace, graph=graph) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=IS_subspace) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS( graph, IS_subspace=IS_subspace) # Initialize adiabatic algorithm simulation = SimulateAdiabatic( graph, hamiltonian=[laser, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=IS_subspace) else: laser = hamiltonian.HamiltonianDriver(IS_subspace=IS_subspace, graph=graph) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=IS_subspace) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS( graph, IS_subspace=IS_subspace) if trotterize: spontaneous_emission = quantum_channels.AmplitudeDampingChannel( graph=graph, IS_subspace=IS_subspace, rates=(.1, )) else: spontaneous_emission = lindblad_operators.SpontaneousEmission( graph=graph, IS_subspace=IS_subspace, rates=(.1, )) # Initialize adiabatic algorithm simulation = SimulateAdiabatic( graph, hamiltonian=[laser, detuning], noise_model='continuous', noise=[spontaneous_emission], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=IS_subspace) return simulation
def mis_qaoa(n, method='minimize', show=True, analytic_gradient=True): penalty = 1 psi0 = tools.equal_superposition(n) psi0 = State(psi0) G = make_ring_graph_multiring(n) if show: nx.draw_networkx(G) plt.show() depths = [2 * i for i in range(1, 2 * n + 1)] mis = [] # Find MIS optimum # Uncomment to visualize graph hc_qubit = hamiltonian.HamiltonianMIS(G, energies=[1, penalty]) cost = hamiltonian.HamiltonianMIS(G, energies=[1, penalty]) # Set the default variational operators hb_qubit = hamiltonian.HamiltonianDriver() # Create Hamiltonian list sim = qaoa.SimulateQAOA(G, cost_hamiltonian=cost, hamiltonian=[], noise_model=None) sim.hamiltonian = [] for p in depths: sim.hamiltonian.append(hc_qubit) sim.hamiltonian.append(hb_qubit) sim.depth = p # You should get the same thing print(p) if method == 'minimize': results = sim.find_parameters_minimize(verbose=True, initial_state=psi0, analytic_gradient=analytic_gradient) approximation_ratio = np.real(results['approximation_ratio']) mis.append(approximation_ratio) if method == 'brute': results = sim.find_parameters_brute(n=15, verbose=True, initial_state=psi0) approximation_ratio = np.real(results['approximation_ratio']) mis.append(approximation_ratio) if method == 'basinhopping': if p >= 10: results = sim.find_parameters_basinhopping(verbose=True, initial_state=psi0, n=250, analytic_gradient=analytic_gradient) print(results) approximation_ratio = np.real(results['approximation_ratio']) mis.append(approximation_ratio) # plt.plot(list(range(n)), maxcut, c='y', label='maxcut') print(mis) plt.plot(depths, [(i + 1) / (i + 2) for i in depths]) plt.scatter(depths, [i / (i + 1) for i in depths], label='maxcut') plt.scatter(depths, mis, label='mis with $n=$' + str(n)) plt.plot(depths, mis) plt.legend() if show: plt.show()
def find_ratio(tails_graph, graph, detuning_plateau, tf): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) print('Starting rydberg') if tails_graph is not None: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver, rydberg], cost_hamiltonian=cost, IS_subspace=True) else: ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) def schedule_cubic(t, T): cubic_ys = 2 * np.pi * np.array([ 11.5, detuning_plateau + .5, detuning_plateau, detuning_plateau - .5, -11.5 ]) cubic_xs = np.array([ .312, (T / 2 - .312) / 1.35 + .312, T / 2, T - .312 - (T / 2 - .312) / 1.35, T - .312 ]) if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 11.5, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (scipy.interpolate.interp1d(cubic_xs, cubic_ys, kind='cubic')(t), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11.5, ) print('Starting evolution') states, data = ad.run(tf, schedule_cubic, num=int(400 * tf), method='trotterize', full_output=False) np.savez_compressed('{}x{}_{}_{}_{}_trotterize_highres.npz'.format( size, size, graph_index, np.round(np.abs(detuning_plateau), 2), np.round(np.abs(tf), 2)), state=states[-1])
def find_ratio(tails_graph, graph, tf): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (11 * 2 * (1 / 2 - x), ) driver.energies = (2 * amplitude, ) # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) # print(driver.hamiltonian) if tails_graph is None: ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) else: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(1, )) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver, rydberg], cost_hamiltonian=cost, IS_subspace=True) print('running') states, data = ad.run(tf, schedule, method='odeint') print(data) times = data['t'] is_overlaps = np.zeros((graph.mis_size + 1, len(states))) cost.energies = (1, ) for j in range(graph.mis_size + 1): projector = (cost._diagonal_hamiltonian == j) for i in range(len(states)): is_overlaps[j, i] = np.sum(np.abs(states[i])**2 * projector) print(is_overlaps) for j in range(graph.mis_size + 1): plt.scatter(times, is_overlaps[j], label=str(j)) plt.legend() plt.show()
def adiabatic_simulation(graph, show_graph=False, IS_subspace=True): if show_graph: nx.draw(graph) plt.show() # Generate the driving and Rydberg Hamiltonians laser = hamiltonian.HamiltonianDriver(IS_subspace=IS_subspace, graph=graph) detuning = hamiltonian.HamiltonianMIS(graph, IS_subspace=IS_subspace) rydberg_hamiltonian_cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=IS_subspace) graph.mis_size = int(np.max(rydberg_hamiltonian_cost.hamiltonian)) print('Degeneracy', len(np.argwhere(rydberg_hamiltonian_cost.hamiltonian == np.max(rydberg_hamiltonian_cost.hamiltonian)).T[0])) # Initialize adiabatic algorithm simulation = SimulateAdiabatic(graph, hamiltonian=[laser, detuning], cost_hamiltonian=rydberg_hamiltonian_cost, IS_subspace=IS_subspace) return simulation
def rate_vs_eigenenergy(times, graph=line_graph(n=2), which='S'): """For REIT, compute the total leakage from the ground state to a given state. Plot the total leakage versus the final eigenenergy""" bad = np.arange(0, 2**graph.n, 1) if which == 'S': index = 0 elif which == 'L': index = -1 else: index = which bad = np.delete(bad, index) full_rates = np.zeros(len(bad)) # 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(t, tf): phi = (tf - t) / tf * np.pi / 2 x.energies = (np.sin(phi)**2, ) x = hamiltonian.HamiltonianDriver(graph=graph, IS_subspace=False, energies=(1, )) zz = hamiltonian.HamiltonianMaxCut(graph, cost_function=False, energies=(1 / 2, )) #dissipation = lindblad_operators.SpontaneousEmission(graph=graph, rates=(1,)) eq = SchrodingerEquation(hamiltonians=[x, zz]) def compute_rate(): # Construct the first order transition matrix energies, states = eq.eig(k='all') rates = np.zeros(len(bad)) for j in range(graph.n): for i in range(len(bad)): rates[i] = rates[i] + (np.abs( states[i].conj() @ qubit.left_multiply( State(states[index].T), [j], qubit.Z))**2)[0, 0] # Select the relevant rates from 'good' to 'bad' print(rates) return rates for i in range(len(times)): print(times[i]) schedule(times[i], 1) full_rates = full_rates + compute_rate() eigval, eigvec = eq.eig(k='all') return full_rates, eigval
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 effective_operator_comparison(graph=None, mis=None, tf=10, show_graph=False, n=3, gamma=500): # Generate annealing schedule def schedule1(t, tf): return [[t / tf, (tf - t) / tf, 1], [1]] if graph is None: graph, mis = line_graph(n=n) graph = Graph(graph) if show_graph: nx.draw(graph) plt.show() # Generate the driving and Rydberg Hamiltonians rabi1 = 1 laser1 = hamiltonian.HamiltonianDriver(transition=(0, 1), energies=[rabi1], code=rydberg, IS_subspace=True, graph=graph) rabi2 = 1 laser2 = hamiltonian.HamiltonianDriver(transition=(1, 2), energies=[rabi2], code=rydberg, IS_subspace=True, graph=graph) rydberg_hamiltonian_cost = hamiltonian.HamiltonianRydberg(graph, code=rydberg, detuning=1, energy=0, IS_subspace=True) # Initialize spontaneous emission spontaneous_emission_rate = gamma spontaneous_emission = lindblad_operators.SpontaneousEmission( transition=(1, 2), rate=spontaneous_emission_rate, code=rydberg, IS_subspace=True, graph=graph) strong_spontaneous_emission_rate = (1, 1) strong_spontaneous_emission = lindblad_operators.StrongSpontaneousEmission( transition=(0, 2), rates=strong_spontaneous_emission_rate, code=rydberg, IS_subspace=True, graph=graph) def schedule2(t, tf): return [[], [(2 * t / tf / np.sqrt(spontaneous_emission_rate), 2 * (tf - t) / tf / np.sqrt(spontaneous_emission_rate))]] # Initialize master equation master_equation = LindbladMasterEquation( hamiltonians=[laser2, laser1], jump_operators=[spontaneous_emission]) # Begin with all qubits in the ground codes psi = np.zeros((rydberg_hamiltonian_cost.hamiltonian.shape[0], 1), dtype=np.complex128) psi[-1, -1] = 1 psi = tools.outer_product(psi, psi) # Integrate the master equation results1 = master_equation.run_ode_solver( psi, 0, tf, num_from_time(tf), schedule=lambda t: schedule1(t, tf)) cost_function = [ rydberg_hamiltonian_cost.cost_function(results1[i], is_ket=False) / mis for i in range(results1.shape[0]) ] # Initialize master equation master_equation = LindbladMasterEquation( hamiltonians=[], jump_operators=[strong_spontaneous_emission]) # Integrate the master equation results2 = master_equation.run_ode_solver( psi, 0, tf, num_from_time(tf), schedule=lambda t: schedule2(t, tf)) cost_function_strong = [ rydberg_hamiltonian_cost.cost_function(results2[i], is_ket=False) / mis for i in range(results2.shape[0]) ] print(results2[-1]) times = np.linspace(0, tf, num_from_time(tf)) # Compute the fidelity of the results fidelities = [ tools.fidelity(results1[i], results2[i]) for i in range(results1.shape[0]) ] plt.plot(times, fidelities, color='r', label='Fidelity') plt.plot(times, cost_function, color='teal', label='Rydberg EIT approximation ratio') plt.plot(times, cost_function_strong, color='y', linestyle=':', label='Effective operator approximation ratio') plt.hlines(1, 0, max(times), linestyles=':', colors='k') plt.legend(loc='lower right') plt.ylim(0, 1.03) plt.xlabel(r'Annealing time $t$') plt.ylabel(r'Approximation ratio') plt.show()
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
#G.add_edge(2, 3, weight=rydberg_noise_rate) G.add_edge(0, 2, weight=rydberg_noise_rate) G.add_edge(1, 2, weight=rydberg_noise_rate) zero = np.zeros([1, 2**N], dtype=np.complex128) zero[-1, -1] = 1 zero = zero.T zero = tools.outer_product(zero, zero) #plot.draw_graph(G) # Goal: numerically integrate master equation with (1) spontaneous emission and (2) IS constraint evolution # with Hb hamiltonian p = 2 spacing = 10 #se_noise_rate = 0.01 #se_noise = jump_operators.SpontaneousEmission(se_noise_rate) rydberg_noise = MISLoweringJumpOperator(G, rydberg_noise_rate) hb_x = hamiltonian.HamiltonianDriver(pauli='X') hb_y = hamiltonian.HamiltonianDriver(pauli='Y') hb_z = hamiltonian.HamiltonianDriver(pauli='Z') hMIS = hamiltonian.HamiltonianMIS(G, blockade_energy=rydberg_noise_rate) C = cost_function(G, rydberg_noise_rate) C = C / np.max(C) is_proj = IS_projector(G) s = zero costs = np.zeros((spacing, spacing)) probabilities = np.zeros((spacing**p, 2**N)) m = 0 for i in np.linspace(0, 2 * np.pi / np.sqrt(3), spacing): n = 0 for l in np.linspace(0, 2 * np.pi / np.sqrt(3), spacing): print(m, n, i, l) s = zero
def visualize_low_energy_subspace(graph, tails_graph, k=5): n_points = 7 times_exp = 2**np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[4] cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) # print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) # print('Starting rydberg') if tails_graph is not None: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) max_detuning = np.max(pulse[:, 2]) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (2 * np.pi * (-(11 + 15) / T * t + 15), ) driver.energies = (2 * np.pi * 2 * amplitude, ) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * max_detuning, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) # print(t, cost.energies) # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) def gap(t): schedule_exp_linear(t, t_max) eigval, eigvec = eq.eig(which='S', k=k) return np.abs(eigval - eigval[0]), eigvec # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) # print(driver.hamiltonian) if tails_graph is None: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver]) else: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver, rydberg]) fig, ax = plt.subplots(1, 1) num = 100 print('beginning computation') for (i, t) in enumerate(np.linspace(.5, .97, num) * t_max): print(i) g, eigvec = gap(t) schedule_exp_linear(t, t_max) detuning = cost.energies[0] / (2 * np.pi) g = g / (2 * np.pi) ax.scatter(-np.ones(len(g)) * detuning, g, s=3, color='navy') ax.set_xlabel(r'Detuning (MHz)') ax.set_ylabel(r'Eigenenergy (MHz))') plt.show()
def track_eigenstate_populations(graph, tails_graph, grid, k=2): n_points = 7 times_exp = 2**np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[6] cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) # print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) # print('Starting rydberg') if tails_graph is not None: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 max_detuning = np.max(pulse[:, 2]) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * max_detuning, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) def eigs(t): schedule_exp_linear(t, t_max) eigval, eigvec = eq.eig(which='S', k=k) return eigval - eigval[0], eigvec if tails_graph is not None: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver, rydberg]) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver, rydberg], cost_hamiltonian=cost, IS_subspace=True) else: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver]) ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) print('starting evolution') states, data = ad.run(t_max, schedule_exp_linear, num=int(60 * t_max), method='odeint', full_output=True) print('finished evolution') times = data['t'] start_index = len(times) // 2 times = times[start_index:] states = states[start_index:] populations = np.zeros((len(times), k)) energies = np.zeros((len(times), k)) for (i, time) in enumerate(times): print(i) eigval, eigvecs = eigs(time) populations[i] = (np.abs(eigvecs @ states[i])**2).flatten() energies[i] = eigval / (2 * np.pi) populations = np.log10(populations) from matplotlib.collections import LineCollection fig, ax = plt.subplots() norm = plt.Normalize(-5, np.max(populations)) for i in range(energies.shape[1]): points = np.array([times, energies[:, i]]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) lc = LineCollection(segments, cmap='coolwarm', norm=norm) # Set the values used for colormapping lc.set_array(populations[:-1, i]) lc.set_linewidth(1) line = ax.add_collection(lc) cbar = fig.colorbar(line, ax=ax) cbar.ax.set_ylabel(r'$\log_{10}(\rm{population})$') ax.set_xlim(np.min(times), np.max(times)) ax.set_xlabel(r'Time ($\mu$s)') ax.set_ylabel(r'Eigenenergy (MHz)') ax.set_ylim(np.min(energies) - .3, np.max(energies)) # ax.annotate(r'$r_{0\rightarrow j} = \sum_\mu |\langle j |c_\mu |0\rangle |^2$', xy=(0.4, 0.1), xycoords='data') plt.show() fig, ax = plt.subplots() deltas = np.zeros(len(times)) print(times) for (i, time) in enumerate(times): schedule_exp_linear(time, t_max) deltas[i] = cost.energies[0] / (2 * np.pi) print(deltas) norm = plt.Normalize(-5, np.max(populations)) for i in range(energies.shape[1]): points = np.array([deltas, energies[:, i]]).T.reshape(-1, 1, 2) segments = np.concatenate([points[:-1], points[1:]], axis=1) lc = LineCollection(segments, cmap='coolwarm', norm=norm) # Set the values used for colormapping lc.set_array(populations[:-1, i]) lc.set_linewidth(1) line = ax.add_collection(lc) cbar = fig.colorbar(line, ax=ax) cbar.ax.set_ylabel(r'$\log_{10}(\rm{population})$') ax.set_xlim(np.max(deltas), np.min(deltas)) ax.set_xlabel(r'$\Delta$ (MHz)') ax.set_ylabel(r'Eigenenergy (MHz)') ax.set_ylim(np.min(energies) - .3, np.max(energies)) # ax.annotate(r'$r_{0\rightarrow j} = \sum_\mu |\langle j |c_\mu |0\rangle |^2$', xy=(0.4, 0.1), xycoords='data') plt.show() fig, ax = plt.subplots(3, 5) probs = np.abs(eigvecs)**2 print(probs[:, :10]) for l in range(k): i = l // 5 j = l % 5 layout = grid.copy().flatten().astype(float) layout[layout == 0] = -5 layout[layout == 1] = 0 layout_temp = layout.copy() for m in range(probs.shape[1]): layout_temp[layout == 0] = layout_temp[ layout == 0] + (1 - graph.independent_sets[m]) * probs[l, m] ax[i][j].imshow(layout_temp.reshape(grid.shape)) ax[i][j].set_axis_off() ax[i][j].text(-0.1, 1.05, '$\lambda${}'.format(str(l)), transform=ax[i][j].transAxes, size=10, weight='bold') plt.show()
def find_ratio(tails_graph, graph, tf, graph_index=None, size=None): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) # print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) # print('Starting rydberg') if tails_graph is not None: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (2 * np.pi * (-(11 + 15) / T * t + 15), ) driver.energies = (2 * np.pi * 2 * amplitude, ) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) # print(t, cost.energies) # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) # print(driver.hamiltonian) if tails_graph is None: ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver], cost_hamiltonian=cost, IS_subspace=True) else: ad = SimulateAdiabatic(graph=graph, hamiltonian=[cost, driver, rydberg], cost_hamiltonian=cost, IS_subspace=True) # print('Starting evolution') ars = [] probs = [] for i in range(len(tf)): states, data = ad.run(tf[i], schedule_exp_linear, num=int(20 * tf[i]), method='odeint', full_output=False) cost.energies = (1, ) ar = cost.approximation_ratio(states[-1]) prob = cost.optimum_overlap(states[-1]) # np.savez_compressed('{}x{}_{}_{}.npz'.format(size, size, graph_index, i), state=states[-1]) print(tf[i], ar, prob) ars.append(ar) probs.append(prob) return ars, probs
def find_gap(graph, tails_graph, k=2, verbose=False): n_points = 7 times_exp = 2**np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[4] print('Starting cost') cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) if tails_graph is not None: print('Starting rydberg') rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 max_detuning = np.max(pulse[:, 2]) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * max_detuning, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) def gap(t): t = t[0] t = t * t_max schedule(t, t_max) eigval, eigvec = eq.eig(which='S', k=k) if verbose: print(np.abs(eigval[1] - eigval[0]), t / t_max) # print(t/t_max, np.abs(eigval[1] - eigval[0])) return np.abs(eigval[1] - eigval[0]) if tails_graph is None: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver]) else: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver, rydberg]) # Do minimization schedule = schedule_exp_linear if tails_graph is None: # Previously .67 upper = 0.8 # Previously .55 lower = .55 init = np.array([.7]) else: # Default: .77 upper = 0.7860824 # 0.77 lower = 0.7856305 # 0.8161#.77#.6 # Default: .71 init = np.array([0.7860309]) # 0.74 print('Starting gap') res_linear = scipy.optimize.minimize(gap, init, bounds=[(lower, upper)], method='L-BFGS-B') terminate = False while res_linear.x[0] == upper and not terminate: upper -= .01 if upper <= lower: upper = .95 res_linear = scipy.optimize.minimize(gap, init, bounds=[(lower, upper)], tol=1e-2) return res_linear.fun, res_linear.x[0]
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 find_ground_first_excited(graph, tails_graph, t, k=2): n_points = 7 times_exp = 2**np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[4] print('Starting cost') cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) print('Starting driver') driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) if tails_graph is not None: print('Starting rydberg') rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 max_detuning = np.max(pulse[:, 2]) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * max_detuning, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) if tails_graph is None: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver]) else: eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver, rydberg]) # Do minimization schedule = schedule_exp_linear t = t * t_max schedule(t, t_max) eigval, eigvec = eq.eig(which='S', k=k) print(eigval[0], eigval[1]) return eigval, eigvec
def track_eigenstate_composition(graph, tails_graph, num=1): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) # print('Starting driver') n_points = 7 times_exp = 2 ** np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[4] driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) # print('Starting rydberg') if tails_graph is not None: rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi,)) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude,) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T),) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude,) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312,) cost.energies = (2 * np.pi * 15,) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2),) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]),) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312,) cost.energies = (-2 * np.pi * 11,) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312,) cost.energies = (2 * np.pi * 15,) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2,) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15),) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312,) cost.energies = (-2 * np.pi * 11,) # print(t, cost.energies) # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) def eigs(t): schedule_exp_linear(t * t_max, t_max) if num == 0: eigval, eigvec = eq.eig(which='S', k=num+2) else: eigval, eigvec = eq.eig(which='S', k=num+1) return eigval, eigvec # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) # print(driver.hamiltonian) if tails_graph is not None: eq = schrodinger_equation.SchrodingerEquation(hamiltonians=[cost, driver, rydberg]) else: eq = schrodinger_equation.SchrodingerEquation(hamiltonians=[cost, driver]) #gap, loc = find_gap(graph, tails_graph) loc = 0.6403615396636326 fig, ax = plt.subplots(1, num+2, sharex=True) print('Beginning computation') print(graph.mis_size) colors = ['blue', 'green', 'navy', 'orange', 'firebrick', 'purple', 'magenta', 'cornflowerblue', 'teal', 'grey', 'cyan', 'limegreen', 'red', 'yellow', 'pink', 'orangered', 'salmon', 'violet'] for (i, t) in enumerate(np.linspace(.6, .7, 50)): print(i) eigval, eigvec = eigs(t) ax[0].scatter(t, np.abs(eigval[0] - eigval[1]), color='k') for n in range(num + 1): if i == 0: ax[n+1].vlines(loc, 0, 1) vec = np.abs(eigvec[n])**2 for j in range(graph.mis_size+1): population = np.sum(vec*(np.isclose(np.sum(1-graph.independent_sets, axis=1),j))) ax[n+1].scatter(t, population, color=colors[j]) ax[0].set_xlabel(r'$t/T$') ax[1].set_xlabel(r'$t/T$') ax[1].set_ylabel(r'Gap') ax[0].set_ylabel(r'Population') for j in range(graph.mis_size): ax[0].scatter([],[],color=colors[j], label='IS size '+str(j)) ax[0].legend() plt.show()
def visualize_low_energy_subspace(graph, tails_graph, k=5): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) # print('Starting driver') n_points = 7 times_exp = 2**np.linspace(-2.5, 4.5 / 6 * (n_points - 1) - 2.5, n_points) + .312 * 2 t_max = times_exp[4] driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) # print('Starting rydberg') rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True, energies=(2 * np.pi, )) pulse = np.loadtxt('for_AWG_{}.000000.txt'.format(6)) t_pulse_max = np.max(pulse[:, 0]) - 2 * 0.312 def schedule(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (2 * np.pi * (-(11 + 15) / T * t + 15), ) driver.energies = (2 * np.pi * 2 * amplitude, ) def schedule_old(t, T): # Linear ramp on the detuning, experiment-like ramp on the driver k = 50 a = .95 b = 3.1 x = t / T amplitude = ( -1 / (1 + np.e ** (k * (x - a))) ** b - 1 / (1 + np.e ** (-k * (x - (1 - a)))) ** b + 1) / \ (-1 / ((1 + np.e ** (k * (1 / 2 - a))) ** b) - 1 / ( (1 + np.e ** (-k * (1 / 2 - (1 - a)))) ** b) + 1) cost.energies = (-2 * np.pi * 11 * 2 * (1 / 2 - t / T), ) # (2 * np.pi * (-(11 + 15) / T * t + 15),) driver.energies = (2 * np.pi * 2 * amplitude, ) # (2 * np.pi * 2 * amplitude,) def schedule_exp_optimized(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: t_pulse = (t - 0.312) / (T - 2 * 0.312) * t_pulse_max + 0.312 driver.energies = ( 2 * np.pi * np.interp(t_pulse, pulse[:, 0], pulse[:, 1] / 2), ) cost.energies = (2 * np.pi * np.interp(t_pulse, pulse[:, 0], -pulse[:, 2]), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) # print(t, cost.energies) def schedule_exp_linear(t, T): if t < .312: driver.energies = (2 * np.pi * 2 * t / .312, ) cost.energies = (2 * np.pi * 15, ) elif .312 <= t <= T - .312: driver.energies = (2 * np.pi * 2, ) cost.energies = (2 * np.pi * (-(11 + 15) / (T - 2 * .312) * (t - .312) + 15), ) else: driver.energies = (2 * np.pi * 2 * (T - t) / .312, ) cost.energies = (-2 * np.pi * 11, ) # print(t, cost.energies) # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) def gap(t): schedule_exp_linear(t * t_max, t_max) eigval, eigvec = eq.eig(which='S', k=k) return np.abs(eigval - eigval[0]), eigvec # Uncomment this to print the schedule at t=0 # schedule(0, 1) # print(cost.hamiltonian*2*np.pi) # print(driver.hamiltonian) eq = schrodinger_equation.SchrodingerEquation( hamiltonians=[cost, driver, rydberg]) fig = plt.figure(tight_layout=True) k_cutoff = 5 gs = gridspec.GridSpec(k_cutoff, k_cutoff) ax = fig.add_subplot(gs[:, 0:k_cutoff - 1]) num = 50 print('beginning computation') for (i, t) in enumerate(np.linspace(.5, .98, num)): print(i) g, eigvec = gap(t) print(g) if i == num - 1: probs = np.abs(eigvec)**2 for l in range(k_cutoff): layout = grid.copy().flatten().astype(float) layout[layout == 0] = -5 layout[layout == 1] = 0 layout_temp = layout.copy() ax_im = fig.add_subplot(gs[k_cutoff - l - 1, -1]) for j in range(probs.shape[1]): layout_temp[layout == 0] = layout_temp[layout == 0] + ( 1 - graph.independent_sets[j]) * probs[l, j] ax_im.imshow(layout_temp.reshape(grid.shape)) ax_im.set_axis_off() ax.scatter(np.ones(len(g)) * t, g, s=5, color='navy') ax.set_xlabel(r'$t/T$') ax.set_ylabel(r'Eigenenergy ($\Omega_{\max} = 1$)') plt.show()
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)
i = tools.nary_to_int(np.roll(i, j)) state[i] = 1 i = 1 - np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]) i = tools.nary_to_int(np.roll(i, j)) state[i] = 1 print(np.argwhere(state != 0)) state = state / np.linalg.norm(state) """where_optimal = degeneracy(cost) state[where_optimal] = 10 state = state/np.linalg.norm(state)""" # state = generate_inital_state_cf(graph, diff=2, verbose=True) # state = generate_initial_state_legal_gw(graph) cost = hamiltonian.HamiltonianMaxCut(graph, cost_function=True) # state = State(state[:, np.newaxis], is_ket=True, graph=graph) driver = hamiltonian.HamiltonianDriver() qaoa = qaoa.SimulateQAOA(graph=graph, hamiltonian=[], cost_hamiltonian=cost) # print('oo', cost.optimum_overlap(state)) print('cf', cost.cost_function(state)) print('maxcut', np.max(cost.hamiltonian)) for p in range(2, 10): max_result = 0 print(p) hamiltonian = [driver] + [cost, driver] * p qaoa.hamiltonian = hamiltonian """num = 20 gammas = np.linspace(0, np.pi/2, num) betas = np.linspace(0, np.pi, num) results = np.zeros((num,num)) for g in range(len(gammas)): print(g)
def test_logical_codes(self): # Construct a known graph G = nx.random_regular_graph(1, 2) for e in G.edges: G[e[0]][e[1]]['weight'] = 1 nx.draw_networkx(G) # Uncomment to visualize graph # plt.draw_graph(G) G = Graph(G) print('No logical encoding:') hc_qubit = hamiltonian.HamiltonianMIS(G) hamiltonians = [hc_qubit, hamiltonian.HamiltonianDriver()] sim = qaoa.SimulateQAOA(G, cost_hamiltonian=hc_qubit, hamiltonian=hamiltonians, noise_model=None, noise=noises) # Set the default variational operators results = sim.find_parameters_brute(n=10) self.assertTrue(np.isclose(results['approximation_ratio'], 1)) print('Two qubit code:') hc_two_qubit_code = hamiltonian.HamiltonianMIS(G, code=two_qubit_code) hamiltonians = [ hc_two_qubit_code, hamiltonian.HamiltonianDriver(code=two_qubit_code) ] sim_code = qaoa.SimulateQAOA(G, code=two_qubit_code, cost_hamiltonian=hc_two_qubit_code, hamiltonian=hamiltonians) # Find optimal parameters via brute force search sim_code.find_parameters_brute(n=10) self.assertTrue(np.isclose(results['approximation_ratio'], 1)) print('Two qubit code with penalty:') # Set the default variational operators with a penalty Hamiltonian hc_qubit = hamiltonian.HamiltonianMIS(G, code=two_qubit_code) hamiltonians = [ hc_qubit, hamiltonian.HamiltonianBookatzPenalty(code=two_qubit_code), hamiltonian.HamiltonianDriver(code=two_qubit_code) ] sim_penalty = qaoa.SimulateQAOA(G, cost_hamiltonian=hc_qubit, hamiltonian=hamiltonians, code=two_qubit_code) # You should get the same thing results = sim_penalty.find_parameters_brute(n=10) self.assertTrue(np.isclose(results['approximation_ratio'], 1)) print('Jordan-Farhi-Shor code:') hc_jordan_farhi_shor = hamiltonian.HamiltonianMIS( G, code=jordan_farhi_shor) hamiltonians = [ hc_jordan_farhi_shor, hamiltonian.HamiltonianDriver(code=jordan_farhi_shor) ] sim_code = qaoa.SimulateQAOA(G, code=jordan_farhi_shor, cost_hamiltonian=hc_jordan_farhi_shor, hamiltonian=hamiltonians) sim_code.find_parameters_brute(n=10) self.assertTrue(np.isclose(results['approximation_ratio'], 1))