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
Exemple #2
0
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()
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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)
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
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
Exemple #10
0
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)
Exemple #11
0
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))
Exemple #12
0
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
Exemple #13
0
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
Exemple #14
0
    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:
Exemple #15
0
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
Exemple #17
0
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
Exemple #18
0
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()
Exemple #19
0
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