def find_fidelity(graph, critical_time): cost = hamiltonian.HamiltonianMIS(graph, IS_subspace=True) driver = hamiltonian.HamiltonianDriver(IS_subspace=True, graph=graph) rydberg = hamiltonian.HamiltonianRydberg(tails_graph, graph, IS_subspace=True) 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 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 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 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 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_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 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 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 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): 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()